├── audioplayer
├── ios
│ ├── Assets
│ │ └── .gitkeep
│ ├── Classes
│ │ ├── AudioplayerPlugin.h
│ │ └── AudioplayerPlugin.m
│ ├── .gitignore
│ └── audioplayer.podspec
├── android
│ ├── settings.gradle
│ ├── gradle.properties
│ ├── .gitignore
│ ├── src
│ │ └── main
│ │ │ └── AndroidManifest.xml
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ └── build.gradle
├── macos
│ ├── Classes
│ │ ├── SwiftAudioplayerPlugin.swift
│ │ ├── AudioplayerPlugin.h
│ │ └── AudioplayerPlugin.m
│ ├── Flutter
│ │ ├── GeneratedPluginRegistrant.swift
│ │ └── ephemeral
│ │ │ ├── Flutter-Generated.xcconfig
│ │ │ └── flutter_export_environment.sh
│ └── audioplayer.podspec
├── .gitignore
├── screenshot.png
├── pubspec.yaml
├── LICENSE
├── CHANGELOG.md
└── README.md
├── android
├── speech
│ ├── .gitignore
│ ├── .settings
│ │ └── org.eclipse.buildship.core.prefs
│ ├── src
│ │ └── main
│ │ │ ├── res
│ │ │ └── values
│ │ │ │ └── strings.xml
│ │ │ ├── jniLibs
│ │ │ └── arm64-v8a
│ │ │ │ ├── libvad.dnn.so
│ │ │ │ └── libBaiduSpeechSDK.so
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ └── xwh
│ │ │ └── lib
│ │ │ └── speech
│ │ │ └── AsrPlugin.java
│ ├── libs
│ │ └── bdasr_V3_20190515_c9eed5d.jar
│ ├── .classpath
│ ├── .project
│ ├── proguard-rules.pro
│ └── build.gradle
├── .settings
│ └── org.eclipse.buildship.core.prefs
├── app
│ ├── keystore.jks
│ ├── .settings
│ │ └── org.eclipse.buildship.core.prefs
│ ├── src
│ │ ├── main
│ │ │ ├── res
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ └── launcher_bg.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── xml
│ │ │ │ │ └── network_security_config.xml
│ │ │ │ ├── values
│ │ │ │ │ └── styles.xml
│ │ │ │ └── drawable
│ │ │ │ │ └── launch_background.xml
│ │ │ ├── kotlin
│ │ │ │ └── xwh
│ │ │ │ │ └── flutter
│ │ │ │ │ └── music
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── AndroidManifest.xml
│ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ └── profile
│ │ │ └── AndroidManifest.xml
│ ├── .classpath
│ ├── .project
│ └── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── .project
├── settings.gradle
└── build.gradle
├── ios
├── Runner
│ ├── Runner-Bridging-Header.h
│ ├── Assets.xcassets
│ │ ├── LaunchImage.imageset
│ │ │ ├── LaunchImage.png
│ │ │ ├── LaunchImage@2x.png
│ │ │ ├── LaunchImage@3x.png
│ │ │ ├── README.md
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ ├── Icon-App-20x20@1x.png
│ │ │ ├── Icon-App-20x20@2x.png
│ │ │ ├── Icon-App-20x20@3x.png
│ │ │ ├── Icon-App-29x29@1x.png
│ │ │ ├── Icon-App-29x29@2x.png
│ │ │ ├── Icon-App-29x29@3x.png
│ │ │ ├── Icon-App-40x40@1x.png
│ │ │ ├── Icon-App-40x40@2x.png
│ │ │ ├── Icon-App-40x40@3x.png
│ │ │ ├── Icon-App-60x60@2x.png
│ │ │ ├── Icon-App-60x60@3x.png
│ │ │ ├── Icon-App-76x76@1x.png
│ │ │ ├── Icon-App-76x76@2x.png
│ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ ├── Icon-App-83.5x83.5@2x.png
│ │ │ └── Contents.json
│ ├── AppDelegate.swift
│ ├── Base.lproj
│ │ ├── Main.storyboard
│ │ └── LaunchScreen.storyboard
│ └── Info.plist
├── Flutter
│ ├── Debug.xcconfig
│ ├── Release.xcconfig
│ ├── Flutter.podspec
│ └── AppFrameworkInfo.plist
├── Runner.xcodeproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── Podfile
└── Podfile.lock
├── fonts
└── iconfont.ttf
├── images
├── music_2.jpg
└── placeholder_play_list.jpg
├── screenshot
├── 03_mv.jpg
├── player.jpg
├── 05_artists.jpg
├── 06_player.jpg
├── 07_player.jpg
├── 08_player.jpg
├── 09_setting.jpg
├── 10_search.jpg
├── fullscreen.jpg
├── 01_home_page.jpg
├── 02_play_list.jpg
├── FlutterMusic.png
├── qr_flutter_music.png
└── 04_playlist_detail.jpg
├── test
├── async_test.dart
└── widget_test.dart
├── lib
├── model
│ ├── song.dart
│ ├── speech_manager.dart
│ ├── video_controller.dart
│ ├── play_list.dart
│ ├── color_provider.dart
│ ├── song_util.dart
│ └── Lyric.dart
├── utils
│ ├── shared_preference_util.dart
│ ├── screen_size.dart
│ ├── toast_util.dart
│ ├── my_icons.dart
│ ├── network_util.dart
│ ├── navigator_util.dart
│ ├── colors.dart
│ ├── file_util.dart
│ └── http_util.dart
├── widget
│ ├── loading_container.dart
│ ├── blur_widget.dart
│ ├── text_icon.dart
│ ├── text_icon_withbg.dart
│ ├── tap_anim_widget.dart
│ ├── current_play_list.dart
│ ├── song_item_tile.dart
│ ├── favorite_icon_playlist.dart
│ ├── play_list_item.dart
│ ├── gradient_text.dart
│ ├── song_item_grid.dart
│ ├── song_item_text.dart
│ ├── mv_item.dart
│ ├── music_progress_bar_2.dart
│ ├── music_progress_bar.dart
│ ├── my_icon_button.dart
│ ├── search_bar.dart
│ ├── wave_widget.dart
│ └── floating_player.dart
├── pages
│ ├── song_list.dart
│ ├── favorite_music.dart
│ ├── rank_song_list.dart
│ ├── mv_tab_page.dart
│ ├── mv_player_page.dart
│ ├── rank_page.dart
│ ├── favorite_page.dart
│ ├── play_list_page.dart
│ ├── mv_page.dart
│ ├── tabs_bottom.dart
│ ├── artist_list_page.dart
│ ├── play_list_tab_page.dart
│ ├── history_page.dart
│ ├── home_page.dart
│ └── artist_detail.dart
├── dao
│ ├── music_db.dart
│ ├── music_db_playlist.dart
│ ├── music_db_favorite.dart
│ ├── music_db_history.dart
│ └── api_cache.dart
├── test
│ ├── test_positioned_1.dart
│ ├── test_positioned_2.dart
│ ├── test_scroll_position.dart
│ └── video_demo.dart
└── main.dart
├── .metadata
├── bugs.md
├── .gitignore
└── pubspec.yaml
/audioplayer/ios/Assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/android/speech/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/audioplayer/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'audioplayer'
2 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
--------------------------------------------------------------------------------
/audioplayer/macos/Classes/SwiftAudioplayerPlugin.swift:
--------------------------------------------------------------------------------
1 | ../../ios/Classes/SwiftAudioplayerPlugin.swift
--------------------------------------------------------------------------------
/fonts/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/fonts/iconfont.ttf
--------------------------------------------------------------------------------
/images/music_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/images/music_2.jpg
--------------------------------------------------------------------------------
/screenshot/03_mv.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/screenshot/03_mv.jpg
--------------------------------------------------------------------------------
/screenshot/player.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/screenshot/player.jpg
--------------------------------------------------------------------------------
/android/.settings/org.eclipse.buildship.core.prefs:
--------------------------------------------------------------------------------
1 | connection.project.dir=
2 | eclipse.preferences.version=1
3 |
--------------------------------------------------------------------------------
/android/app/keystore.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/android/app/keystore.jks
--------------------------------------------------------------------------------
/audioplayer/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .dart_tool/
3 |
4 | .packages
5 | .pub/
6 |
7 | build/
8 |
9 | .metadata
--------------------------------------------------------------------------------
/screenshot/05_artists.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/screenshot/05_artists.jpg
--------------------------------------------------------------------------------
/screenshot/06_player.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/screenshot/06_player.jpg
--------------------------------------------------------------------------------
/screenshot/07_player.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/screenshot/07_player.jpg
--------------------------------------------------------------------------------
/screenshot/08_player.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/screenshot/08_player.jpg
--------------------------------------------------------------------------------
/screenshot/09_setting.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/screenshot/09_setting.jpg
--------------------------------------------------------------------------------
/screenshot/10_search.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/screenshot/10_search.jpg
--------------------------------------------------------------------------------
/screenshot/fullscreen.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/screenshot/fullscreen.jpg
--------------------------------------------------------------------------------
/android/app/.settings/org.eclipse.buildship.core.prefs:
--------------------------------------------------------------------------------
1 | connection.project.dir=..
2 | eclipse.preferences.version=1
3 |
--------------------------------------------------------------------------------
/audioplayer/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/audioplayer/screenshot.png
--------------------------------------------------------------------------------
/screenshot/01_home_page.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/screenshot/01_home_page.jpg
--------------------------------------------------------------------------------
/screenshot/02_play_list.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/screenshot/02_play_list.jpg
--------------------------------------------------------------------------------
/screenshot/FlutterMusic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/screenshot/FlutterMusic.png
--------------------------------------------------------------------------------
/android/speech/.settings/org.eclipse.buildship.core.prefs:
--------------------------------------------------------------------------------
1 | connection.project.dir=..
2 | eclipse.preferences.version=1
3 |
--------------------------------------------------------------------------------
/android/speech/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Speech
3 |
4 |
--------------------------------------------------------------------------------
/images/placeholder_play_list.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/images/placeholder_play_list.jpg
--------------------------------------------------------------------------------
/screenshot/qr_flutter_music.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/screenshot/qr_flutter_music.png
--------------------------------------------------------------------------------
/screenshot/04_playlist_detail.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/screenshot/04_playlist_detail.jpg
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/audioplayer/ios/Classes/AudioplayerPlugin.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface AudioplayerPlugin : NSObject
4 | @end
5 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 |
3 | android.enableR8=true
4 |
5 |
6 | android.enableJetifier=true
7 | android.useAndroidX=true
--------------------------------------------------------------------------------
/audioplayer/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.enableR8=true
3 | android.useAndroidX=true
4 | android.enableJetifier=true
5 |
--------------------------------------------------------------------------------
/android/speech/libs/bdasr_V3_20190515_c9eed5d.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/android/speech/libs/bdasr_V3_20190515_c9eed5d.jar
--------------------------------------------------------------------------------
/audioplayer/android/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 |
--------------------------------------------------------------------------------
/audioplayer/macos/Classes/AudioplayerPlugin.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface AudioplayerPlugin : NSObject
4 | @end
5 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/launcher_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/android/app/src/main/res/mipmap-hdpi/launcher_bg.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/speech/src/main/jniLibs/arm64-v8a/libvad.dnn.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/android/speech/src/main/jniLibs/arm64-v8a/libvad.dnn.so
--------------------------------------------------------------------------------
/test/async_test.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_test/flutter_test.dart';
2 |
3 |
4 | void main() {
5 |
6 | test('test hello!', (){
7 | print('hello');
8 | });
9 | }
--------------------------------------------------------------------------------
/audioplayer/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/android/speech/src/main/jniLibs/arm64-v8a/libBaiduSpeechSDK.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/android/speech/src/main/jniLibs/arm64-v8a/libBaiduSpeechSDK.so
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xwh817/flutter_music_player/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/android/app/src/main/res/xml/network_security_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/audioplayer/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
6 |
--------------------------------------------------------------------------------
/lib/model/song.dart:
--------------------------------------------------------------------------------
1 | class Song{
2 | Song({
3 | this.id,
4 | this.name,
5 | this.artist
6 | });
7 |
8 | BigInt id;
9 | String name;
10 | String artist;
11 | int album;
12 | int duration;
13 | String cover;
14 | String url;
15 | BigInt lastPlayTime;
16 | }
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
7 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 2d2a1ffec95cc70a3218872a2cd3f8de4933c42f
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/audioplayer/macos/Flutter/GeneratedPluginRegistrant.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | import FlutterMacOS
6 | import Foundation
7 |
8 | import audioplayer
9 |
10 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
11 | AudioplayerPlugin.register(with: registry.registrar(forPlugin: "AudioplayerPlugin"))
12 | }
13 |
--------------------------------------------------------------------------------
/android/app/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/speech/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/audioplayer/macos/Flutter/ephemeral/Flutter-Generated.xcconfig:
--------------------------------------------------------------------------------
1 | // This is a generated file; do not edit or check into version control.
2 | FLUTTER_ROOT=/Users/rxlabz/dev/tools/flutter
3 | FLUTTER_APPLICATION_PATH=/Users/rxlabz/dev/projects/audioplayer2/audioplayer/audioplayer
4 | FLUTTER_BUILD_DIR=build
5 | FLUTTER_FRAMEWORK_DIR=/Users/rxlabz/dev/tools/flutter/bin/cache/artifacts/engine/darwin-x64
6 | FLUTTER_BUILD_NAME=0.6.0
7 | FLUTTER_BUILD_NUMBER=0.6.0
8 |
--------------------------------------------------------------------------------
/lib/utils/shared_preference_util.dart:
--------------------------------------------------------------------------------
1 | import 'package:shared_preferences/shared_preferences.dart';
2 |
3 | class SharedPreferenceUtil {
4 | static SharedPreferences instance;
5 |
6 | /// SharedPreferences的初始化是异步的,很多地方要同步的方式使用很麻烦。
7 | /// 这里在启动时统一初始化一次,后面直接用。
8 | static init() async {
9 | instance = await SharedPreferences.getInstance();
10 | }
11 |
12 | static SharedPreferences getInstance() {
13 | return instance;
14 | }
15 |
16 |
17 | }
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/lib/utils/screen_size.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/widgets.dart';
2 |
3 | class ScreenSize {
4 | static double width;
5 | static double height;
6 |
7 | static void getScreenSize(BuildContext context) {
8 | MediaQueryData mediaData = MediaQuery.of(context);
9 | final size = mediaData.size;
10 | width = size.width;
11 | height = size.height;
12 |
13 | double dp = mediaData.devicePixelRatio;
14 | print('屏幕宽高: ${size.width} * ${size.height}, 屏幕密度:$dp ');
15 | }
16 |
17 |
18 | }
--------------------------------------------------------------------------------
/android/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | android
4 | Project android created by Buildship.
5 |
6 |
7 |
8 |
9 | org.eclipse.buildship.core.gradleprojectbuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.buildship.core.gradleprojectnature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/audioplayer/macos/Flutter/ephemeral/flutter_export_environment.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # This is a generated file; do not edit or check into version control.
3 | export "FLUTTER_ROOT=/Users/rxlabz/dev/tools/flutter"
4 | export "FLUTTER_APPLICATION_PATH=/Users/rxlabz/dev/projects/audioplayer2/audioplayer/audioplayer"
5 | export "FLUTTER_BUILD_DIR=build"
6 | export "FLUTTER_FRAMEWORK_DIR=/Users/rxlabz/dev/tools/flutter/bin/cache/artifacts/engine/darwin-x64"
7 | export "FLUTTER_BUILD_NAME=0.6.0"
8 | export "FLUTTER_BUILD_NUMBER=0.6.0"
9 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | -
8 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':speech'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/audioplayer/ios/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .vagrant/
3 | .sconsign.dblite
4 | .svn/
5 |
6 | .DS_Store
7 | *.swp
8 | profile
9 |
10 | DerivedData/
11 | build/
12 | GeneratedPluginRegistrant.h
13 | GeneratedPluginRegistrant.m
14 |
15 | .generated/
16 |
17 | *.pbxuser
18 | *.mode1v3
19 | *.mode2v3
20 | *.perspectivev3
21 |
22 | !default.pbxuser
23 | !default.mode1v3
24 | !default.mode2v3
25 | !default.perspectivev3
26 |
27 | xcuserdata
28 |
29 | *.moved-aside
30 |
31 | *.pyc
32 | *sync/
33 | Icon?
34 | .tags*
35 |
36 | /Flutter/Generated.xcconfig
37 | /Flutter/flutter_export_environment.sh
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/xwh/flutter/music/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package xwh.flutter.music
2 |
3 | import android.os.Bundle
4 |
5 | import io.flutter.app.FlutterActivity
6 | import io.flutter.plugins.GeneratedPluginRegistrant
7 | import xwh.lib.speech.AsrPlugin
8 |
9 | class MainActivity: FlutterActivity() {
10 | override fun onCreate(savedInstanceState: Bundle?) {
11 | super.onCreate(savedInstanceState)
12 | GeneratedPluginRegistrant.registerWith(this)
13 |
14 | this.registerMyPlugins()
15 | }
16 |
17 |
18 | // 注册自定义的插件
19 | private fun registerMyPlugins() {
20 | AsrPlugin.registerWith(registrarFor("xwh.lib.speech.AsrPlugin"))
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/audioplayer/ios/Classes/AudioplayerPlugin.m:
--------------------------------------------------------------------------------
1 | #import "AudioplayerPlugin.h"
2 | #if __has_include()
3 | #import
4 | #else
5 | // Support project import fallback if the generated compatibility header
6 | // is not copied when this plugin is created as a library.
7 | // https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816
8 | #import "audioplayer-Swift.h"
9 | #endif
10 |
11 | @implementation AudioplayerPlugin
12 | + (void)registerWithRegistrar:(NSObject*)registrar {
13 | [SwiftAudioplayerPlugin registerWithRegistrar:registrar];
14 | }
15 | @end
16 |
--------------------------------------------------------------------------------
/audioplayer/macos/Classes/AudioplayerPlugin.m:
--------------------------------------------------------------------------------
1 | #import "AudioplayerPlugin.h"
2 | #if __has_include()
3 | #import
4 | #else
5 | // Support project import fallback if the generated compatibility header
6 | // is not copied when this plugin is created as a library.
7 | // https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816
8 | #import "audioplayer-Swift.h"
9 | #endif
10 |
11 | @implementation AudioplayerPlugin
12 | + (void)registerWithRegistrar:(NSObject *)registrar {
13 | [SwiftAudioplayerPlugin registerWithRegistrar:registrar];
14 | }
15 | @end
16 |
--------------------------------------------------------------------------------
/audioplayer/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: audioplayer
2 | description: A Flutter audio plugin (Swift/Java) to play remote or local audio files (ios, android, macos)
3 | version: 0.8.1
4 | author: Erick Ghaumez
5 | homepage: https://github.com/rxlabz/audioplayer
6 |
7 | environment:
8 | sdk: ">=2.0.0 <3.0.0"
9 | flutter: ">=1.10.0"
10 |
11 | dependencies:
12 | flutter:
13 | sdk: flutter
14 |
15 | flutter:
16 | plugin:
17 | platforms:
18 | android:
19 | package: bz.rxla.audioplayer
20 | pluginClass: AudioplayerPlugin
21 | ios:
22 | pluginClass: AudioplayerPlugin
23 | macos:
24 | pluginClass: AudioplayerPlugin
25 |
--------------------------------------------------------------------------------
/android/app/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | app
4 | Project app created by Buildship.
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.buildship.core.gradleprojectbuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.jdt.core.javanature
21 | org.eclipse.buildship.core.gradleprojectnature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/lib/model/speech_manager.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/services.dart';
2 |
3 | class AsrManager {
4 | static const MethodChannel _channel = const MethodChannel('speech_plugin');
5 |
6 | /// 初始化
7 | static Future init() async {
8 | return await _channel.invokeMethod('init');
9 | }
10 |
11 | /// 开始录音
12 | static Future start({Map params}) async {
13 | return await _channel.invokeMethod('start', params ?? {});
14 | }
15 |
16 | /// 停止录音
17 | static Future stop() async {
18 | return await _channel.invokeMethod('stop');
19 | }
20 |
21 | /// 取消录音
22 | static Future cancel() async {
23 | return await _channel.invokeMethod('cancel');
24 | }
25 | }
--------------------------------------------------------------------------------
/android/speech/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | speech
4 | Project speech created by Buildship.
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.buildship.core.gradleprojectbuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.jdt.core.javanature
21 | org.eclipse.buildship.core.gradleprojectnature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/lib/utils/toast_util.dart:
--------------------------------------------------------------------------------
1 |
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter_music_player/model/color_provider.dart';
5 | import 'package:fluttertoast/fluttertoast.dart';
6 | import 'package:provider/provider.dart';
7 |
8 | class ToastUtil {
9 | static showToast(BuildContext context, String msg, {toastLength= Toast.LENGTH_SHORT, gravity: ToastGravity.CENTER}) {
10 | Fluttertoast.showToast(
11 | msg: msg,
12 | toastLength: toastLength,
13 | gravity: gravity,
14 | backgroundColor: Provider.of(context, listen: false).getCurrentColor().withAlpha(200),
15 | textColor: Colors.white,
16 | fontSize: 14.0);
17 | }
18 | }
--------------------------------------------------------------------------------
/audioplayer/android/build.gradle:
--------------------------------------------------------------------------------
1 | group 'bz.rxla.audioplayer'
2 | version '1.0'
3 |
4 | buildscript {
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 |
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:4.1.0'
12 | }
13 | }
14 |
15 | rootProject.allprojects {
16 | repositories {
17 | google()
18 | jcenter()
19 | }
20 | }
21 |
22 | apply plugin: 'com.android.library'
23 |
24 | android {
25 | compileSdkVersion 30
26 |
27 | defaultConfig {
28 | minSdkVersion 16
29 | }
30 | lintOptions {
31 | disable 'InvalidPackage'
32 | }
33 | }
34 |
35 | dependencies {
36 | implementation 'com.android.support:support-annotations:28.0.0'
37 | }
38 |
--------------------------------------------------------------------------------
/lib/widget/loading_container.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | ///加载进度条组件
4 | class LoadingContainer extends StatelessWidget {
5 | final Widget child;
6 | final bool isLoading;
7 | final bool cover;
8 |
9 | const LoadingContainer(
10 | {Key key,
11 | @required this.isLoading,
12 | this.cover = false,
13 | @required this.child})
14 | : super(key: key);
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | return !cover
19 | ? !isLoading ? child : _loadingView
20 | : Stack(
21 | children: [child, isLoading ? _loadingView : Container()],
22 | );
23 | }
24 |
25 | Widget get _loadingView {
26 | return Center(
27 | child: CircularProgressIndicator(),
28 | );
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/ios/Flutter/Flutter.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # NOTE: This podspec is NOT to be published. It is only used as a local source!
3 | #
4 |
5 | Pod::Spec.new do |s|
6 | s.name = 'Flutter'
7 | s.version = '1.0.0'
8 | s.summary = 'High-performance, high-fidelity mobile apps.'
9 | s.description = <<-DESC
10 | Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS.
11 | DESC
12 | s.homepage = 'https://flutter.io'
13 | s.license = { :type => 'MIT' }
14 | s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
15 | s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s }
16 | s.ios.deployment_target = '8.0'
17 | s.vendored_frameworks = 'Flutter.framework'
18 | end
19 |
--------------------------------------------------------------------------------
/android/speech/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/lib/widget/blur_widget.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:flutter/material.dart';
4 |
5 | /// 毛玻璃背景
6 | class BlurOvalWidget extends StatelessWidget {
7 | final Widget child;
8 | final double padding;
9 | final Color color;
10 | final double sigma;
11 |
12 | BlurOvalWidget(
13 | {this.child,
14 | this.padding: 0.0,
15 | this.sigma: 10.0,
16 | this.color: Colors.white10});
17 |
18 | @override
19 | Widget build(BuildContext context) {
20 | return ClipOval(
21 | child: BackdropFilter(
22 | filter: ImageFilter.blur(
23 | sigmaX: 8,
24 | sigmaY: 8,
25 | ),
26 | child: Container(
27 | color: color,
28 | padding: EdgeInsets.all(padding),
29 | child: child,
30 | ),
31 | ),
32 | );
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/audioplayer/macos/audioplayer.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
3 | # Run `pod lib lint audioplayer.podspec' to validate before publishing.
4 | #
5 | Pod::Spec.new do |s|
6 | s.name = 'audioplayer'
7 | s.version = '0.0.1'
8 | s.summary = 'A new flutter plugin project.'
9 | s.description = <<-DESC
10 | A new flutter plugin project.
11 | DESC
12 | s.homepage = 'http://example.com'
13 | s.license = { :file => '../LICENSE' }
14 | s.author = { 'Your Company' => 'email@example.com' }
15 | s.source = { :path => '.' }
16 | s.source_files = 'Classes/**/*'
17 | s.dependency 'FlutterMacOS'
18 |
19 | s.platform = :osx, '10.11'
20 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
21 | s.swift_version = '5.0'
22 | end
23 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/lib/model/video_controller.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 | import 'package:video_player/video_player.dart';
3 |
4 | class VideoControllerProvider with ChangeNotifier{
5 | VideoPlayerController controller;
6 |
7 | setController(VideoPlayerController controller){
8 | /* if (controller != null) { // 把上一个停掉
9 | controller.pause();
10 | controller.dispose();
11 | } */
12 | this.controller = controller;
13 | //notifyListeners();
14 | }
15 |
16 | VideoPlayerController getController(){
17 | return this.controller;
18 | }
19 |
20 | // 判断参数是否是当前controller,如果是就把全局controller置空。
21 | bool clearController(VideoPlayerController itemController){
22 | bool isCurrentController = itemController!= null && itemController == this.controller;
23 | if (isCurrentController) {
24 | this.controller = null;
25 | }
26 | return isCurrentController;
27 | }
28 |
29 | }
--------------------------------------------------------------------------------
/bugs.md:
--------------------------------------------------------------------------------
1 | ## 问题Bugs:
2 | - snackBar改ListTile展示
3 | - MV视频页面添加类别展示,或者优化title
4 | - 获取歌曲下载进度
5 | -
6 | - 搜索功能、语音识别搜索
7 | - 收藏歌曲图片和歌词缓存到指定目录
8 | - 歌曲后台播放,避免退入后台
9 | - 缓存大小监测和清理
10 |
11 | - [2019-11-2] 实现歌曲收藏缓存、本地播放。
12 | - [2019-11-3] 优化api缓存
13 |
14 |
15 | - 语音搜索时暂停音乐 有歌词没有进度,查看是不是解析问题
16 | - 收藏页不刷新
17 | - 搜索框不可输入了
18 | - 播放和暂停时声音渐隐渐现
19 | - 判断一下个数,缓存太多才清理。
20 | - 首页几个页面keepAlive
21 | - 歌单hero动画切换背景图可用前一张模糊的。
22 | - 首页添加更多按钮 首页进来不要等待网络白屏,先显示部分或本地内容。
23 | - 通过和上一句比较长度,计算最后一句歌词长度。
24 | - 尝试在关闭播放页的时候把背景去掉,让动画好一点
25 | - 启动时进行缓存清理,隔一段时间判断,然后使用后台任务进行操作。。
26 | - 收藏的歌曲资源要单独存下来,不然会被回收掉。
27 | - 歌曲详情页等待状态
28 | - 接口失败时使用缓存
29 | - 浮动播放的图片不用placehold
30 | - 不在首页时首页动画要停掉
31 | - 慢网环境,歌词没及时切换,歌词进度还是之前的。
32 | - 语音搜索,先做java版
33 | - 判断是不是另外一首,不要用url,用id
34 | - 首页默认背景图要换浅色一点的,不然初次打开不好看。
35 | - 图片加载,默认图片不显示,会空白一会儿。
36 | - 等待中进度条看能否自定义。
37 | - 切歌时歌词要重置,不然下一首无歌词或加载失败就会显示前一首歌词。
38 | - 大图要设置默认图片,不然会全身绿色的背景。
39 | - 将播放器单独拿出来,主页面添加悬浮播放控件。
40 | - 查看源码,添加自定义Controller 暂停的时候点下一首,不会自动播放 创建表里面没有加新字段
--------------------------------------------------------------------------------
/audioplayer/ios/audioplayer.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
3 | # Run `pod lib lint audioplayer.podspec' to validate before publishing.
4 | #
5 | Pod::Spec.new do |s|
6 | s.name = 'audioplayer'
7 | s.version = '0.0.1'
8 | s.summary = 'A new flutter plugin project.'
9 | s.description = <<-DESC
10 | A new flutter plugin project.
11 | DESC
12 | s.homepage = 'http://example.com'
13 | s.license = { :file => '../LICENSE' }
14 | s.author = { 'Your Company' => 'email@example.com' }
15 | s.source = { :path => '.' }
16 | s.source_files = 'Classes/**/*'
17 | s.dependency 'Flutter'
18 | s.platform = :ios, '8.0'
19 |
20 | # Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported.
21 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }
22 | s.swift_version = '5.0'
23 | end
24 |
--------------------------------------------------------------------------------
/lib/utils/my_icons.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | /// iconfont图标,code为图标代码,在网页上查看
4 | class MyIcons{
5 |
6 | static const IconData full_screen = const IconData(
7 | 0xe60b,
8 | fontFamily: 'myIcon',
9 | matchTextDirection: true
10 | );
11 | static const IconData full_screen_exit = const IconData(
12 | 0xe7d0,
13 | fontFamily: 'myIcon',
14 | matchTextDirection: true
15 | );
16 | static const IconData player_random = const IconData(
17 | 0xe61a,
18 | fontFamily: 'myIcon',
19 | matchTextDirection: true
20 | );
21 | static const IconData player_cycle = const IconData(
22 | 0xe778,
23 | fontFamily: 'myIcon',
24 | matchTextDirection: true
25 | );
26 | static const IconData player_single = const IconData(
27 | 0xe779,
28 | fontFamily: 'myIcon',
29 | matchTextDirection: true
30 | );
31 | static const IconData player_list = const IconData(
32 | 0xe604,
33 | fontFamily: 'myIcon',
34 | matchTextDirection: true
35 | );
36 | }
--------------------------------------------------------------------------------
/android/speech/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
11 |
14 |
17 |
18 |
21 |
22 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.3.50'
3 | repositories {
4 | //google()
5 | //jcenter()
6 | maven { url 'https://maven.aliyun.com/repository/google' }
7 | maven { url 'https://maven.aliyun.com/repository/jcenter' }
8 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
9 | }
10 |
11 | dependencies {
12 | classpath 'com.android.tools.build:gradle:4.1.0'
13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | //google()
20 | //jcenter()
21 | maven { url 'https://maven.aliyun.com/repository/google' }
22 | maven { url 'https://maven.aliyun.com/repository/jcenter' }
23 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
24 | }
25 | }
26 |
27 | rootProject.buildDir = '../build'
28 | subprojects {
29 | project.buildDir = "${rootProject.buildDir}/${project.name}"
30 | }
31 | subprojects {
32 | project.evaluationDependsOn(':app')
33 | }
34 |
35 | task clean(type: Delete) {
36 | delete rootProject.buildDir
37 | }
38 |
--------------------------------------------------------------------------------
/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | //
3 | // To perform an interaction with a widget in your test, use the WidgetTester
4 | // utility that Flutter provides. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter/material.dart';
9 | import 'package:flutter_test/flutter_test.dart';
10 |
11 | import 'package:flutter_music_player/main.dart';
12 |
13 | void main() {
14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 | // Build our app and trigger a frame.
16 | await tester.pumpWidget(MyApp());
17 |
18 | // Verify that our counter starts at 0.
19 | expect(find.text('0'), findsOneWidget);
20 | expect(find.text('1'), findsNothing);
21 |
22 | // Tap the '+' icon and trigger a frame.
23 | await tester.tap(find.byIcon(Icons.add));
24 | await tester.pump();
25 |
26 | // Verify that our counter has incremented.
27 | expect(find.text('0'), findsNothing);
28 | expect(find.text('1'), findsOneWidget);
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/lib/utils/network_util.dart:
--------------------------------------------------------------------------------
1 | import 'package:connectivity/connectivity.dart';
2 |
3 | class NetworkUtil {
4 |
5 | /// 单例对象的写法
6 | // 私有静态instance
7 | static NetworkUtil _instance;
8 |
9 | // 对外访问点,指向私有静态方法
10 | factory NetworkUtil() {
11 | if (_instance == null) {
12 | _instance = NetworkUtil._();
13 | }
14 | return _instance;
15 | }
16 |
17 | // 将默认构造函数私有化
18 | NetworkUtil._();
19 |
20 |
21 | static ConnectivityResult networkState;
22 |
23 | var subscription;
24 |
25 | initNetworkListener(){
26 | //监测网络变化
27 | subscription = Connectivity()
28 | .onConnectivityChanged
29 | .listen((ConnectivityResult result) {
30 | networkState = result;
31 | print('当前网络状态: $networkState');
32 | /* if (result == ConnectivityResult.mobile) { // 手机网络
33 |
34 | } else if (result == ConnectivityResult.wifi) { // wifi
35 |
36 | } else { // 无网络
37 |
38 | } */
39 | });
40 | }
41 |
42 | ConnectivityResult getNetworkState(){
43 | return networkState;
44 | }
45 |
46 | bool isNetworkAvailable(){
47 | return networkState != ConnectivityResult.none;
48 | }
49 |
50 | void dispose() {
51 | //在页面销毁的时候一定要取消网络状态的监听
52 | subscription?.cancle();
53 | }
54 |
55 | }
--------------------------------------------------------------------------------
/lib/utils/navigator_util.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | /// 页面导航
3 | /// 可自定义切页效果
4 | class NavigatorUtil {
5 | static void push(BuildContext context, Widget page) {
6 | Navigator.of(context).push(MaterialPageRoute(builder: (context) => page));
7 | }
8 |
9 | static void pushFade(BuildContext context, Widget page) {
10 | Navigator.of(context).push(CustomRouteFade(page));
11 | }
12 | }
13 |
14 | // 渐变效果
15 | class CustomRouteFade extends PageRouteBuilder {
16 | final Widget widget;
17 | CustomRouteFade(this.widget)
18 | : super(
19 | transitionDuration: const Duration(milliseconds: 600),
20 | pageBuilder: (BuildContext context, Animation animation1,
21 | Animation animation2) {
22 | return widget;
23 | },
24 | transitionsBuilder: (BuildContext context,
25 | Animation animation1,
26 | Animation animation2,
27 | Widget child) {
28 | return FadeTransition(
29 | opacity: Tween(begin: 0.0, end: 2.0).animate(CurvedAnimation(
30 | parent: animation1, curve: Curves.fastOutSlowIn)),
31 | child: child,
32 | );
33 | });
34 | }
35 |
--------------------------------------------------------------------------------
/lib/pages/song_list.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_music_player/widget/song_item_tile.dart';
3 | import '../dao/music_163.dart';
4 |
5 | class SongList extends StatefulWidget {
6 | SongList({Key key}) : super(key: key);
7 |
8 | _SongListState createState() => _SongListState();
9 | }
10 |
11 | class _SongListState extends State {
12 | List _songs = [];
13 |
14 | _getSongs() async {
15 | await MusicDao.getTopSongs(0).then((result) {
16 | // 界面未加载,返回。
17 | if (!mounted) return;
18 |
19 | setState(() {
20 | _songs = result;
21 | });
22 | }).catchError((e) {
23 | print('Failed: ${e.toString()}');
24 | });
25 | }
26 |
27 | @override
28 | void initState() {
29 | super.initState();
30 | _getSongs();
31 | }
32 |
33 | Widget mWidget;
34 |
35 | @override
36 | Widget build(BuildContext context) {
37 | if (_songs.length == 0) {
38 | // 显示进度条
39 | mWidget = Center(child: CircularProgressIndicator());
40 | } else {
41 | mWidget = ListView.builder(
42 | itemCount: this._songs.length,
43 | itemExtent: 70.0, // 设定item的高度,这样可以减少高度计算。
44 | itemBuilder: (context, index) => SongItemTile(_songs, index),
45 | );
46 | }
47 | return mWidget;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/lib/widget/text_icon.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_music_player/model/color_provider.dart';
3 | import 'package:provider/provider.dart';
4 |
5 | class TextIcon extends StatelessWidget {
6 | final IconData icon;
7 | final String title;
8 | final bool selected;
9 | final Function onPressed;
10 | const TextIcon(
11 | {Key key, this.icon, this.title, this.selected: false, this.onPressed})
12 | : super(key: key);
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | Color color = selected ? Provider.of(context).getCurrentColor() : Colors.black54;
17 | return InkWell(
18 | onTap: this.onPressed,
19 | child: Container(
20 | width: 66.0,
21 | padding: EdgeInsets.fromLTRB(4.0, 8.0, 4.0, 4.0),
22 | child: Column(
23 | mainAxisSize: MainAxisSize.min,
24 | children: [
25 | Icon(icon, color: color, size: 22.0),
26 | Text(
27 | title,
28 | style: TextStyle(
29 | //fontSize: selected ? 14.0 : 12.0,
30 | fontSize: 14.0,
31 | height: 1.4,
32 | color: color),
33 | )
34 | ],
35 | )));
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/lib/widget/text_icon_withbg.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_music_player/model/color_provider.dart';
3 | import 'package:provider/provider.dart';
4 |
5 | class TextIconWithBg extends StatelessWidget {
6 | final IconData icon;
7 | final String title;
8 | final Function onPressed;
9 | const TextIconWithBg({Key key, this.icon, this.title, this.onPressed})
10 | : super(key: key);
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | return GestureDetector(
15 | onTap: this.onPressed,
16 | child: Column(
17 | mainAxisSize: MainAxisSize.min,
18 | mainAxisAlignment: MainAxisAlignment.center,
19 | children: [
20 | Container(
21 | margin: EdgeInsets.fromLTRB(12.0, 16.0, 12.0, 8.0),
22 | padding: EdgeInsets.all(10.0),
23 | decoration: BoxDecoration(
24 | shape: BoxShape.circle,
25 | color: Provider.of(context)
26 | .getCurrentColor()),
27 | child: Icon(icon, color: Colors.white, size: 24.0),
28 | ),
29 | Text(
30 | title,
31 | style: TextStyle(fontSize: 13.0, color: Colors.black87),
32 | ),
33 | SizedBox(height: 16.0),
34 | ],
35 | ));
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/android/speech/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 |
4 | // 添加对Flutter的依赖
5 | def localProperties = new Properties()
6 | def localPropertiesFile = rootProject.file('local.properties')
7 | if (localPropertiesFile.exists()) {
8 | localPropertiesFile.withReader('UTF-8') { reader ->
9 | localProperties.load(reader)
10 | }
11 | }
12 |
13 | def flutterRoot = localProperties.getProperty('flutter.sdk')
14 | if (flutterRoot == null) {
15 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
16 | }
17 |
18 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
19 |
20 |
21 | android {
22 | compileSdkVersion 30
23 |
24 | defaultConfig {
25 | minSdkVersion 16
26 | targetSdkVersion 30
27 | versionCode 1
28 | versionName "1.0"
29 |
30 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
31 | }
32 |
33 | buildTypes {
34 | release {
35 | minifyEnabled false
36 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
37 | }
38 | }
39 |
40 | }
41 |
42 | // 配置flutter的源目录
43 | flutter {
44 | source '../..'
45 | }
46 |
47 | dependencies {
48 | implementation fileTree(dir: 'libs', include: ['*.jar'])
49 |
50 | implementation 'androidx.appcompat:appcompat:1.0.2'
51 | }
52 |
--------------------------------------------------------------------------------
/lib/utils/colors.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class AppColors {
4 | static Color unSelectedColor = Color(0xFF999999);
5 |
6 | static MaterialColor mainColor = Colors.green;
7 | static Color mainLightColor = Colors.greenAccent;
8 | static Color mainLightAccent = Colors.lightGreenAccent;
9 | static Color indicatorColor = Colors.orange;
10 |
11 | /* static Color mainColor = Colors.pink;
12 | static Color mainLightColor = Colors.pink;
13 | static Color mainLightAccent = Colors.pinkAccent;
14 | static Color toastBackground = Colors.pink[400];
15 | static Color indicatorColor = Colors.pinkAccent; */
16 |
17 | /* static Color mainColor = Colors.orange;
18 | static Color mainLightColor = Colors.orange;
19 | static Color mainLightAccent = Colors.deepOrangeAccent;
20 | static Color toastBackground = Colors.orange[400];
21 | static Color indicatorColor = Colors.orange; */
22 |
23 |
24 | /* static MaterialColor mainColor = Colors.purple;
25 | static Color mainLightColor = Colors.purple;
26 | static Color mainLightAccent = Colors.purpleAccent;
27 | static Color toastBackground = Colors.purple[400];
28 | static Color indicatorColor = Colors.deepPurple; */
29 |
30 | /* static Color mainColor = Colors.blue;
31 | static Color mainLightColor = Colors.lightBlue;
32 | static Color mainLightAccent = Colors.lightBlueAccent;
33 | static Color toastBackground = Colors.blue[400];
34 | static Color indicatorColor = Colors.lightBlue; */
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/lib/pages/favorite_music.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_music_player/dao/music_db_favorite.dart';
3 | import 'package:flutter_music_player/widget/song_item_tile.dart';
4 |
5 | class FavoriteMusic extends StatefulWidget {
6 | FavoriteMusic({Key key}) : super(key: key);
7 |
8 | _FavoriteMusicState createState() => _FavoriteMusicState();
9 | }
10 |
11 | class _FavoriteMusicState extends State {
12 | List _songs;
13 |
14 | _getSongs() async {
15 | FavoriteDB().getFavoriteList().then((result) {
16 | // 界面未加载,返回。
17 | if (!mounted) return;
18 |
19 | setState(() {
20 | _songs = result;
21 | });
22 | }).catchError((e) {
23 | print('Failed: ${e.toString()}');
24 | });
25 | }
26 |
27 | @override
28 | void initState() {
29 | super.initState();
30 | _getSongs();
31 | }
32 |
33 | @override
34 | Widget build(BuildContext context) {
35 | if (_songs == null) {
36 | return Container();
37 | }
38 | if (_songs.length == 0) {
39 | return Center(
40 | child: Text(
41 | '您还没有收藏歌曲\n可点击播放页右上角进行收藏。',
42 | textAlign: TextAlign.center,
43 | style: TextStyle(color: Colors.grey, height: 1.5),
44 | ));
45 | } else {
46 | return ListView.builder(
47 | itemCount: this._songs.length,
48 | itemExtent: 70.0, // 设定item的高度,这样可以减少高度计算。
49 | itemBuilder: (context, index) => SongItemTile(_songs, index),
50 | );
51 | }
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/lib/pages/rank_song_list.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_music_player/dao/music_163.dart';
3 | import 'package:flutter_music_player/widget/song_item_tile.dart';
4 |
5 | class RankSongList extends StatefulWidget {
6 | final int topId;
7 | final String topName;
8 | RankSongList(this.topId, this.topName, {Key key}) : super(key: key);
9 |
10 | @override
11 | _RankSongListState createState() => _RankSongListState();
12 | }
13 |
14 | class _RankSongListState extends State {
15 | List _songs = [];
16 |
17 | _getSongs() async {
18 | await MusicDao.getTopSongs(widget.topId).then((result) {
19 | // 界面未加载,返回。
20 | if (!mounted) return;
21 |
22 | setState(() {
23 | _songs = result;
24 | });
25 | }).catchError((e) {
26 | print('Failed: ${e.toString()}');
27 | });
28 | }
29 |
30 | @override
31 | void initState() {
32 | super.initState();
33 | _getSongs();
34 | }
35 |
36 | @override
37 | Widget build(BuildContext context) {
38 | return Scaffold(
39 | appBar: AppBar(
40 | titleSpacing: 0.0,
41 | title: Text(widget.topName, style: TextStyle(fontSize: 16.0)),
42 | ),
43 | body: _songs.length == 0
44 | ? Center(child: CircularProgressIndicator())
45 | : ListView.builder(
46 | itemCount: _songs.length,
47 | itemExtent: 70.0, // 设定item的高度,这样可以减少高度计算。
48 | itemBuilder: (context, index) => SongItemTile(_songs, index),
49 | ),
50 | );
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/lib/pages/mv_tab_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_music_player/dao/music_163.dart';
3 | import 'package:flutter_music_player/widget/mv_item.dart';
4 |
5 | class MVTabPage extends StatefulWidget {
6 | final String url;
7 | MVTabPage({Key key, this.url}) : super(key: key);
8 |
9 | @override
10 | _MVTabPageState createState() => _MVTabPageState();
11 | }
12 |
13 | class _MVTabPageState extends State {
14 | List _mvList = [];
15 |
16 | _getMVList() async {
17 | await MusicDao.getMVList(widget.url).then((result) {
18 | // 界面未加载,返回。
19 | if (!mounted) return;
20 |
21 | setState(() {
22 | _mvList = result;
23 | });
24 | }).catchError((e) {
25 | print('Failed: ${e.toString()}');
26 | });
27 | }
28 |
29 | @override
30 | void initState() {
31 | super.initState();
32 | _getMVList();
33 | }
34 |
35 | @override
36 | Widget build(BuildContext context) {
37 | return _mvList.length == 0
38 | ? Center(child: CircularProgressIndicator())
39 | : ListView.builder(
40 | cacheExtent: 10.0, // 缓存区域,滚出多远后回收item,调用其dispose
41 | itemCount: this._mvList.length,
42 | //itemExtent: 70.0, // 设定item的高度,这样可以减少高度计算。
43 | itemBuilder: (context, index) => MVItem(this._mvList[index]),
44 | /* separatorBuilder: (context, index) => Divider(
45 | color: Color(0x0f000000),
46 | height: 12.0, // 间隔的高度
47 | thickness: 8.0, // 绘制的线的厚度
48 | ), */
49 | );
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/lib/widget/tap_anim_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | /// 点击会有动画的控件
4 | class TapAnim extends StatefulWidget {
5 | final Function onPressed;
6 | final Widget child;
7 | final int animDuration;
8 |
9 | TapAnim({this.child, this.onPressed, this.animDuration:160});
10 |
11 | @override
12 | _TapAnimState createState() => _TapAnimState();
13 | }
14 |
15 | class _TapAnimState extends State with SingleTickerProviderStateMixin {
16 | Animation animation;
17 | AnimationController _controller;
18 |
19 | @override
20 | void initState() {
21 | super.initState();
22 | _controller =
23 | AnimationController(vsync: this, duration: Duration(milliseconds: widget.animDuration))
24 | ..addListener(() {
25 | setState(() {});
26 | });
27 |
28 | animation = new Tween(begin: 0.0, end: 1.0).animate(_controller);
29 | animation.addStatusListener((status) {
30 | if (status == AnimationStatus.completed) {
31 | //动画执行结束时反向执行动画
32 | _controller.reverse();
33 | }
34 | });
35 | }
36 |
37 | @override
38 | void dispose() {
39 | _controller.dispose();
40 | super.dispose();
41 | }
42 |
43 | void startAnim() {
44 | _controller.forward();
45 | }
46 |
47 | @override
48 | Widget build(BuildContext context) {
49 | return GestureDetector(
50 | onTap: () {
51 | startAnim();
52 | widget.onPressed();
53 | },
54 | child: Transform.scale(
55 | scale: 1.0 - _controller.value * 0.2,
56 | child: widget.child,
57 | ));
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/audioplayer/LICENSE:
--------------------------------------------------------------------------------
1 | // Copyright 2017 rxlabz. All rights reserved.
2 | //
3 | // Redistribution and use in source and binary forms, with or without
4 | // modification, are permitted provided that the following conditions are
5 | // met:
6 | //
7 | // * Redistributions of source code must retain the above copyright
8 | // notice, this list of conditions and the following disclaimer.
9 | // * Redistributions in binary form must reproduce the above
10 | // copyright notice, this list of conditions and the following disclaimer
11 | // in the documentation and/or other materials provided with the
12 | // distribution.
13 | // * Neither the name of Your Company nor the names of its
14 | // contributors may be used to endorse or promote products derived from
15 | // this software without specific prior written permission.
16 | //
17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | FlutterMusic
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/lib/widget/current_play_list.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_music_player/model/music_controller.dart';
3 | import 'package:flutter_music_player/widget/song_item_text.dart';
4 | import 'package:provider/provider.dart';
5 |
6 | class CurrentPlayList extends StatefulWidget {
7 | CurrentPlayList({Key key}) : super(key: key);
8 |
9 | @override
10 | _CurrentPlayListState createState() => _CurrentPlayListState();
11 | }
12 |
13 | class _CurrentPlayListState extends State {
14 | final itemHeight = 40.0;
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | MusicController musicController =
19 | Provider.of(context, listen: false);
20 | List songs = musicController.playList.songList;
21 | double initScroll = itemHeight * (musicController.getCurrentIndex() - 3);
22 | return ClipRRect(
23 | borderRadius: BorderRadius.only(
24 | topLeft: Radius.circular(16.0),
25 | topRight: Radius.circular(16.0)),
26 | child: Container(
27 | color: Colors.white.withOpacity(0.9),
28 | padding: EdgeInsets.symmetric(vertical: 20),
29 | child: ListView.builder(
30 | controller: ScrollController(initialScrollOffset: initScroll),
31 | itemCount: songs.length,
32 | itemExtent: itemHeight, // 设定item的高度,这样可以减少高度计算。
33 | itemBuilder: (context, index) => SongItemText(
34 | songs,
35 | index,
36 | onItemTap: () {
37 | Future.delayed(Duration(milliseconds: 300)).then((_) {
38 | Navigator.of(context).pop();
39 | });
40 | },
41 | ),
42 | ),
43 | ));
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | .dart_tool/
26 | .flutter-plugins
27 | .packages
28 | .pub-cache/
29 | .pub/
30 | /build/
31 | pubspec.lock
32 | .flutter-plugins
33 | .flutter-plugins-dependencies
34 |
35 |
36 | # Android related
37 | **/android/**/gradle-wrapper.jar
38 | **/android/.gradle
39 | **/android/captures/
40 | **/android/gradlew
41 | **/android/gradlew.bat
42 | **/android/local.properties
43 | **/android/**/GeneratedPluginRegistrant.java
44 |
45 | # iOS/XCode related
46 | **/ios/**/*.mode1v3
47 | **/ios/**/*.mode2v3
48 | **/ios/**/*.moved-aside
49 | **/ios/**/*.pbxuser
50 | **/ios/**/*.perspectivev3
51 | **/ios/**/*sync/
52 | **/ios/**/.sconsign.dblite
53 | **/ios/**/.tags*
54 | **/ios/**/.vagrant/
55 | **/ios/**/DerivedData/
56 | **/ios/**/Icon?
57 | **/ios/**/Pods/
58 | **/ios/**/.symlinks/
59 | **/ios/**/profile
60 | **/ios/**/xcuserdata
61 | **/ios/.generated/
62 | **/ios/Flutter/App.framework
63 | **/ios/Flutter/Flutter.framework
64 | **/ios/Flutter/Generated.xcconfig
65 | **/ios/Flutter/app.flx
66 | **/ios/Flutter/app.zip
67 | **/ios/Flutter/flutter_assets/
68 | **/ios/Flutter/flutter_export_environment.sh
69 | **/ios/ServiceDefinitions.json
70 | **/ios/Runner/GeneratedPluginRegistrant.*
71 |
72 | # Exceptions to above rules.
73 | !**/ios/**/default.mode1v3
74 | !**/ios/**/default.mode2v3
75 | !**/ios/**/default.pbxuser
76 | !**/ios/**/default.perspectivev3
77 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
78 |
--------------------------------------------------------------------------------
/lib/dao/music_db.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_music_player/dao/music_db_history.dart';
2 | import 'package:flutter_music_player/dao/music_db_playlist.dart';
3 | import 'package:sqflite/sqflite.dart';
4 |
5 | import 'music_db_favorite.dart';
6 |
7 | class MusicDB {
8 | static const db_version = 4;
9 | static const db_file = 'music.db';
10 |
11 | /// 单例对象的写法
12 | // 私有静态instance
13 | static MusicDB _instance;
14 |
15 | // 对外访问点,指向私有静态方法
16 | factory MusicDB() => _getInstance();
17 |
18 | static MusicDB _getInstance() {
19 | if (_instance == null) {
20 | _instance = MusicDB._();
21 | }
22 | return _instance;
23 | }
24 |
25 | // 将默认构造函数私有化
26 | MusicDB._();
27 |
28 | // db对象不能直接生成,第一次会报错,因为db对象是异步生成的,直接调用的时候为null。
29 | Database db;
30 | // 定义一个get方法,完美解决获取db可能为空的情况。
31 | Future getDB() async {
32 | if (db == null) {
33 | db = await initDB();
34 | }
35 | return db;
36 | }
37 |
38 | Future initDB() async {
39 | print('initDB');
40 | return await openDatabase(db_file, version: db_version,
41 | onCreate: (Database db, int version) async {
42 | // 初始化,创建表
43 | FavoriteDB().createTable(db);
44 | HistoryDB().createTable(db);
45 | PlayListDB().createTable(db);
46 | }, onUpgrade: (Database db, int oldVersion, int newVersion) async {
47 | // 数据库升级,修改表结构。
48 | if (oldVersion == 1) {
49 | oldVersion++;
50 | await db.execute(
51 | 'ALTER TABLE ${FavoriteDB.table_name} ADD COLUMN createTime integer');
52 | }
53 | if (oldVersion == 2) {
54 | oldVersion++;
55 | HistoryDB().createTable(db);
56 | }
57 | if (oldVersion == 3) {
58 | oldVersion++;
59 | PlayListDB().createTable(db);
60 | }
61 | });
62 | }
63 |
64 | closeDB() async {
65 | await db?.close();
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
9 |
14 |
21 |
25 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/audioplayer/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 0.8.1
4 | - iOS : enable audio output to speakers thanks @mhatout
5 | - fixes iOS 'timeobservers' typo thanks @athornz
6 |
7 | ## 0.8.0
8 | - Android : new FlutterPlugin API & AndroidX migration
9 |
10 | ## 0.7.0
11 | - add Web support
12 |
13 | ## 0.6.0
14 | - switch to Swift thanks @matteti #114
15 | - add MacOS support thanks @matteti #115
16 |
17 | ## 0.5.2
18 | - fix objC warning
19 | - updated example
20 |
21 | ## 0.5.1
22 | - Allow Dart 2 SDK
23 | - Fix java lint warnings.
24 |
25 | ## 0.5.0
26 | - BREAKING Change: No more separate handlers for communicating the state of the player. Instead we rely on streams to publish state changes and position updates.
27 | - Code formatting and flow improvements. Preparation for testing.
28 |
29 | ## 0.4.0
30 |
31 | - Feat : merge PR from [mindon](https://github.com/mindon) with mute methods and various improvements
32 | - fixes Future errors with --preview-dart2
33 | - Example : add a slider to demonstrate the seek feature
34 |
35 | ## 0.3.0
36 |
37 | - merge PR from [johanhenselmans](https://github.com/johanhenselmans) to switch iOS to ObjectiveC
38 | - merge PR from [oaks](https://github.com/oakes) to add the seek feature
39 |
40 | ## 0.2.0
41 |
42 | - support for local files
43 |
44 | ## 0.1.0
45 |
46 | - update to the current Plugin API
47 | - move to https://github.com/rxlabz/audioplayer
48 |
49 | ## 0.0.2
50 |
51 | Separated handlers for position, duration, completion and errors
52 |
53 | - setDurationHandler(TimeChangeHandler handler)
54 | - setPositionHandler(TimeChangeHandler handler)
55 | - setCompletionHandler(VoidCallback callback)
56 | - setErrorHandler(ErrorHandler handler)
57 |
58 | - new typedef
59 | ```dart
60 | typedef void TimeChangeHandler(Duration duration);
61 | typedef void ErrorHandler(String message);
62 | ```
63 |
64 | ## 0.0.1
65 |
66 | - first POC :
67 | - methods : play, pause, stop
68 | - a globalHandler for position, duration, completion and errors
69 |
--------------------------------------------------------------------------------
/lib/test/test_positioned_1.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_music_player/test/test_positioned_2.dart';
3 |
4 | class TestPage extends StatefulWidget {
5 | TestPage({Key key}) : super(key: key);
6 |
7 | _TestPageState createState() => _TestPageState();
8 | }
9 |
10 | class _TestPageState extends State {
11 | @override
12 | Widget build(BuildContext context) {
13 | return Scaffold(
14 | appBar: AppBar(
15 | title: Text('Flutter Music Player'),
16 | ),
17 | body: Stack(
18 | alignment: Alignment.center,
19 | children: [
20 | /* Positioned(
21 | bottom: 30.0,
22 | child: Text("Test"),
23 | ), */
24 | Positioned(
25 | bottom: 30.0,
26 | left: 20.0,
27 | right: 20.0,
28 | child: Row(
29 | children: [
30 | Text("00:00",
31 | style: TextStyle(color: Colors.black, fontSize: 12)),
32 | Expanded(
33 | child: Slider.adaptive(
34 | value: 20.0,
35 | min: 0.0,
36 | max: 100.0,
37 | onChanged: (value) {},
38 | ),
39 | ),
40 | Text(
41 | "12:34",
42 | style: TextStyle(color: Colors.black, fontSize: 12),
43 | ),
44 | ],
45 | ),
46 | ),
47 | Positioned( // 发现一个现象:如果这儿不是Positioned那么上面的Positioned布局就会失效,报overflow异常。
48 | bottom: 100.0,
49 | left: 20.0,
50 | right: 20.0,
51 | child: RaisedButton(
52 | child: Text("单独的页面"),
53 | onPressed: () {
54 | Navigator.of(context)
55 | .push(MaterialPageRoute(builder: (context) => TestPage2()));
56 | },
57 | ))
58 | ],
59 | ));
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/lib/widget/song_item_tile.dart:
--------------------------------------------------------------------------------
1 | import 'package:cached_network_image/cached_network_image.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_music_player/model/song_util.dart';
4 | import 'package:flutter_music_player/pages/player_page.dart';
5 |
6 | class SongItemTile extends StatelessWidget {
7 | final List songList;
8 | final int index;
9 | final Function onItemTap;
10 | const SongItemTile(this.songList, this.index, {Key key, this.onItemTap})
11 | : super(key: key);
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | Map song = this.songList[index];
16 | String image = SongUtil.getSongImage(song);
17 | return Container(
18 | decoration: BoxDecoration(
19 | color: Color(0x08ffffff),
20 | /* border: Border(
21 | bottom: BorderSide(
22 | color: Color(0x11000000), width: 0.5, style: BorderStyle.solid),
23 | ), */
24 | ),
25 | child: ListTile(
26 | leading: ClipRRect(
27 | borderRadius: BorderRadius.circular(6.0),
28 | child: image.isEmpty
29 | ? Image.asset('images/music_2.jpg', fit: BoxFit.cover)
30 | : CachedNetworkImage(
31 | imageUrl: image,
32 | placeholder: (context, url) =>
33 | Image.asset('images/music_2.jpg', fit: BoxFit.cover)),
34 | ),
35 | title: new Text(
36 | "${song['name']}",
37 | maxLines: 1,
38 | overflow: TextOverflow.ellipsis,
39 | style: TextStyle(fontSize: 14.0),
40 | ),
41 | subtitle: new Text(
42 | SongUtil.getArtistNames(song),
43 | maxLines: 1,
44 | overflow: TextOverflow.ellipsis,
45 | style: TextStyle(fontSize: 12.0),
46 | ),
47 | onTap: () {
48 | if (onItemTap != null) {
49 | this.onItemTap();
50 | }
51 | PlayerPage.gotoPlayer(context, list: songList, index: index);
52 | },
53 | ));
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/lib/pages/mv_player_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_music_player/dao/music_163.dart';
3 | import 'package:video_player/video_player.dart';
4 |
5 | class MVPlayer extends StatefulWidget {
6 | final Map mv;
7 | MVPlayer(this.mv, {Key key}) : super(key: key);
8 |
9 | @override
10 | _MVPlayerState createState() => _MVPlayerState();
11 | }
12 |
13 | class _MVPlayerState extends State {
14 | VideoPlayerController _controller;
15 | @override
16 | void initState() {
17 | super.initState();
18 |
19 | MusicDao.getMVDetail(widget.mv['id']).then((url) {
20 | _controller = VideoPlayerController.network(url)
21 | ..initialize().then((_) {
22 | // Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
23 | setState(() {});
24 | _controller.play();
25 | });
26 | });
27 | }
28 |
29 | @override
30 | Widget build(BuildContext context) {
31 | bool initialized = _controller != null && _controller.value.isInitialized;
32 | bool playing = _controller != null && _controller.value.isPlaying;
33 |
34 | return MaterialApp(
35 | title: 'Video Demo',
36 | home: Scaffold(
37 | body: Center(
38 | child: initialized
39 | ? AspectRatio(
40 | aspectRatio: _controller.value.aspectRatio,
41 | child: Hero(
42 | tag: widget.mv,
43 | child: VideoPlayer(_controller),
44 | ))
45 | : Center(child: CircularProgressIndicator()),
46 | ),
47 | floatingActionButton: FloatingActionButton(
48 | onPressed: () {
49 | setState(() {
50 | playing ? _controller.pause() : _controller.play();
51 | });
52 | },
53 | child: Icon(
54 | playing ? Icons.pause : Icons.play_arrow,
55 | ),
56 | ),
57 | ),
58 | );
59 | }
60 |
61 | @override
62 | void dispose() {
63 | super.dispose();
64 | _controller.dispose();
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/lib/widget/favorite_icon_playlist.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_music_player/dao/music_db_playlist.dart';
3 |
4 | class FavoritePlayListIcon extends StatefulWidget {
5 | final Map play;
6 | const FavoritePlayListIcon(this.play, {Key key}) : super(key: key);
7 |
8 | @override
9 | _FavoritePlayListIconState createState() => _FavoritePlayListIconState();
10 | }
11 |
12 | class _FavoritePlayListIconState extends State {
13 | bool isFavorited = false;
14 | Map play;
15 |
16 | @override
17 | void initState() {
18 | super.initState();
19 | //print('FavoritePlayListIcon initState');
20 | }
21 |
22 | void _checkFavorite() {
23 | PlayListDB().getPlayListById(play['id']).then((fav) {
24 | //print('getFavoriteById : $fav');
25 | setState(() {
26 | isFavorited = fav != null;
27 | });
28 | });
29 | }
30 |
31 | @override
32 | Widget build(BuildContext context) {
33 | if (widget.play != play) {
34 | play = widget.play;
35 | _checkFavorite();
36 | }
37 | return IconButton(
38 | icon: Icon(
39 | Icons.favorite,
40 | color: isFavorited
41 | ? Colors.white
42 | : Colors.white30,
43 | ),
44 | onPressed: () {
45 | if (this.isFavorited) {
46 | _cancelFavorite(context);
47 | } else {
48 | _addFavorite(context);
49 | }
50 | },
51 | );
52 | }
53 |
54 | void _addFavorite(context) {
55 | PlayListDB().addPlayList(widget.play).then((re) {
56 | print('addFavorite re: $re , play: ${widget.play}');
57 | setState(() {
58 | isFavorited = true;
59 | });
60 | }).catchError((error) {
61 | print('addFavorite error: $error');
62 | });
63 | }
64 |
65 | void _cancelFavorite(context) {
66 | PlayListDB().deletePlayList(widget.play['id']).then((re) {
67 | setState(() {
68 | isFavorited = false;
69 | });
70 | }).catchError((error) {
71 | print('deleteFavorite error: $error');
72 | throw Exception('取消收藏失败');
73 | });
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/lib/model/play_list.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | enum CycleType { queue, one, random }
4 |
5 | class PlayList {
6 | List songList = [];
7 | int index = 0;
8 | CycleType cycleType = CycleType.queue;
9 |
10 | setPlayList(List list, int currentIndex) {
11 | songList = list;
12 | this.index = currentIndex;
13 | }
14 |
15 | setCurrentIndex(int index) {
16 | this.index = index;
17 | }
18 |
19 | Map getCurrentSong() {
20 | if (index < 0 || index >= songList.length) {
21 | return null;
22 | }
23 | return songList[index];
24 | }
25 |
26 | Map next() {
27 | if (songList.length == 0) {
28 | return null;
29 | }
30 | index++;
31 | if (index >= songList.length) {
32 | index = 0;
33 | }
34 | return songList[index];
35 | }
36 |
37 | Map previous() {
38 | if (songList.length == 0) {
39 | return null;
40 | }
41 | index--;
42 | if (index < 0) {
43 | index = songList.length - 1;
44 | }
45 | return songList[index];
46 | }
47 |
48 | Map randomNext() {
49 | if (songList.length == 0) {
50 | return null;
51 | }
52 | int rdmIndex = 0;
53 | if (songList.length > 1) {
54 | rdmIndex = Random().nextInt(songList.length);
55 | if (rdmIndex == index) {
56 | // 如果和当前index相同,就+1。
57 | rdmIndex++;
58 | if (rdmIndex >= songList.length) {
59 | rdmIndex = 0;
60 | }
61 | }
62 | }
63 | index = rdmIndex;
64 | return songList[index];
65 | }
66 |
67 | int getCurrentIndex() {
68 | return this.index;
69 | }
70 |
71 | void changCycleType() {
72 | if (cycleType == CycleType.queue) {
73 | cycleType = CycleType.one;
74 | } else if (cycleType == CycleType.one) {
75 | cycleType = CycleType.random;
76 | } else {
77 | cycleType = CycleType.queue;
78 | }
79 | }
80 |
81 | String getCycleName() {
82 | String cycleName;
83 | switch(cycleType) {
84 | case CycleType.queue: cycleName = '顺序播放';break;
85 | case CycleType.one: cycleName = '单曲循环';break;
86 | case CycleType.random: cycleName = '随机播放';break;
87 | }
88 | return cycleName;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/lib/widget/play_list_item.dart:
--------------------------------------------------------------------------------
1 | import 'package:cached_network_image/cached_network_image.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_music_player/pages/play_list_detail.dart';
4 | import 'package:flutter_music_player/utils/navigator_util.dart';
5 |
6 |
7 | class PlayListItem extends StatelessWidget {
8 | final Map play;
9 | final String heroTag;
10 | const PlayListItem(this.play, {Key key, this.heroTag}) : super(key: key);
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | //print('PlayListItem build: ${play['name']}, $hashCode');
15 | String tag = '${play['id']}_$heroTag';
16 | return Stack(
17 | alignment: AlignmentDirectional.bottomStart,
18 | children: [
19 | ClipRRect(
20 | borderRadius: BorderRadius.all(Radius.circular(4.0)),
21 | child: Hero(
22 | tag: tag, // 注意页面keepAlive之后全局唯一
23 | child: CachedNetworkImage(imageUrl: '${play['coverImgUrl']}?param=300y300'),
24 | )
25 | ),
26 | ClipRRect(
27 | borderRadius: BorderRadius.only(
28 | bottomLeft: Radius.circular(4.0),
29 | bottomRight: Radius.circular(4.0)),
30 | child: Container(
31 | width: double.infinity,
32 | color: Color.fromARGB(80, 0, 0, 0),
33 | padding: EdgeInsets.all(6.0),
34 | child: Text(
35 | play['name'],
36 | overflow: TextOverflow.ellipsis,
37 | style: TextStyle(fontSize: 12.0, color: Colors.white),
38 | )),
39 | ),
40 | Positioned.fill(
41 | child: Material(
42 | color: Colors.transparent,
43 | child: InkWell(
44 | // 水波纹
45 | splashColor: Colors.white.withOpacity(0.3),
46 | highlightColor: Colors.white.withOpacity(0.1),
47 | onTap: () {
48 | NavigatorUtil.push(context, PlayListPage(playlist: play, heroTag: tag));
49 | }),
50 | ),
51 | ),
52 | ],
53 | );
54 | }
55 | }
--------------------------------------------------------------------------------
/lib/pages/rank_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_music_player/pages/rank_song_list.dart';
3 | import 'package:flutter_music_player/utils/navigator_util.dart';
4 |
5 | class RankPage extends StatefulWidget {
6 | RankPage({Key key}) : super(key: key);
7 |
8 | @override
9 | _RankPageState createState() => _RankPageState();
10 | }
11 |
12 | class _RankPageState extends State {
13 | @override
14 | void initState() {
15 | super.initState();
16 | }
17 |
18 | @override
19 | Widget build(BuildContext context) {
20 | return Scaffold(
21 | appBar: AppBar(
22 | titleSpacing: 0.0,
23 | title: Text('排行榜', style: TextStyle(fontSize: 16.0)),
24 | ),
25 | body: ListView.separated(
26 | itemCount: ranks.length,
27 | itemBuilder: (context, index) =>
28 | _buildItem(ranks.entries.elementAt(index)),
29 | separatorBuilder: (context, index) =>
30 | Divider(height: 0.5, color: Colors.black12),
31 | ),
32 | );
33 | }
34 |
35 | Widget _buildItem(MapEntry entry) {
36 | return ListTile(
37 | contentPadding: EdgeInsets.only(left: 20.0, top: 4.0, bottom: 4.0),
38 | leading: Icon(Icons.whatshot, color: Colors.deepOrangeAccent),
39 | title: Text(entry.value, style: TextStyle(fontSize: 14.0)),
40 | onTap: () {
41 | NavigatorUtil.push(context, RankSongList(entry.key, entry.value));
42 | },
43 | );
44 | }
45 | }
46 |
47 | Map ranks = {
48 | 3779629: '云音乐新歌榜',
49 | 3778678: '云音乐热歌榜',
50 | 2: '网易原创歌曲榜',
51 | 3: '云音乐飙升榜',
52 | 4: '云音乐电音榜',
53 | 5: 'UK排行榜周榜',
54 | 6: '美国Billboard周榜',
55 | 7: 'KTV嗨榜',
56 | 8: 'iTunes榜',
57 | 9: 'Hit FM Top榜',
58 | 10: '日本Oricon周榜',
59 | 11: '韩国Melon排行榜周榜',
60 | 12: '韩国Mnet排行榜周榜',
61 | 13: '韩国Melon原声周榜',
62 | 14: '中国TOP排行榜(港台榜)',
63 | 15: '中国TOP排行榜(内地榜)',
64 | 16: '香港电台中文歌曲龙虎榜',
65 | 17: '华语金曲榜',
66 | 18: '中国嘻哈榜',
67 | 19: '法国 NRJ EuroHot 30周榜',
68 | 20: '台湾Hito排行榜',
69 | 21: 'Beatport全球电子舞曲榜',
70 | 22: '云音乐ACG音乐榜',
71 | 23: '云音乐说唱榜',
72 | 24: '云音乐古典音乐榜',
73 | 25: '云音乐电音榜',
74 | 26: '抖音排行榜',
75 | 27: '新声榜',
76 | 28: '云音乐韩语榜',
77 | 29: '英国Q杂志中文版周榜',
78 | 30: '电竞音乐榜',
79 | 31: '云音乐欧美热歌榜',
80 | 32: '云音乐欧美新歌榜',
81 | 33: '说唱TOP榜',
82 | };
83 |
--------------------------------------------------------------------------------
/lib/widget/gradient_text.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_music_player/model/color_provider.dart';
3 | import 'package:provider/provider.dart';
4 |
5 | class GradientText extends StatefulWidget {
6 | final Text text;
7 | final double offsetX;
8 | final Color colorBg;
9 | _GradientTextState _state;
10 | GradientText({this.text, this.offsetX = 0.0, this.colorBg = Colors.white});
11 |
12 | @override
13 | _GradientTextState createState() {
14 | _state = _GradientTextState();
15 | return _state;
16 | }
17 |
18 | int retryCount = 0;
19 | void setOffsetX(double offsetX) {
20 | if (_state == null) {
21 | print('_LyricPageState is null, retryCount: $retryCount');
22 | Future.delayed(Duration(milliseconds: 200)).then((_) {
23 | retryCount++;
24 | if (retryCount < 5) {
25 | setOffsetX(offsetX);
26 | }
27 | });
28 | } else {
29 | retryCount = 0;
30 | _state.setOffsetX(offsetX);
31 | }
32 | }
33 | }
34 |
35 | class _GradientTextState extends State {
36 | double offsetX = 0.0;
37 |
38 | @override
39 | void initState() {
40 | super.initState();
41 | offsetX = widget.offsetX;
42 | }
43 |
44 | setOffsetX(offsetX) {
45 | if (!mounted) return;
46 | //print('setOffset: $offsetX');
47 | setState(() {
48 | this.offsetX = offsetX;
49 | });
50 | }
51 |
52 | @override
53 | Widget build(BuildContext context) {
54 | if (widget.text.data.isEmpty) {
55 | return widget.text;
56 | }
57 |
58 | ColorStyleProvider colorProvider = Provider.of(context);
59 | final Gradient gradient = LinearGradient(
60 | colors: [colorProvider.getLightColor(), widget.colorBg],
61 | stops: [0.5, 0.65]); // 设置渐变的起始位置
62 |
63 | /// 参考:https://juejin.im/post/5c860c0a6fb9a049e702ef39
64 | return ShaderMask(
65 | // 遮罩层src,通过不同的BlendMode(混合模式)叠在dst上,产生不同的效果。
66 | shaderCallback: (bounds) {
67 | //print('bounds: ${bounds.width}');
68 | return gradient.createShader(
69 | Offset(-bounds.width / 2 + bounds.width * this.offsetX, 0.0) &
70 | bounds.size);
71 | },
72 | blendMode: BlendMode.srcIn,
73 | child: widget.text,
74 | );
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/lib/pages/favorite_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_music_player/model/color_provider.dart';
3 | import 'package:flutter_music_player/pages/play_list_tab_page.dart';
4 | import 'package:provider/provider.dart';
5 | import 'favorite_music.dart';
6 |
7 | class FavoritePage extends StatefulWidget {
8 | FavoritePage({Key key}) : super(key: key);
9 |
10 | _FavoritePageState createState() => _FavoritePageState();
11 | }
12 |
13 | const types = ['单曲', '歌单'];
14 |
15 | class _FavoritePageState extends State
16 | with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin {
17 | TabController tabController; //tab控制器
18 |
19 | @override
20 | bool get wantKeepAlive => false;
21 |
22 | @override
23 | void initState() {
24 | super.initState();
25 | //初始化controller并添加监听
26 | tabController = TabController(length: types.length, vsync: this);
27 | }
28 |
29 | Widget mWidget;
30 | @override
31 | Widget build(BuildContext context) {
32 | super.build(context);
33 | ColorStyleProvider colorStyleProvider =
34 | Provider.of(context);
35 | return Scaffold(
36 | appBar: AppBar(
37 | backgroundColor: Color(0x07000000),
38 | elevation: 0,
39 | title: TabBar(
40 | controller: tabController, //控制器
41 | indicatorColor: colorStyleProvider.getIndicatorColor(),
42 | labelColor: colorStyleProvider.getCurrentColor(),
43 | unselectedLabelColor: Colors.black45,
44 | labelStyle: TextStyle(fontWeight: FontWeight.w600), //选中的样式
45 | unselectedLabelStyle: TextStyle(fontSize: 14), //未选中的样式
46 | isScrollable: true, //是否可滑动
47 | //tab标签
48 | tabs: types
49 | .map((name) => Tab(
50 | text: name,
51 | ))
52 | .toList(),
53 | //点击事件
54 | onTap: (int i) {
55 | tabController.animateTo(i);
56 | },
57 | ),
58 | ),
59 | body: TabBarView(
60 | controller: tabController,
61 | children: [
62 | FavoriteMusic(),
63 | PlayListTabPage(
64 | type: PlayListTabPage.TYPE_DB,
65 | heroTag: 'from_fav',
66 | error: '您还没有收藏歌单\n可在歌单页右上角进行收藏。')
67 | ],
68 | ),
69 | );
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/lib/widget/song_item_grid.dart:
--------------------------------------------------------------------------------
1 | import 'package:cached_network_image/cached_network_image.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_music_player/model/song_util.dart';
4 | import 'package:flutter_music_player/pages/player_page.dart';
5 |
6 | class SongItemOfGrid extends StatelessWidget {
7 | final List songList;
8 | final int index;
9 | /* static final Image defaultCover = Image.asset('images/music_cover.jpg',
10 | fit: BoxFit.cover,
11 | color: Colors.black54,
12 | colorBlendMode: BlendMode.dstOut); */
13 |
14 | SongItemOfGrid(this.songList, this.index);
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | Map song = this.songList[index];
19 | String image = SongUtil.getSongImage(song, size: 200);
20 | return Stack(
21 | alignment: AlignmentDirectional.bottomStart,
22 | children: [
23 | ClipRRect(
24 | borderRadius: BorderRadius.all(Radius.circular(4.0)),
25 | child: CachedNetworkImage(
26 | imageUrl: image,
27 | fit: BoxFit.fill,
28 | //placeholder: (context, url) => Container(color: Colors.black12)
29 | ),
30 | ),
31 | ClipRRect(
32 | borderRadius: BorderRadius.only(
33 | bottomLeft: Radius.circular(4.0),
34 | bottomRight: Radius.circular(4.0)),
35 | child: Container(
36 | width: double.infinity,
37 | color: Color.fromARGB(80, 0, 0, 0),
38 | padding: EdgeInsets.all(6.0),
39 | child: Text(
40 | song['name'],
41 | overflow: TextOverflow.ellipsis,
42 | style: TextStyle(fontSize: 12.0, color: Colors.white),
43 | )),
44 | ),
45 | Positioned.fill(
46 | child: Material(
47 | color: Colors.transparent,
48 | child: InkWell(
49 | // ???
50 | splashColor: Colors.white.withOpacity(0.3),
51 | highlightColor: Colors.white.withOpacity(0.1),
52 | onTap: () {
53 | PlayerPage.gotoPlayer(context,
54 | list: songList, index: index);
55 | }),
56 | ),
57 | ),
58 | ]);
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/lib/dao/music_db_playlist.dart:
--------------------------------------------------------------------------------
1 | import 'package:sqflite/sqflite.dart';
2 | import 'music_db.dart';
3 |
4 | class PlayListDB {
5 | static const table_name = 't_play_list';
6 |
7 | /// 单例对象的写法
8 | // 私有静态instance
9 | static PlayListDB _instance;
10 |
11 | // 对外访问点,指向私有静态方法
12 | factory PlayListDB() => _getInstance();
13 |
14 | static PlayListDB _getInstance() {
15 | if (_instance == null) {
16 | _instance = PlayListDB._();
17 | }
18 | return _instance;
19 | }
20 |
21 | // 将默认构造函数私有化
22 | PlayListDB._();
23 |
24 | /// 在数据库onCreate的时候,创建表。
25 | /// 注意:onUpgrade中添加的字段要在这儿添加,不然第一次安装就没有那个字段了。
26 | createTable(Database db) {
27 | db.execute('''create table $table_name (
28 | id integer primary key,
29 | name text not null,
30 | cover text,
31 | createTime integer)
32 | ''');
33 | }
34 |
35 | Future addPlayList(Map playList) async {
36 | var fav = {
37 | 'id': playList['id'],
38 | 'name': playList['name'],
39 | 'cover': playList['coverImgUrl'],
40 | // 查看sqflite文档,发现不支持DateTime字段,用int来存储。
41 | 'createTime': DateTime.now().millisecondsSinceEpoch,
42 | };
43 |
44 | print('fav: $fav, playList:$playList');
45 | return (await MusicDB().getDB()).insert(table_name, fav);
46 | }
47 |
48 | Future