├── flutter2048 ├── android │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── app │ │ ├── src │ │ │ └── main │ │ │ │ ├── res │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values │ │ │ │ │ └── styles.xml │ │ │ │ └── drawable │ │ │ │ │ └── launch_background.xml │ │ │ │ ├── java │ │ │ │ └── cz │ │ │ │ │ └── flutter2048 │ │ │ │ │ └── MainActivity.java │ │ │ │ └── AndroidManifest.xml │ │ └── build.gradle │ ├── .gitignore │ ├── settings.gradle │ ├── build.gradle │ └── gradlew.bat ├── ios │ ├── Flutter │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── AppFrameworkInfo.plist │ ├── Runner │ │ ├── AppDelegate.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 │ │ ├── main.m │ │ ├── AppDelegate.m │ │ ├── Base.lproj │ │ │ ├── Main.storyboard │ │ │ └── LaunchScreen.storyboard │ │ └── Info.plist │ ├── Runner.xcworkspace │ │ └── contents.xcworkspacedata │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ └── .gitignore ├── .gitignore ├── .metadata ├── README.md ├── flutter2048.iml ├── test │ └── widget_test.dart ├── lib │ ├── logic │ │ ├── matrixUtil.dart │ │ └── game.dart │ ├── widget │ │ ├── chessboard.dart │ │ ├── chess.dart │ │ └── scoreTitle.dart │ └── main.dart ├── flutter2048_android.iml └── pubspec.yaml ├── music_player ├── android │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── app │ │ ├── src │ │ │ └── main │ │ │ │ ├── res │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values │ │ │ │ │ └── styles.xml │ │ │ │ └── drawable │ │ │ │ │ └── launch_background.xml │ │ │ │ ├── java │ │ │ │ └── cz │ │ │ │ │ └── musicplayer │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── methodChannel │ │ │ │ │ └── PlayerMethodHandler.java │ │ │ │ └── AndroidManifest.xml │ │ └── build.gradle │ ├── .gitignore │ ├── settings.gradle │ ├── build.gradle │ └── gradlew.bat ├── ios │ ├── Flutter │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── AppFrameworkInfo.plist │ ├── Runner │ │ ├── AppDelegate.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 │ │ ├── main.m │ │ ├── AppDelegate.m │ │ ├── Info.plist │ │ └── Base.lproj │ │ │ ├── Main.storyboard │ │ │ └── LaunchScreen.storyboard │ ├── Runner.xcworkspace │ │ └── contents.xcworkspacedata │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ └── .gitignore ├── .gitignore ├── README.md ├── .metadata ├── music_player.iml ├── test │ └── widget_test.dart ├── music_player_android.iml ├── pubspec.yaml └── lib │ └── main.dart ├── zhihu_daily ├── android │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── app │ │ ├── src │ │ │ └── main │ │ │ │ ├── res │ │ │ │ ├── values │ │ │ │ │ ├── colors.xml │ │ │ │ │ └── styles.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ └── drawable │ │ │ │ │ └── launch_background.xml │ │ │ │ ├── java │ │ │ │ └── cz │ │ │ │ │ └── zhihudaily │ │ │ │ │ └── MainActivity.java │ │ │ │ └── AndroidManifest.xml │ │ └── build.gradle │ ├── .gitignore │ ├── settings.gradle │ ├── build.gradle │ └── gradlew.bat ├── ios │ ├── Flutter │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── AppFrameworkInfo.plist │ ├── Runner │ │ ├── AppDelegate.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 │ │ ├── main.m │ │ ├── AppDelegate.m │ │ ├── Info.plist │ │ └── Base.lproj │ │ │ ├── Main.storyboard │ │ │ └── LaunchScreen.storyboard │ ├── Runner.xcworkspace │ │ └── contents.xcworkspacedata │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ └── .gitignore ├── res │ └── images │ │ ├── logo.png │ │ ├── avatar.png │ │ ├── login.png │ │ └── splash.png ├── lib │ ├── main.dart │ ├── model │ │ ├── usrInfo.dart │ │ ├── theme.dart │ │ └── story.dart │ ├── route │ │ ├── routeInterceptor.dart │ │ ├── routeModel.dart │ │ ├── interceptors │ │ │ └── loginInterceptor.dart │ │ └── routeGenerator.dart │ ├── constants │ │ ├── urls.dart │ │ └── pages.dart │ ├── widgets │ │ ├── circleImage.dart │ │ ├── loadMoreFooter.dart │ │ ├── animatedLogo.dart │ │ └── homeBanner.dart │ ├── fragment │ │ └── themeFragment.dart │ ├── utils │ │ └── timeUtil.dart │ ├── pages │ │ ├── comment.dart │ │ ├── collection.dart │ │ ├── home.dart │ │ ├── login.dart │ │ ├── splash.dart │ │ └── storyDetail.dart │ ├── dialog │ │ └── moreMenuDialog.dart │ ├── application.dart │ └── manager │ │ ├── usrInfoManager.dart │ │ ├── collectionManager.dart │ │ └── skinManager.dart ├── .gitignore ├── .metadata ├── test │ └── widget_test.dart ├── zhihu_daily.iml ├── zhihu_daily_android.iml ├── pubspec.yaml └── README.md ├── screenshot ├── 2048.png ├── baiping.gif ├── baiping_opt.gif ├── zhihu-dark.png ├── zhihu-home.png ├── zhihu-login.png ├── zhihu-menu.png ├── flutterstudio.png ├── zhihu-detail.png ├── zhihu-drawer.png ├── zhihu-splash.gif └── zhihu-collection.png └── README.md /flutter2048/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /flutter2048/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /music_player/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /music_player/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /zhihu_daily/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /zhihu_daily/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /flutter2048/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /music_player/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /zhihu_daily/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /screenshot/2048.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/screenshot/2048.png -------------------------------------------------------------------------------- /screenshot/baiping.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/screenshot/baiping.gif -------------------------------------------------------------------------------- /screenshot/baiping_opt.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/screenshot/baiping_opt.gif -------------------------------------------------------------------------------- /screenshot/zhihu-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/screenshot/zhihu-dark.png -------------------------------------------------------------------------------- /screenshot/zhihu-home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/screenshot/zhihu-home.png -------------------------------------------------------------------------------- /screenshot/zhihu-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/screenshot/zhihu-login.png -------------------------------------------------------------------------------- /screenshot/zhihu-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/screenshot/zhihu-menu.png -------------------------------------------------------------------------------- /screenshot/flutterstudio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/screenshot/flutterstudio.png -------------------------------------------------------------------------------- /screenshot/zhihu-detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/screenshot/zhihu-detail.png -------------------------------------------------------------------------------- /screenshot/zhihu-drawer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/screenshot/zhihu-drawer.png -------------------------------------------------------------------------------- /screenshot/zhihu-splash.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/screenshot/zhihu-splash.gif -------------------------------------------------------------------------------- /screenshot/zhihu-collection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/screenshot/zhihu-collection.png -------------------------------------------------------------------------------- /zhihu_daily/res/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/res/images/logo.png -------------------------------------------------------------------------------- /zhihu_daily/res/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/res/images/avatar.png -------------------------------------------------------------------------------- /zhihu_daily/res/images/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/res/images/login.png -------------------------------------------------------------------------------- /zhihu_daily/res/images/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/res/images/splash.png -------------------------------------------------------------------------------- /flutter2048/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /flutter2048/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /music_player/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /zhihu_daily/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /music_player/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /zhihu_daily/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:zhihu_daily/application.dart'; 3 | 4 | void main() { 5 | runApp(Application()); 6 | } -------------------------------------------------------------------------------- /zhihu_daily/android/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ff17181a 4 | -------------------------------------------------------------------------------- /zhihu_daily/lib/model/usrInfo.dart: -------------------------------------------------------------------------------- 1 | class UsrInfo { 2 | final int uid; 3 | final String name; 4 | final String avatar; 5 | 6 | UsrInfo(this.uid, this.name, this.avatar); 7 | } -------------------------------------------------------------------------------- /flutter2048/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .atom/ 3 | .dart_tool/ 4 | .idea 5 | .vscode/ 6 | .packages 7 | .pub/ 8 | build/ 9 | ios/.generated/ 10 | packages 11 | .flutter-plugins 12 | -------------------------------------------------------------------------------- /music_player/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .atom/ 3 | .dart_tool/ 4 | .idea 5 | .vscode/ 6 | .packages 7 | .pub/ 8 | build/ 9 | ios/.generated/ 10 | packages 11 | .flutter-plugins 12 | -------------------------------------------------------------------------------- /zhihu_daily/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .atom/ 3 | .dart_tool/ 4 | .idea 5 | .vscode/ 6 | .packages 7 | .pub/ 8 | build/ 9 | ios/.generated/ 10 | packages 11 | .flutter-plugins 12 | -------------------------------------------------------------------------------- /flutter2048/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter2048/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter2048/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter2048/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /music_player/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /music_player/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /music_player/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /zhihu_daily/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /zhihu_daily/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /zhihu_daily/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /zhihu_daily/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter2048/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /music_player/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /music_player/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /zhihu_daily/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /music_player/README.md: -------------------------------------------------------------------------------- 1 | # music_player 2 | 3 | A new Flutter application. 4 | 5 | ## Getting Started 6 | 7 | For help getting started with Flutter, view our online 8 | [documentation](https://flutter.io/). 9 | -------------------------------------------------------------------------------- /music_player/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /zhihu_daily/lib/route/routeInterceptor.dart: -------------------------------------------------------------------------------- 1 | import 'routeModel.dart'; 2 | 3 | abstract class RouteInterceptor { 4 | bool intercept(RouteModel routeModel); 5 | RouteModel process(RouteModel routeModel); 6 | } -------------------------------------------------------------------------------- /flutter2048/android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | *.class 3 | .gradle 4 | /local.properties 5 | /.idea/workspace.xml 6 | /.idea/libraries 7 | .DS_Store 8 | /build 9 | /captures 10 | GeneratedPluginRegistrant.java 11 | -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /music_player/android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | *.class 3 | .gradle 4 | /local.properties 5 | /.idea/workspace.xml 6 | /.idea/libraries 7 | .DS_Store 8 | /build 9 | /captures 10 | GeneratedPluginRegistrant.java 11 | -------------------------------------------------------------------------------- /zhihu_daily/android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | *.class 3 | .gradle 4 | /local.properties 5 | /.idea/workspace.xml 6 | /.idea/libraries 7 | .DS_Store 8 | /build 9 | /captures 10 | GeneratedPluginRegistrant.java 11 | -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /music_player/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /music_player/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh8637688/Flutter-Example/HEAD/music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /flutter2048/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /music_player/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter2048/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /music_player/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter2048/ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char * argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /music_player/ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /flutter2048/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-4.1-all.zip 7 | -------------------------------------------------------------------------------- /music_player/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-4.4-all.zip 7 | -------------------------------------------------------------------------------- /zhihu_daily/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-4.1-all.zip 7 | -------------------------------------------------------------------------------- /flutter2048/.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: b397406561f5e7a9c94e28f58d9e49fca0dd58b7 8 | channel: beta 9 | -------------------------------------------------------------------------------- /music_player/.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: 5ab9e70727d858def3a586db7fb98ee580352957 8 | channel: beta 9 | -------------------------------------------------------------------------------- /zhihu_daily/.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: c7ea3ca377e909469c68f2ab878a5bc53d3cf66b 8 | channel: beta 9 | -------------------------------------------------------------------------------- /flutter2048/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. -------------------------------------------------------------------------------- /music_player/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. -------------------------------------------------------------------------------- /zhihu_daily/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. -------------------------------------------------------------------------------- /flutter2048/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /music_player/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /zhihu_daily/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /zhihu_daily/lib/constants/urls.dart: -------------------------------------------------------------------------------- 1 | class Urls { 2 | static const String _HOST = 'https://news-at.zhihu.com/api/4'; 3 | 4 | static const String THEME_LIST = _HOST + '/themes'; 5 | static const String NEWS_LAST = _HOST + '/news/latest'; 6 | static const String NEWS_BEFORE = _HOST + '/news/before/'; 7 | static const String NEWS_EXTRA_INFO = _HOST + '/story-extra/'; 8 | static const String NEWS_DETAIL_WEB = 'http://daily.zhihu.com/story/'; 9 | } -------------------------------------------------------------------------------- /zhihu_daily/lib/model/theme.dart: -------------------------------------------------------------------------------- 1 | class ThemeModel { 2 | final int id; 3 | final String name; 4 | final String thumbnail; 5 | final String description; 6 | 7 | ThemeModel(this.id, this.name, this.thumbnail, this.description); 8 | 9 | ThemeModel.fromJson(Map json) 10 | : id = json['id'], 11 | name = json['name'], 12 | thumbnail = json['thumbnail'], 13 | description = json['description']; 14 | } -------------------------------------------------------------------------------- /zhihu_daily/android/app/src/main/java/cz/zhihudaily/MainActivity.java: -------------------------------------------------------------------------------- 1 | package cz.zhihudaily; 2 | 3 | import android.os.Bundle; 4 | import io.flutter.app.FlutterActivity; 5 | import io.flutter.plugins.GeneratedPluginRegistrant; 6 | 7 | public class MainActivity extends FlutterActivity { 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | GeneratedPluginRegistrant.registerWith(this); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /flutter2048/android/app/src/main/java/cz/flutter2048/MainActivity.java: -------------------------------------------------------------------------------- 1 | package cz.flutter2048; 2 | 3 | import android.os.Bundle; 4 | 5 | import io.flutter.app.FlutterActivity; 6 | import io.flutter.plugins.GeneratedPluginRegistrant; 7 | 8 | public class MainActivity extends FlutterActivity { 9 | @Override 10 | protected void onCreate(Bundle savedInstanceState) { 11 | super.onCreate(savedInstanceState); 12 | GeneratedPluginRegistrant.registerWith(this); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /flutter2048/README.md: -------------------------------------------------------------------------------- 1 | # flutter2048 2 | 3 | Flutter 2048 4 | 5 | Flutter版本的2048,作为第一个练手的Flutter项目,包含了下面几个知识点: 6 | * 自定义控件,[StatefulWidget和StatelessWidget](https://flutter.io/tutorials/interactive/#stateful-stateless); 7 | * 本地存储,[SharedPreferences](https://pub.dartlang.org/packages/shared_preferences) 8 | * 手势,[GestureDetector](https://flutter.io/gestures/) 9 | -------------------------------------------------------------------------------- /flutter2048/ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #include "AppDelegate.h" 2 | #include "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 7 | [GeneratedPluginRegistrant registerWithRegistry:self]; 8 | // Override point for customization after application launch. 9 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 10 | } 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /zhihu_daily/lib/widgets/circleImage.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | class CircleImage extends StatelessWidget { 4 | final ImageProvider image; 5 | 6 | CircleImage(this.image, {Key key}) : super(key: key); 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return new Container( 11 | decoration: new BoxDecoration( 12 | shape: BoxShape.circle, 13 | image: new DecorationImage(image: image) 14 | ) 15 | ); 16 | } 17 | } -------------------------------------------------------------------------------- /music_player/ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #include "AppDelegate.h" 2 | #include "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #include "AppDelegate.h" 2 | #include "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /flutter2048/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /music_player/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /zhihu_daily/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /flutter2048/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 | -------------------------------------------------------------------------------- /music_player/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 | -------------------------------------------------------------------------------- /zhihu_daily/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 | -------------------------------------------------------------------------------- /zhihu_daily/lib/fragment/themeFragment.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:zhihu_daily/model/theme.dart'; 3 | 4 | class ThemeFragment extends StatefulWidget { 5 | final ThemeModel theme; 6 | 7 | ThemeFragment(this.theme, {Key key}) : super(key: key); 8 | 9 | @override 10 | State createState() { 11 | return _FragmentState(); 12 | } 13 | } 14 | 15 | class _FragmentState extends State { 16 | @override 17 | Widget build(BuildContext context) { 18 | return Text(widget.theme.name); 19 | } 20 | } -------------------------------------------------------------------------------- /flutter2048/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 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 | -------------------------------------------------------------------------------- /music_player/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 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 | -------------------------------------------------------------------------------- /zhihu_daily/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 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 | -------------------------------------------------------------------------------- /zhihu_daily/lib/model/story.dart: -------------------------------------------------------------------------------- 1 | class StoryModel { 2 | final String title; 3 | final String image; 4 | final int id; 5 | 6 | StoryModel(this.id, this.title, {this.image}); 7 | 8 | StoryModel.fromJson(Map json) 9 | : this(json['id'], json['title'], 10 | image: json['image'] != null ? json['image'] : (json['images'] != null 11 | ? json['images'][0] 12 | : null)); 13 | 14 | Map toJson() { 15 | return { 16 | 'id': id, 17 | 'title': title, 18 | 'image': image 19 | }; 20 | } 21 | } -------------------------------------------------------------------------------- /music_player/android/app/src/main/java/cz/musicplayer/MainActivity.java: -------------------------------------------------------------------------------- 1 | package cz.musicplayer; 2 | 3 | import android.os.Bundle; 4 | 5 | import cz.musicplayer.methodChannel.PlayerMethodHandler; 6 | import io.flutter.app.FlutterActivity; 7 | import io.flutter.plugins.GeneratedPluginRegistrant; 8 | 9 | public class MainActivity extends FlutterActivity { 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | GeneratedPluginRegistrant.registerWith(this); 14 | 15 | PlayerMethodHandler.register(getFlutterView()); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /flutter2048/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.0.1' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /zhihu_daily/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.0.1' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /music_player/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.1.2' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /zhihu_daily/lib/route/routeModel.dart: -------------------------------------------------------------------------------- 1 | class RouteModel { 2 | final String uri; 3 | String _path; 4 | Map _params; 5 | 6 | String get path => _path; 7 | Map get params => _params; 8 | 9 | RouteModel(this.uri) { 10 | _resolveURI(uri); 11 | } 12 | 13 | void _resolveURI(String uri) { 14 | List resoled = uri.split('?'); 15 | _path = resoled[0]; 16 | if (resoled.length > 1) { 17 | _params = Map(); 18 | resoled[1].split('&').forEach((paramStr) { 19 | List item = paramStr.split('='); 20 | _params.putIfAbsent(item[0], () => Uri.decodeComponent(item[1])); 21 | }); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /flutter2048/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 | *.pbxuser 16 | *.mode1v3 17 | *.mode2v3 18 | *.perspectivev3 19 | 20 | !default.pbxuser 21 | !default.mode1v3 22 | !default.mode2v3 23 | !default.perspectivev3 24 | 25 | xcuserdata 26 | 27 | *.moved-aside 28 | 29 | *.pyc 30 | *sync/ 31 | Icon? 32 | .tags* 33 | 34 | /Flutter/app.flx 35 | /Flutter/app.zip 36 | /Flutter/flutter_assets/ 37 | /Flutter/App.framework 38 | /Flutter/Flutter.framework 39 | /Flutter/Generated.xcconfig 40 | /ServiceDefinitions.json 41 | 42 | Pods/ 43 | -------------------------------------------------------------------------------- /zhihu_daily/lib/route/interceptors/loginInterceptor.dart: -------------------------------------------------------------------------------- 1 | import 'package:zhihu_daily/route/routeInterceptor.dart'; 2 | import 'package:zhihu_daily/route/routeModel.dart'; 3 | import 'package:zhihu_daily/constants/pages.dart'; 4 | import 'package:zhihu_daily/manager/usrInfoManager.dart'; 5 | 6 | class LoginInterceptor extends RouteInterceptor { 7 | @override 8 | bool intercept(RouteModel routeModel) { 9 | if (routeModel.path == Pages.COLLECTION) { 10 | return !UsrInfoManager().hasLogin(); 11 | } 12 | return false; 13 | } 14 | 15 | @override 16 | RouteModel process(RouteModel routeModel) { 17 | String params = '?nextPage=' + routeModel.uri; 18 | return RouteModel(Pages.LOGIN + params); 19 | } 20 | } -------------------------------------------------------------------------------- /music_player/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/app.flx 37 | /Flutter/app.zip 38 | /Flutter/flutter_assets/ 39 | /Flutter/App.framework 40 | /Flutter/Flutter.framework 41 | /Flutter/Generated.xcconfig 42 | /ServiceDefinitions.json 43 | 44 | Pods/ 45 | .symlinks/ 46 | -------------------------------------------------------------------------------- /zhihu_daily/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/app.flx 37 | /Flutter/app.zip 38 | /Flutter/flutter_assets/ 39 | /Flutter/App.framework 40 | /Flutter/Flutter.framework 41 | /Flutter/Generated.xcconfig 42 | /ServiceDefinitions.json 43 | 44 | Pods/ 45 | .symlinks/ 46 | -------------------------------------------------------------------------------- /zhihu_daily/lib/utils/timeUtil.dart: -------------------------------------------------------------------------------- 1 | bool sameDay(DateTime time1, DateTime time2) { 2 | return time1.year == time2.year && time1.month == time2.month && 3 | time1.day == time2.day; 4 | } 5 | 6 | String formatTime(DateTime time) { 7 | return time.month.toString() + '月' + time.day.toString() + '日 ' + 8 | weekInChinese(time.weekday); 9 | } 10 | 11 | String weekInChinese(int week) { 12 | switch (week) { 13 | case 1: 14 | return '星期一'; 15 | case 2: 16 | return '星期二'; 17 | case 3: 18 | return '星期三'; 19 | case 4: 20 | return '星期四'; 21 | case 5: 22 | return '星期五'; 23 | case 6: 24 | return '星期六'; 25 | case 7: 26 | return '星期日'; 27 | default: 28 | return ''; 29 | } 30 | } -------------------------------------------------------------------------------- /music_player/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | -------------------------------------------------------------------------------- /zhihu_daily/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | -------------------------------------------------------------------------------- /zhihu_daily/lib/pages/comment.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class PageStoryComment extends StatefulWidget { 4 | final int storyID; 5 | final int longComments; 6 | final int shortComments; 7 | 8 | PageStoryComment(this.storyID, this.longComments, this.shortComments); 9 | 10 | PageStoryComment.fromParams(Map params) 11 | : storyID = int.parse(params['storyID']), 12 | longComments = int.parse(params['longComments']), 13 | shortComments = int.parse(params['shortComments']); 14 | 15 | @override 16 | State createState() { 17 | return _PageState(); 18 | } 19 | } 20 | 21 | class _PageState extends State { 22 | @override 23 | void initState() { 24 | super.initState(); 25 | } 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | return Scaffold( 30 | body: Text('该页面被 WebView 遮挡,无法正常展示', 31 | style: TextStyle(fontSize: 24.0),) 32 | ); 33 | } 34 | } -------------------------------------------------------------------------------- /flutter2048/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | UIRequiredDeviceCapabilities 24 | 25 | arm64 26 | 27 | MinimumOSVersion 28 | 8.0 29 | 30 | 31 | -------------------------------------------------------------------------------- /flutter2048/flutter2048.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /zhihu_daily/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // To perform an interaction with a widget in your test, use the WidgetTester utility that Flutter 3 | // provides. For example, you can send tap and scroll gestures. You can also use WidgetTester to 4 | // find child widgets in the widget tree, read text, and verify that the values of widget properties 5 | // are correct. 6 | 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter_test/flutter_test.dart'; 9 | 10 | void main() { 11 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 12 | // Build our app and trigger a frame. 13 | 14 | // Verify that our counter starts at 0. 15 | expect(find.text('0'), findsOneWidget); 16 | expect(find.text('1'), findsNothing); 17 | 18 | // Tap the '+' icon and trigger a frame. 19 | await tester.tap(find.byIcon(Icons.add)); 20 | await tester.pump(); 21 | 22 | // Verify that our counter has incremented. 23 | expect(find.text('0'), findsNothing); 24 | expect(find.text('1'), findsOneWidget); 25 | }); 26 | } 27 | -------------------------------------------------------------------------------- /zhihu_daily/zhihu_daily.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /music_player/music_player.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /music_player/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // To perform an interaction with a widget in your test, use the WidgetTester utility that Flutter 3 | // provides. For example, you can send tap and scroll gestures. You can also use WidgetTester to 4 | // find child widgets in the widget tree, read text, and verify that the values of widget properties 5 | // are correct. 6 | 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter_test/flutter_test.dart'; 9 | 10 | import 'package:music_player/main.dart'; 11 | 12 | void main() { 13 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 14 | // Build our app and trigger a frame. 15 | await tester.pumpWidget(new MyApp()); 16 | 17 | // Verify that our counter starts at 0. 18 | expect(find.text('0'), findsOneWidget); 19 | expect(find.text('1'), findsNothing); 20 | 21 | // Tap the '+' icon and trigger a frame. 22 | await tester.tap(find.byIcon(Icons.add)); 23 | await tester.pump(); 24 | 25 | // Verify that our counter has incremented. 26 | expect(find.text('0'), findsNothing); 27 | expect(find.text('1'), findsOneWidget); 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /flutter2048/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // To perform an interaction with a widget in your test, use the WidgetTester utility that Flutter 3 | // provides. For example, you can send tap and scroll gestures. You can also use WidgetTester to 4 | // find child widgets in the widget tree, read text, and verify that the values of widget properties 5 | // are correct. 6 | 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter_test/flutter_test.dart'; 9 | 10 | import 'package:flutter2048/main.dart'; 11 | 12 | void main() { 13 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 14 | // Build our app and trigger a frame. 15 | await tester.pumpWidget(new Flutter2048()); 16 | 17 | // Verify that our counter starts at 0. 18 | expect(find.text('0'), findsOneWidget); 19 | expect(find.text('1'), findsNothing); 20 | 21 | // Tap the '+' icon and trigger a frame. 22 | await tester.tap(find.byIcon(Icons.add)); 23 | await tester.pump(); 24 | 25 | // Verify that our counter has incremented. 26 | expect(find.text('0'), findsNothing); 27 | expect(find.text('1'), findsOneWidget); 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /zhihu_daily/lib/widgets/loadMoreFooter.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class LoadMoreFooter extends StatefulWidget { 4 | @override 5 | State createState() { 6 | return _FooterState(); 7 | } 8 | } 9 | 10 | class _FooterState extends State with TickerProviderStateMixin { 11 | AnimationController controller; 12 | 13 | @override 14 | void initState() { 15 | super.initState(); 16 | controller = 17 | AnimationController(vsync: this, duration: Duration(seconds: 1)); 18 | controller.repeat(); 19 | } 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return Padding( 24 | padding: EdgeInsets.symmetric(vertical: 8.0), 25 | child: Row( 26 | mainAxisAlignment: MainAxisAlignment.center, 27 | children: [ 28 | RotationTransition( 29 | turns: controller, 30 | child: Icon(Icons.loop, color: Colors.grey, size: 16.0), 31 | ), 32 | Text(' 正在加载...', style: TextStyle(color: Colors.grey)) 33 | ]), 34 | ); 35 | } 36 | 37 | @override 38 | void dispose() { 39 | super.dispose(); 40 | controller.dispose(); 41 | } 42 | } -------------------------------------------------------------------------------- /zhihu_daily/lib/constants/pages.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:zhihu_daily/route/routeGenerator.dart'; 3 | import 'package:zhihu_daily/pages/splash.dart'; 4 | import 'package:zhihu_daily/pages/home.dart'; 5 | import 'package:zhihu_daily/pages/storyDetail.dart'; 6 | import 'package:zhihu_daily/pages/comment.dart'; 7 | import 'package:zhihu_daily/pages/collection.dart'; 8 | import 'package:zhihu_daily/pages/login.dart'; 9 | 10 | class Pages { 11 | static const String SPLASH = '/splash'; 12 | static const String HOME = '/home'; 13 | static const String STORY_DETAIL = '/story_detail'; 14 | static const String COMMENT = '/comment'; 15 | static const String LOGIN = '/login'; 16 | static const String COLLECTION = '/collection'; 17 | 18 | static Map routes = { 19 | SPLASH: (context, params) => PageSplash(), 20 | HOME: (context, params) => PageHome(), 21 | STORY_DETAIL: (context, params) => PageStoryDetail.fromParams(params), 22 | COMMENT: (context, params) => PageStoryComment.fromParams(params), 23 | LOGIN: (context, params) => PageLogin.fromParams(params), 24 | COLLECTION: (context, params) => PageCollection() 25 | }; 26 | 27 | static Widget firstPage(BuildContext context) { 28 | if (routes.length > 0) { 29 | return routes.entries.first.value(context, null); 30 | } 31 | return Container(); 32 | } 33 | } -------------------------------------------------------------------------------- /flutter2048/lib/logic/matrixUtil.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | class MatrixUtil { 4 | 5 | // 矩阵左右交换 6 | static List flipLR(List matrix) { 7 | int n = sqrt(matrix.length).toInt(); 8 | List newMatrix = []; 9 | for (int i = 0; i < n; i++) { 10 | for (int j = n - 1; j >= 0; j--) { 11 | newMatrix.add(matrix[i * n + j]); 12 | } 13 | } 14 | return newMatrix; 15 | } 16 | 17 | // 矩阵求逆 18 | static List inv(List matrix) { 19 | int n = sqrt(matrix.length).toInt(); 20 | List newMatrix = []; 21 | for (int i = 0; i < n; i++) { 22 | for (int j = 0; j < n; j++) { 23 | newMatrix.add(matrix[j * n + i]); 24 | } 25 | } 26 | return newMatrix; 27 | } 28 | 29 | // 顺时针旋转 30 | static List rot(List matrix) { 31 | int n = sqrt(matrix.length).toInt(); 32 | List newMatrix = []; 33 | for (int i = 0; i < n; i++) { 34 | for (int j = n - 1; j >= 0; j--) { 35 | newMatrix.add(matrix[j * n + i]); 36 | } 37 | } 38 | return newMatrix; 39 | } 40 | 41 | // 逆时针旋转 42 | static List antiRot(List matrix) { 43 | int n = sqrt(matrix.length).toInt(); 44 | List newMatrix = []; 45 | for (int i = n - 1; i >= 0; i--) { 46 | for (int j = 0; j < n; j++) { 47 | newMatrix.add(matrix[j * n + i]); 48 | } 49 | } 50 | return newMatrix; 51 | } 52 | } -------------------------------------------------------------------------------- /flutter2048/flutter2048_android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /zhihu_daily/zhihu_daily_android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /music_player/music_player_android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | zhihu_daily 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 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 | -------------------------------------------------------------------------------- /music_player/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | music_player 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 | -------------------------------------------------------------------------------- /flutter2048/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 | -------------------------------------------------------------------------------- /music_player/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 | -------------------------------------------------------------------------------- /zhihu_daily/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 | -------------------------------------------------------------------------------- /zhihu_daily/lib/dialog/moreMenuDialog.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:zhihu_daily/manager/skinManager.dart'; 3 | 4 | class MoreMenuDialog extends StatefulWidget { 5 | @override 6 | State createState() { 7 | return _DialogState(); 8 | } 9 | } 10 | 11 | class _DialogState extends State { 12 | SkinManager skinManager = SkinManager(); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return Align( 17 | alignment: Alignment.topRight, 18 | child: ConstrainedBox( 19 | constraints: const BoxConstraints(minWidth: 180.0), 20 | child: Material( 21 | elevation: 24.0, 22 | child: SingleChildScrollView(child: _buildMenu()), 23 | type: MaterialType.card,), 24 | ),); 25 | } 26 | 27 | Widget _buildMenu() { 28 | return Column( 29 | crossAxisAlignment: CrossAxisAlignment.start, 30 | children: [ 31 | _buildMenuItem( 32 | skinManager.brightness == Brightness.light ? '夜间模式' : '日间模式', () { 33 | skinManager.setBrightness(context, 34 | skinManager.brightness == Brightness.light 35 | ? Brightness.dark 36 | : Brightness.light); 37 | Navigator.of(context).pop(); 38 | },), 39 | _buildMenuItem('设置选项', () { 40 | Navigator.of(context).pop(); 41 | }) 42 | ], 43 | ); 44 | } 45 | 46 | Widget _buildMenuItem(String title, VoidCallback onTap) { 47 | return GestureDetector( 48 | onTap: onTap, 49 | child: Padding( 50 | padding: EdgeInsets.all(12.0), 51 | child: Text(title, style: TextStyle(fontSize: 17.0),), 52 | ),); 53 | } 54 | } -------------------------------------------------------------------------------- /flutter2048/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | apply plugin: 'com.android.application' 15 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 16 | 17 | android { 18 | compileSdkVersion 27 19 | 20 | lintOptions { 21 | disable 'InvalidPackage' 22 | } 23 | 24 | defaultConfig { 25 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 26 | applicationId "cz.flutter2048" 27 | minSdkVersion 16 28 | targetSdkVersion 27 29 | versionCode 1 30 | versionName "1.0" 31 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 32 | } 33 | 34 | buildTypes { 35 | release { 36 | // TODO: Add your own signing config for the release build. 37 | // Signing with the debug keys for now, so `flutter run --release` works. 38 | signingConfig signingConfigs.debug 39 | } 40 | } 41 | } 42 | 43 | flutter { 44 | source '../..' 45 | } 46 | 47 | dependencies { 48 | testImplementation 'junit:junit:4.12' 49 | androidTestImplementation 'com.android.support.test:runner:1.0.1' 50 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' 51 | } 52 | -------------------------------------------------------------------------------- /zhihu_daily/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | apply plugin: 'com.android.application' 15 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 16 | 17 | android { 18 | compileSdkVersion 27 19 | 20 | lintOptions { 21 | disable 'InvalidPackage' 22 | } 23 | 24 | defaultConfig { 25 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 26 | applicationId "cz.zhihudaily" 27 | minSdkVersion 16 28 | targetSdkVersion 27 29 | versionCode 1 30 | versionName "1.0" 31 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 32 | } 33 | 34 | buildTypes { 35 | release { 36 | // TODO: Add your own signing config for the release build. 37 | // Signing with the debug keys for now, so `flutter run --release` works. 38 | signingConfig signingConfigs.debug 39 | } 40 | } 41 | } 42 | 43 | flutter { 44 | source '../..' 45 | } 46 | 47 | dependencies { 48 | testImplementation 'junit:junit:4.12' 49 | androidTestImplementation 'com.android.support.test:runner:1.0.1' 50 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' 51 | } 52 | -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | flutter2048 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | arm64 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | UIViewControllerBasedStatusBarAppearance 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /flutter2048/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter2048 2 | description: flutter 2048 3 | 4 | dependencies: 5 | flutter: 6 | sdk: flutter 7 | 8 | # The following adds the Cupertino Icons font to your application. 9 | # Use with the CupertinoIcons class for iOS style icons. 10 | cupertino_icons: ^0.1.0 11 | shared_preferences: ^0.4.2 12 | 13 | dev_dependencies: 14 | flutter_test: 15 | sdk: flutter 16 | 17 | 18 | # For information on the generic Dart part of this file, see the 19 | # following page: https://www.dartlang.org/tools/pub/pubspec 20 | 21 | # The following section is specific to Flutter. 22 | flutter: 23 | 24 | # The following line ensures that the Material Icons font is 25 | # included with your application, so that you can use the icons in 26 | # the material Icons class. 27 | uses-material-design: true 28 | 29 | # To add assets to your application, add an assets section, like this: 30 | # assets: 31 | # - images/a_dot_burr.jpeg 32 | # - images/a_dot_ham.jpeg 33 | 34 | # An image asset can refer to one or more resolution-specific "variants", see 35 | # https://flutter.io/assets-and-images/#resolution-aware. 36 | 37 | # For details regarding adding assets from package dependencies, see 38 | # https://flutter.io/assets-and-images/#from-packages 39 | 40 | # To add custom fonts to your application, add a fonts section here, 41 | # in this "flutter" section. Each entry in this list should have a 42 | # "family" key with the font family name, and a "fonts" key with a 43 | # list giving the asset and other descriptors for the font. For 44 | # example: 45 | # fonts: 46 | # - family: Schyler 47 | # fonts: 48 | # - asset: fonts/Schyler-Regular.ttf 49 | # - asset: fonts/Schyler-Italic.ttf 50 | # style: italic 51 | # - family: Trajan Pro 52 | # fonts: 53 | # - asset: fonts/TrajanPro.ttf 54 | # - asset: fonts/TrajanPro_Bold.ttf 55 | # weight: 700 56 | # 57 | # For details regarding fonts from package dependencies, 58 | # see https://flutter.io/custom-fonts/#from-packages 59 | -------------------------------------------------------------------------------- /flutter2048/lib/widget/chessboard.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'chess.dart'; 3 | 4 | class Chessboard extends StatelessWidget { 5 | final List chess; 6 | 7 | Chessboard({Key key, @required this.chess}) :super(key: key); 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | List children = new List(); 12 | children.add(_buildChessboard()); 13 | children.addAll(_buildChess()); 14 | return new Container( 15 | width: 330.0, 16 | height: 330.0, 17 | decoration: new BoxDecoration( 18 | color: new Color(0xffbbada3), 19 | borderRadius: new BorderRadius.all(new Radius.circular(5.0)) 20 | ), 21 | padding: EdgeInsets.all(4.0), 22 | margin: EdgeInsets.only(top: 30.0), 23 | child: new Stack( 24 | children: children 25 | ) 26 | ); 27 | } 28 | 29 | List _buildChess() { 30 | List children = new List(); 31 | for (int i = 0; i < chess.length; i++) { 32 | if (chess[i] > 0) { 33 | children.add(new Positioned( 34 | top: (i / 4).floor() * (72.5 + 8), 35 | left: i % 4 * (72.5 + 8), 36 | child: new Chess(value: chess[i]) 37 | )); 38 | } 39 | } 40 | return children; 41 | } 42 | 43 | Widget _buildChessboard() { 44 | return new Column( 45 | children: [ 46 | _buildColumn(), 47 | _buildColumn(), 48 | _buildColumn(), 49 | _buildColumn() 50 | ], 51 | ); 52 | } 53 | 54 | Widget _buildColumn() { 55 | return new Row( 56 | children: [ 57 | _buildCell(), 58 | _buildCell(), 59 | _buildCell(), 60 | _buildCell() 61 | ], 62 | ); 63 | } 64 | 65 | Widget _buildCell() { 66 | return new Container( 67 | width: 72.5, 68 | height: 72.5, 69 | margin: EdgeInsets.all(4.0), 70 | decoration: new BoxDecoration( 71 | color: new Color(0xffd5cbc0), 72 | borderRadius: new BorderRadius.all(new Radius.circular(5.0)) 73 | ), 74 | ); 75 | } 76 | } -------------------------------------------------------------------------------- /zhihu_daily/lib/route/routeGenerator.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:zhihu_daily/route/routeInterceptor.dart'; 3 | import 'package:zhihu_daily/route/routeModel.dart'; 4 | 5 | typedef Widget PageBuilder(BuildContext context, Map params); 6 | 7 | class RouteGenerator { 8 | final Map routes; 9 | List interceptors; 10 | 11 | RouteGenerator({this.routes}); 12 | 13 | Route onGenerateRoute(RouteSettings settings) { 14 | String uri = settings.name; 15 | RouteModel routeModel = RouteModel(uri); 16 | 17 | if (interceptors != null) { 18 | for(RouteInterceptor interceptor in interceptors) { 19 | if(interceptor.intercept(routeModel)) { 20 | routeModel = interceptor.process(routeModel); 21 | break; 22 | } 23 | } 24 | } 25 | PageBuilder builder = routes[routeModel.path]; 26 | if (builder != null) { 27 | return _genSlideTransitionPageRoute(builder, routeModel.params); 28 | } 29 | return null; 30 | } 31 | 32 | void addInterceptor(RouteInterceptor interceptor) { 33 | if (interceptors == null) { 34 | interceptors = []; 35 | } 36 | 37 | if (interceptor != null) { 38 | interceptors.add(interceptor); 39 | } 40 | } 41 | 42 | void removeInterceptor(RouteInterceptor interceptor) { 43 | if (interceptors != null) { 44 | interceptors.remove(interceptor); 45 | } 46 | } 47 | 48 | PageRouteBuilder _genSlideTransitionPageRoute(PageBuilder builder, 49 | Map params) { 50 | return PageRouteBuilder( 51 | pageBuilder: (BuildContext context, _, __) { 52 | return builder(context, params); 53 | }, 54 | transitionsBuilder: (_, Animation animation, __, 55 | Widget child) { 56 | return new SlideTransition( 57 | position: new Tween( 58 | begin: const Offset(1.0, 0.0), 59 | end: const Offset(0.0, 0.0), 60 | ).animate(animation), 61 | child: child 62 | ); 63 | }, 64 | ); 65 | } 66 | } -------------------------------------------------------------------------------- /music_player/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | 27 | android { 28 | compileSdkVersion 27 29 | 30 | lintOptions { 31 | disable 'InvalidPackage' 32 | } 33 | 34 | defaultConfig { 35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 36 | applicationId "cz.musicplayer" 37 | minSdkVersion 16 38 | targetSdkVersion 27 39 | versionCode flutterVersionCode.toInteger() 40 | versionName flutterVersionName 41 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 42 | } 43 | 44 | buildTypes { 45 | release { 46 | // TODO: Add your own signing config for the release build. 47 | // Signing with the debug keys for now, so `flutter run --release` works. 48 | signingConfig signingConfigs.debug 49 | } 50 | } 51 | } 52 | 53 | flutter { 54 | source '../..' 55 | } 56 | 57 | dependencies { 58 | testImplementation 'junit:junit:4.12' 59 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 60 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 61 | } 62 | -------------------------------------------------------------------------------- /flutter2048/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 15 | 19 | 26 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /music_player/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 15 | 19 | 26 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /zhihu_daily/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 15 | 19 | 26 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /zhihu_daily/lib/application.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'constants/pages.dart'; 3 | import 'package:zhihu_daily/manager/usrInfoManager.dart'; 4 | import 'package:zhihu_daily/manager/skinManager.dart'; 5 | import 'package:zhihu_daily/route/routeGenerator.dart'; 6 | import 'package:zhihu_daily/route/interceptors/loginInterceptor.dart'; 7 | import 'package:zhihu_daily/manager/collectionManager.dart'; 8 | 9 | class Application extends StatefulWidget { 10 | @override 11 | State createState() { 12 | return _ApplicationState(); 13 | } 14 | } 15 | 16 | class _ApplicationState extends State with WidgetsBindingObserver { 17 | RouteGenerator route; 18 | 19 | @override 20 | void initState() { 21 | super.initState(); 22 | WidgetsBinding.instance.addObserver(this); 23 | 24 | initRoute(); 25 | initUsrInfo(); 26 | } 27 | 28 | @override 29 | void dispose() { 30 | WidgetsBinding.instance.removeObserver(this); 31 | onAppDestroy(); 32 | super.dispose(); 33 | } 34 | 35 | @override 36 | void didChangeAppLifecycleState(AppLifecycleState state) { 37 | if (state == AppLifecycleState.resumed) { 38 | onAppResumed(); 39 | } else if (state == AppLifecycleState.paused) { 40 | onAppPaused(); 41 | } 42 | } 43 | 44 | void onAppResumed() { 45 | 46 | } 47 | 48 | void onAppPaused() { 49 | 50 | } 51 | 52 | void onAppDestroy() { 53 | CollectionManager().destroy(); 54 | } 55 | 56 | @override 57 | Widget build(BuildContext context) { 58 | return SkinManager().wrap( 59 | themeBuilder: (brightness) => 60 | ThemeData(brightness: brightness), 61 | themedWidgetBuilder: (context, theme) { 62 | return MaterialApp( 63 | theme: theme, 64 | home: Pages.firstPage(context), 65 | onGenerateRoute: route.onGenerateRoute 66 | ); 67 | }, 68 | ); 69 | } 70 | 71 | void initRoute() { 72 | route = RouteGenerator( 73 | routes: Pages.routes 74 | ); 75 | route.addInterceptor(LoginInterceptor()); 76 | } 77 | 78 | void initUsrInfo() { 79 | UsrInfoManager(); 80 | } 81 | } -------------------------------------------------------------------------------- /flutter2048/lib/widget/chess.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class Chess extends StatelessWidget { 4 | final int value; 5 | 6 | Chess({ 7 | Key key, 8 | @required this.value 9 | }) : super(key: key); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | Color backgroundColor = _getBackgroundColor(); 14 | TextStyle textStyle = _getTextStyle(); 15 | return new Container( 16 | width: 72.5, 17 | height: 72.5, 18 | margin: EdgeInsets.all(4.0), 19 | decoration: new BoxDecoration( 20 | color: backgroundColor, 21 | borderRadius: new BorderRadius.all(new Radius.circular(5.0)) 22 | ), 23 | alignment: Alignment.center, 24 | child: new Text( 25 | value.toString(), 26 | style: textStyle 27 | ), 28 | ); 29 | } 30 | 31 | Color _getBackgroundColor() { 32 | switch (value) { 33 | case 2: 34 | return new Color(0xffeee4da); 35 | case 4: 36 | return new Color(0xffeee1ca); 37 | case 8: 38 | return new Color(0xfff1b17e); 39 | case 16: 40 | return new Color(0xfff49669); 41 | case 32: 42 | return new Color(0xfff57c63); 43 | case 64: 44 | return new Color(0xfff46043); 45 | case 128: 46 | return new Color(0xffeccf79); 47 | case 256: 48 | return new Color(0xffeccb6a); 49 | case 512: 50 | return new Color(0xffecc85a); 51 | case 1024: 52 | return new Color(0xffecc44c); 53 | default: 54 | return new Color(0xffecc140); 55 | } 56 | } 57 | 58 | TextStyle _getTextStyle() { 59 | double fontSize; 60 | Color fontColor; 61 | if (value >= 8) { 62 | fontColor = new Color(0xfff9f6f2); 63 | } else { 64 | fontColor = new Color(0xff776d68); 65 | } 66 | 67 | if (value < 128) { 68 | fontSize = 28.0; 69 | } else if (value < 256) { 70 | fontSize = 26.0; 71 | } else if (value < 1024) { 72 | fontSize = 24.0; 73 | } else { 74 | fontSize = 22.0; 75 | } 76 | return new TextStyle( 77 | fontSize: fontSize, 78 | color: fontColor, 79 | fontWeight: FontWeight.bold 80 | ); 81 | } 82 | } -------------------------------------------------------------------------------- /zhihu_daily/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: zhihu_daily 2 | description: A new Flutter application. 3 | 4 | dependencies: 5 | flutter: 6 | sdk: flutter 7 | 8 | # The following adds the Cupertino Icons font to your application. 9 | # Use with the CupertinoIcons class for iOS style icons. 10 | cupertino_icons: ^0.1.2 11 | transparent_image: ^0.1.0 12 | flutter_webview_plugin: ^0.2.0 13 | shared_preferences: ^0.4.2 14 | sqflite: any 15 | 16 | dev_dependencies: 17 | flutter_test: 18 | sdk: flutter 19 | 20 | 21 | # For information on the generic Dart part of this file, see the 22 | # following page: https://www.dartlang.org/tools/pub/pubspec 23 | 24 | # The following section is specific to Flutter. 25 | flutter: 26 | 27 | # The following line ensures that the Material Icons font is 28 | # included with your application, so that you can use the icons in 29 | # the material Icons class. 30 | uses-material-design: true 31 | 32 | # To add assets to your application, add an assets section, like this: 33 | assets: 34 | - res/images/splash.png 35 | - res/images/avatar.png 36 | - res/images/login.png 37 | - res/images/logo.png 38 | 39 | # An image asset can refer to one or more resolution-specific "variants", see 40 | # https://flutter.io/assets-and-images/#resolution-aware. 41 | 42 | # For details regarding adding assets from package dependencies, see 43 | # https://flutter.io/assets-and-images/#from-packages 44 | 45 | # To add custom fonts to your application, add a fonts section here, 46 | # in this "flutter" section. Each entry in this list should have a 47 | # "family" key with the font family name, and a "fonts" key with a 48 | # list giving the asset and other descriptors for the font. For 49 | # example: 50 | # fonts: 51 | # - family: Schyler 52 | # fonts: 53 | # - asset: fonts/Schyler-Regular.ttf 54 | # - asset: fonts/Schyler-Italic.ttf 55 | # style: italic 56 | # - family: Trajan Pro 57 | # fonts: 58 | # - asset: fonts/TrajanPro.ttf 59 | # - asset: fonts/TrajanPro_Bold.ttf 60 | # weight: 700 61 | # 62 | # For details regarding fonts from package dependencies, 63 | # see https://flutter.io/custom-fonts/#from-packages 64 | -------------------------------------------------------------------------------- /zhihu_daily/lib/pages/collection.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:zhihu_daily/constants/pages.dart'; 4 | import 'package:zhihu_daily/model/story.dart'; 5 | import 'package:zhihu_daily/manager/collectionManager.dart'; 6 | 7 | class PageCollection extends StatefulWidget { 8 | @override 9 | State createState() { 10 | return _PageState(); 11 | } 12 | } 13 | 14 | class _PageState extends State { 15 | String appBarTitle = '收藏'; 16 | List stories = []; 17 | 18 | @override 19 | void initState() { 20 | super.initState(); 21 | loadCollections(); 22 | } 23 | 24 | @override 25 | Widget build(BuildContext context) { 26 | return Scaffold( 27 | appBar: AppBar(title: Text(appBarTitle)), 28 | body: ListView( 29 | children: buildCollectionList(context), 30 | ), 31 | ); 32 | } 33 | 34 | List buildCollectionList(BuildContext context) { 35 | List list = []; 36 | stories.forEach((story) { 37 | list.add(buildItem(story)); 38 | }); 39 | return list; 40 | } 41 | 42 | Widget buildItem(StoryModel story) { 43 | return Container( 44 | padding: EdgeInsets.only(left: 5.0, right: 5.0, bottom: 3.0), 45 | child: GestureDetector( 46 | onTap: () { 47 | openStoryDetailPage(story); 48 | }, 49 | child: Card( 50 | child: Container( 51 | padding: EdgeInsets.all(10.0), 52 | child: Row(children: [ 53 | Expanded(child: Text(story.title, 54 | style: TextStyle( 55 | fontSize: 18.0, fontWeight: FontWeight.w500))), 56 | Container( 57 | width: 80.0, 58 | height: 80.0, 59 | margin: EdgeInsets.only(left: 10.0), 60 | child: Image.network(story.image), 61 | ) 62 | ]), 63 | ), 64 | ), 65 | ), 66 | ); 67 | } 68 | 69 | loadCollections() async { 70 | List stories = await CollectionManager().getAllCollections(); 71 | setState(() { 72 | this.stories = stories; 73 | this.appBarTitle = 74 | stories.length > 0 ? stories.length.toString() + '条收藏' : '收藏'; 75 | }); 76 | } 77 | 78 | openStoryDetailPage(StoryModel story) { 79 | Navigator.of(context).pushNamed(Pages.STORY_DETAIL + '?story=' + Uri.encodeComponent(json.encode(story))); 80 | } 81 | } -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Base.lproj/LaunchScreen.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 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /music_player/ios/Runner/Base.lproj/LaunchScreen.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 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Base.lproj/LaunchScreen.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 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /music_player/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: music_player 2 | description: A new Flutter application. 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # Read more about versioning at semver.org. 10 | version: 1.0.0+1 11 | 12 | environment: 13 | sdk: ">=2.0.0-dev.68.0 <3.0.0" 14 | 15 | dependencies: 16 | flutter: 17 | sdk: flutter 18 | 19 | # The following adds the Cupertino Icons font to your application. 20 | # Use with the CupertinoIcons class for iOS style icons. 21 | cupertino_icons: ^0.1.2 22 | 23 | dev_dependencies: 24 | flutter_test: 25 | sdk: flutter 26 | 27 | 28 | # For information on the generic Dart part of this file, see the 29 | # following page: https://www.dartlang.org/tools/pub/pubspec 30 | 31 | # The following section is specific to Flutter. 32 | flutter: 33 | 34 | # The following line ensures that the Material Icons font is 35 | # included with your application, so that you can use the icons in 36 | # the material Icons class. 37 | uses-material-design: true 38 | 39 | # To add assets to your application, add an assets section, like this: 40 | # assets: 41 | # - images/a_dot_burr.jpeg 42 | # - images/a_dot_ham.jpeg 43 | 44 | # An image asset can refer to one or more resolution-specific "variants", see 45 | # https://flutter.io/assets-and-images/#resolution-aware. 46 | 47 | # For details regarding adding assets from package dependencies, see 48 | # https://flutter.io/assets-and-images/#from-packages 49 | 50 | # To add custom fonts to your application, add a fonts section here, 51 | # in this "flutter" section. Each entry in this list should have a 52 | # "family" key with the font family name, and a "fonts" key with a 53 | # list giving the asset and other descriptors for the font. For 54 | # example: 55 | # fonts: 56 | # - family: Schyler 57 | # fonts: 58 | # - asset: fonts/Schyler-Regular.ttf 59 | # - asset: fonts/Schyler-Italic.ttf 60 | # style: italic 61 | # - family: Trajan Pro 62 | # fonts: 63 | # - asset: fonts/TrajanPro.ttf 64 | # - asset: fonts/TrajanPro_Bold.ttf 65 | # weight: 700 66 | # 67 | # For details regarding fonts from package dependencies, 68 | # see https://flutter.io/custom-fonts/#from-packages 69 | -------------------------------------------------------------------------------- /zhihu_daily/lib/pages/home.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:http/http.dart'; 4 | import 'package:zhihu_daily/widgets/homeDrawer.dart'; 5 | import 'package:zhihu_daily/model/theme.dart'; 6 | import 'package:zhihu_daily/constants/urls.dart'; 7 | import 'package:zhihu_daily/fragment/homeFragment.dart'; 8 | import 'package:zhihu_daily/fragment/themeFragment.dart'; 9 | import 'package:zhihu_daily/dialog/moreMenuDialog.dart'; 10 | 11 | class PageHome extends StatefulWidget { 12 | @override 13 | State createState() { 14 | return new _PageState(); 15 | } 16 | } 17 | 18 | class _PageState extends State { 19 | int activatedThemeId; 20 | ThemeModel activatedTheme; 21 | List themeList; 22 | 23 | @override 24 | void initState() { 25 | super.initState(); 26 | setState(() { 27 | activatedThemeId = 0; 28 | themeList = []; 29 | }); 30 | 31 | _loadThemeList(); 32 | } 33 | 34 | @override 35 | Widget build(BuildContext context) { 36 | Widget body; 37 | if (activatedThemeId == 0) { 38 | body = HomeFragment(); 39 | } else { 40 | body = ThemeFragment(activatedTheme); 41 | } 42 | return new Scaffold( 43 | appBar: _buildAppBar(), 44 | drawer: _buildDrawer(), 45 | body: body, 46 | ); 47 | } 48 | 49 | Widget _buildDrawer() { 50 | return new HomeDrawer(activatedThemeId, themeList, (ThemeModel theme) { 51 | if (theme == null) { 52 | setState(() { 53 | activatedThemeId = 0; 54 | activatedTheme = null; 55 | }); 56 | } else { 57 | setState(() { 58 | activatedThemeId = theme.id; 59 | activatedTheme = theme; 60 | }); 61 | } 62 | }); 63 | } 64 | 65 | AppBar _buildAppBar() { 66 | return AppBar( 67 | actions: [ 68 | IconButton(icon: Icon(Icons.notifications), onPressed: _pressMsgBtn,), 69 | IconButton(icon: Icon(Icons.more_vert), onPressed: _pressMoreBtn,) 70 | ], 71 | ); 72 | } 73 | 74 | _pressMsgBtn() { 75 | 76 | } 77 | 78 | _pressMoreBtn() { 79 | showDialog(context: context, builder: (context) => MoreMenuDialog()); 80 | } 81 | 82 | _loadThemeList() async { 83 | Response response = await get(Urls.THEME_LIST); 84 | Map result = json.decode(response.body); 85 | if (result['others'] != null) { 86 | result['others'].forEach((item) { 87 | themeList.add(ThemeModel.fromJson(item)); 88 | }); 89 | setState(() {}); 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /zhihu_daily/lib/manager/usrInfoManager.dart: -------------------------------------------------------------------------------- 1 | import 'package:shared_preferences/shared_preferences.dart'; 2 | import 'package:zhihu_daily/model/usrInfo.dart'; 3 | 4 | const String _sp_key_usr_uid = 'usr_uid'; 5 | const String _sp_key_usr_name = 'usr_name'; 6 | const String _sp_key_usr_avatar = 'usr_avatar'; 7 | 8 | enum LoginState { 9 | login, 10 | logout 11 | } 12 | 13 | typedef void OnLoginStateChanged(LoginState state, UsrInfo usrInfo); 14 | 15 | class UsrInfoManager { 16 | static UsrInfoManager _instance; 17 | 18 | List _loginListeners = []; 19 | 20 | UsrInfo usrInfo; 21 | 22 | UsrInfoManager._internal() { 23 | _loadFromLocal(); 24 | } 25 | 26 | factory UsrInfoManager() { 27 | if (_instance == null) { 28 | _instance = UsrInfoManager._internal(); 29 | } 30 | return _instance; 31 | } 32 | 33 | void addLoginListener(OnLoginStateChanged listener) { 34 | _loginListeners.add(listener); 35 | } 36 | 37 | void removeLoginListener(OnLoginStateChanged listener) { 38 | _loginListeners.remove(listener); 39 | } 40 | 41 | bool hasLogin() { 42 | return usrInfo != null; 43 | } 44 | 45 | void mockLogin() { 46 | usrInfo = UsrInfo(0, '测试用户', ''); 47 | _dispatchLoginStateChanged(LoginState.login, usrInfo); 48 | _saveToLocal(usrInfo); 49 | } 50 | 51 | void logout() { 52 | usrInfo = null; 53 | _dispatchLoginStateChanged(LoginState.logout, null); 54 | _clearLocalInfo(); 55 | } 56 | 57 | void _loadFromLocal() async { 58 | SharedPreferences sp = await SharedPreferences.getInstance(); 59 | int uid = sp.getInt(_sp_key_usr_uid); 60 | String name = sp.getString(_sp_key_usr_name); 61 | String avatar = sp.getString(_sp_key_usr_avatar); 62 | if (uid != null) { 63 | usrInfo = UsrInfo(uid, name, avatar); 64 | _dispatchLoginStateChanged(LoginState.login, usrInfo); 65 | } 66 | } 67 | 68 | void _saveToLocal(UsrInfo usrInfo) async { 69 | if (usrInfo != null) { 70 | SharedPreferences sp = await SharedPreferences.getInstance(); 71 | sp.setInt(_sp_key_usr_uid, usrInfo.uid); 72 | sp.setString(_sp_key_usr_name, usrInfo.name); 73 | sp.setString(_sp_key_usr_avatar, usrInfo.avatar); 74 | } 75 | } 76 | 77 | void _clearLocalInfo() async { 78 | SharedPreferences sp = await SharedPreferences.getInstance(); 79 | sp.remove(_sp_key_usr_uid); 80 | sp.remove(_sp_key_usr_name); 81 | sp.remove(_sp_key_usr_avatar); 82 | } 83 | 84 | void _dispatchLoginStateChanged(LoginState state, UsrInfo usrInfo) { 85 | _loginListeners.forEach((listener) { 86 | listener(state, usrInfo); 87 | }); 88 | } 89 | } -------------------------------------------------------------------------------- /zhihu_daily/README.md: -------------------------------------------------------------------------------- 1 | # zhihu_daily 2 | 3 | Flutter版知乎日报 4 | 5 | ## 页面截图 6 | 7 | ### Splash 启动白屏优化对比 8 | 启动白屏 启动白屏优化 9 | 10 | * 启动白屏 11 | * [Canvas绘制](https://flutter.io/flutter-for-android/#how-do-i-use-a-canvas-to-drawpaint); 12 | * 补间动画,[Animation](https://flutter.io/animations/#tween-animation); 13 | * 页面导航,[Navigator](https://docs.flutter.io/flutter/widgets/Navigator-class.html) 14 | 15 | ### Drawer 16 | Drawer 17 | 18 | * [Drawer](https://docs.flutter.io/flutter/material/Drawer-class.html) 19 | 20 | ### 首页 21 | 首页 22 | 23 | * Banner焦点图,[PageView](https://docs.flutter.io/flutter/widgets/PageView-class.html),[实例](https://github.com/zh8637688/Flutter-Practise/blob/master/zhihu_daily/lib/widgets/homeBanner.dart) 24 | - 循环播放,两种方法:1,itemCount最大值;2.首尾各增加一个虚拟item占位 25 | - 预加载,目前PageView只有在下一个Item出现前才会去加载这个Item,所以暂时无法预加载next item 26 | * 下拉刷新,[RefreshIndicator](https://docs.flutter.io/flutter/material/RefreshIndicator-class.html),[实例](https://github.com/zh8637688/Flutter-Practise/blob/master/zhihu_daily/lib/fragment/homeFragment.dart#L46) 27 | * 上拉加载,ListView & ScrollController,[实例](https://github.com/zh8637688/Flutter-Practise/blob/master/zhihu_daily/lib/fragment/homeFragment.dart#L66) 28 | 29 | ### 详情 30 | detail 31 | 32 | * WebView,Flutter官方并没有对 WebView 提供支持,所以 WebView 使用的第三方插件[flutter_webview_plugin](https://pub.dartlang.org/packages/flutter_webview_plugin#-example-tab-)。**该插件是基于原生 WebView 进行开发,所以无法与 Flutter 的控件进行整合,只能在新页面中使用。** 33 | 34 | ### 夜间模式 35 | menu dark 36 | 37 | * showDialog,自定义 Dialog 38 | * 通过配置 Theme 实现换肤效果,[链接](https://proandroiddev.com/how-to-dynamically-change-the-theme-in-flutter-698bd022d0f0) 39 | -------------------------------------------------------------------------------- /flutter2048/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /music_player/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /zhihu_daily/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /zhihu_daily/lib/pages/login.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:zhihu_daily/model/usrInfo.dart'; 3 | import 'package:zhihu_daily/manager/usrInfoManager.dart'; 4 | 5 | class PageLogin extends StatefulWidget { 6 | final String nextPage; 7 | 8 | PageLogin(this.nextPage); 9 | 10 | PageLogin.fromParams(Map params) 11 | :this(params != null ? params['nextPage'] : null); 12 | 13 | @override 14 | State createState() { 15 | return _PageState(); 16 | } 17 | } 18 | 19 | class _PageState extends State { 20 | UsrInfoManager usrInfoManager = UsrInfoManager(); 21 | 22 | @override 23 | void initState() { 24 | super.initState(); 25 | usrInfoManager.addLoginListener(onLoginStateChanged); 26 | } 27 | 28 | @override 29 | void dispose() { 30 | super.dispose(); 31 | usrInfoManager.removeLoginListener(onLoginStateChanged); 32 | } 33 | 34 | @override 35 | Widget build(BuildContext context) { 36 | return Scaffold( 37 | appBar: AppBar(title: Text('登录')), 38 | body: Stack( 39 | fit: StackFit.expand, 40 | children: [ 41 | Image.asset('res/images/login.png', fit: BoxFit.fill), 42 | Container( 43 | alignment: Alignment.center, 44 | child: _buildLogoAndButton(), 45 | ) 46 | ], 47 | ), 48 | ); 49 | } 50 | 51 | Widget _buildLogoAndButton() { 52 | return Column( 53 | mainAxisAlignment: MainAxisAlignment.center, 54 | children: [ 55 | Image.asset('res/images/logo.png', 56 | width: 141.0, 57 | height: 51.0,), 58 | Container( 59 | margin: EdgeInsets.only(top: 50.0), 60 | child: _buildInkButton( 61 | Container( 62 | width: 230.0, 63 | height: 50.0, 64 | alignment: Alignment.center, 65 | child: new Text('登 录', style: TextStyle( 66 | fontSize: 20.0, fontWeight: FontWeight.w500)), 67 | ), _onTapLoginBtn), 68 | ) 69 | ], 70 | ); 71 | } 72 | 73 | Widget _buildInkButton(Widget child, GestureTapCallback onTap) { 74 | return Material( 75 | borderRadius: new BorderRadius.all(new Radius.circular(6.0)), 76 | child: Ink( 77 | child: new InkWell( 78 | onTap: onTap, 79 | child: child, 80 | ), 81 | ), 82 | ); 83 | } 84 | 85 | _onTapLoginBtn() { 86 | UsrInfoManager().mockLogin(); 87 | } 88 | 89 | onLoginStateChanged(LoginState state, UsrInfo usrInfo) { 90 | if (state == LoginState.login) { 91 | if (widget.nextPage != null) { 92 | Navigator.pushReplacementNamed(context, widget.nextPage); 93 | } else { 94 | Navigator.pop(context); 95 | } 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /zhihu_daily/lib/widgets/animatedLogo.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'dart:math'; 3 | 4 | Color _color = const Color(0xffc2c5cc); 5 | 6 | class AnimatedLogo extends StatefulWidget { 7 | final bool showAnimation; 8 | final AnimationStatusListener callback; 9 | 10 | AnimatedLogo({ 11 | Key key, 12 | this.showAnimation = false, 13 | this.callback 14 | }) : super(key: key); 15 | 16 | @override 17 | State createState() { 18 | return new _LogoState(); 19 | } 20 | } 21 | 22 | class _LogoState extends State 23 | with SingleTickerProviderStateMixin { 24 | AnimationController controller; 25 | Animation animation; 26 | 27 | @override 28 | void initState() { 29 | super.initState(); 30 | controller = new AnimationController( 31 | duration: const Duration(milliseconds: 1500), vsync: this); 32 | Animation curve = new CurvedAnimation( 33 | parent: controller, curve: Curves.easeOut); 34 | animation = new Tween(begin: 0.0, end: 0.75).animate(curve) 35 | ..addListener(() { 36 | setState(() {}); 37 | }) 38 | ..addStatusListener(widget.callback); 39 | } 40 | 41 | 42 | @override 43 | void didUpdateWidget(AnimatedLogo oldWidget) { 44 | super.didUpdateWidget(oldWidget); 45 | if (widget.showAnimation) { 46 | controller.forward(); 47 | } 48 | } 49 | 50 | @override 51 | Widget build(BuildContext context) { 52 | return new Container( 53 | padding: EdgeInsets.all(8.0), 54 | decoration: new BoxDecoration( 55 | border: new Border.all(color: _color), 56 | borderRadius: new BorderRadius.all(new Radius.circular(6.0)), 57 | ), 58 | child: new CustomPaint(painter: new _LogoPainter(animation)), 59 | ); 60 | } 61 | 62 | @override 63 | void dispose() { 64 | super.dispose(); 65 | if (controller != null) { 66 | controller.dispose(); 67 | } 68 | } 69 | } 70 | 71 | class _LogoPainter extends CustomPainter { 72 | Animation animation; 73 | 74 | _LogoPainter(this.animation); 75 | 76 | @override 77 | void paint(Canvas canvas, Size size) { 78 | if (animation != null) { 79 | Paint paint = new Paint() 80 | ..color = _color 81 | ..strokeCap = StrokeCap.round 82 | ..strokeWidth = 4.5 83 | ..style = PaintingStyle.stroke; 84 | int max = (72 * animation.value).toInt(); 85 | double r = size.width / 2; 86 | Path path = new Path(); 87 | path.moveTo(size.width / 2, size.height); 88 | for (int i = 0; i < max; i++) { 89 | double radians = (0.5 + i / 36.0) * pi; 90 | path.lineTo(r * cos(radians) + r, 91 | r * sin(radians) + r); 92 | } 93 | canvas.drawPath(path, paint); 94 | } 95 | } 96 | 97 | @override 98 | bool shouldRepaint(_LogoPainter other) => true; 99 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Flutter-Example 2 | Flutter是Google推出的一款移动端跨平台UI开发框架。 3 | 4 | 不同于React-Native、Weex等跨平台框架,Flutter具有以下的特性: 5 | 1. Flutter抛弃了桥接原生控件的方案,而是通过平台提供的Canvas自行绘制所有控件; 6 | 2. Flutter使用Dart作为编程语言,Dart语言的AOT特性使得Flutter应用代码能够被预编译成本地代码。 7 | 8 | 这些特性让Flutter能够更加流畅地运行在各个移动平台中。 9 | 10 | Flutter即将发布第一个Release版本,这里记录一下Flutter的学习过程及Flutter相关的资料。 11 | 12 | ### Flutter官网 13 | [https://flutter.io/](https://flutter.io/) 14 | 15 | ### Flutter中文网站 16 | [https://flutter-io.cn/](https://flutter-io.cn/) 17 | [Flutter中文网](https://flutterchina.club/) 18 | [Flutter中文开发者论坛](http://flutter-dev.cn/) 19 | 20 | ### FlutterStudio,一个在线的Flutter页面构建工具 21 | [https://flutterstudio.app/](https://flutterstudio.app/) 22 | FlutterStudio 23 | 24 | ### Flutter填坑 25 | * **[Android应用启动白屏](https://juejin.im/post/5b443975f265da0f6825b56c)** 26 | * **Flutter 中关于 WebView 的[讨论](https://github.com/flutter/flutter/issues/730)**,目前 Flutter 自身还不支持 WebView,可通过[插件](https://pub.dartlang.org/packages/flutter_webview_plugin)使用 native 的 WebView。(native webview 会覆盖在 flutter 渲染层之上,导致后续打开的页面被遮挡) 27 | 28 |
29 | 30 | ## [知乎日报](https://github.com/zh8637688/Flutter-Practise/tree/master/zhihu_daily) 31 | Splash Home detail 32 | 33 | Drawer Login Collection 34 | 35 | menu dark 36 | 37 | ### Future 38 | * Route 39 | * 支持设置统一的页面跳转动画; 40 | * 支持带参数的命名路由,``Navigator.of(context).pushNamed(pagePath + '?key=value')``; 41 | * 支持路由拦截,``RouteInterceptor``; 42 | 43 | ## [Flutter 2048](https://github.com/zh8637688/Flutter-Practise/tree/master/flutter2048/) 44 | Flutter 2048 45 | -------------------------------------------------------------------------------- /flutter2048/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter2048/widget/scoreTitle.dart'; 3 | import 'package:flutter2048/widget/chessboard.dart'; 4 | import 'package:flutter2048/logic/game.dart'; 5 | import 'package:shared_preferences/shared_preferences.dart'; 6 | 7 | class Flutter2048 extends StatefulWidget { 8 | @override 9 | _Flutter2048State createState() => new _Flutter2048State(); 10 | } 11 | 12 | class _Flutter2048State extends State { 13 | int score; 14 | int best; 15 | List chess; 16 | 17 | @override 18 | void initState() { 19 | super.initState(); 20 | setState(() { 21 | score = 0; 22 | best = 0; 23 | chess = initChess(); 24 | }); 25 | _getBestFromLocal(); 26 | } 27 | 28 | _getBestFromLocal() async { 29 | SharedPreferences prefs = await SharedPreferences.getInstance(); 30 | setState(() { 31 | best = prefs.getInt('best') ?? 0; 32 | }); 33 | } 34 | 35 | _saveBestToLocal(int best) async { 36 | SharedPreferences prefs = await SharedPreferences.getInstance(); 37 | prefs.setInt('best', best); 38 | } 39 | 40 | @override 41 | Widget build(BuildContext context) { 42 | return new MaterialApp( 43 | home: new Scaffold( 44 | appBar: new AppBar( 45 | title: const Text('Flutter 2048'), 46 | backgroundColor: new Color(0xff3c3c3a), 47 | ), 48 | body: new Container( 49 | color: new Color(0xfffaf8ef), 50 | child: new GestureDetector( 51 | child: new Column( 52 | mainAxisAlignment: MainAxisAlignment.center, 53 | children: [ 54 | new ScoreTitle(score: score, best: best), 55 | new Chessboard(chess: chess) 56 | ], 57 | ), 58 | onHorizontalDragEnd: onHorizontalDragEnd, 59 | onVerticalDragEnd: onVerticalDragEnd, 60 | ) 61 | ), 62 | ), 63 | ); 64 | } 65 | 66 | onHorizontalDragEnd(details) { 67 | var result; 68 | if (details.primaryVelocity > 0.0) { 69 | result = flingTo(this.chess, 0); 70 | } else { 71 | result = flingTo(this.chess, 1); 72 | } 73 | int score = this.score + result['score']; 74 | if (score > best) { 75 | best = score; 76 | _saveBestToLocal(best); 77 | } 78 | setState(() { 79 | this.score = score; 80 | this.best = best; 81 | this.chess = result['chess']; 82 | }); 83 | } 84 | 85 | onVerticalDragEnd(details) { 86 | var result; 87 | if (details.primaryVelocity < 0.0) { 88 | result = flingTo(this.chess, 2); 89 | } else { 90 | result = flingTo(this.chess, 3); 91 | } 92 | int score = this.score + result['score']; 93 | if (score > best) { 94 | best = score; 95 | _saveBestToLocal(best); 96 | } 97 | setState(() { 98 | this.score = score; 99 | this.best = best; 100 | this.chess = result['chess']; 101 | }); 102 | } 103 | } 104 | 105 | void main() { 106 | runApp(new Flutter2048()); 107 | } -------------------------------------------------------------------------------- /flutter2048/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /music_player/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /flutter2048/lib/logic/game.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | import 'matrixUtil.dart'; 3 | 4 | Random _random = new Random(); 5 | 6 | List initChess() { 7 | List chess = [ 8 | 0, 0, 0, 0, 9 | 0, 0, 0, 0, 10 | 0, 0, 0, 0, 11 | 0, 0, 0, 0 12 | ]; 13 | _randomChess(chess, true); 14 | _randomChess(chess, true); 15 | return chess; 16 | } 17 | 18 | flingTo(List chess, int direction) { 19 | bool canMove = false; 20 | List tempChess = _transform(chess, direction); 21 | int n = sqrt(chess.length).toInt(); 22 | int score = 0; 23 | for (int i = 0; i < n; i++) { 24 | for (int j = n - 1; j >= 0; j--) { 25 | int index = i * n + j; 26 | int destPos = _findDestPos(tempChess, index); 27 | if (destPos >= 0) { 28 | canMove = true; 29 | if (tempChess[destPos] > 0) { 30 | score += _mergeTo(tempChess, index, destPos); 31 | } else { 32 | _moveTo(tempChess, index, destPos); 33 | } 34 | } 35 | } 36 | } 37 | chess = _recovery(tempChess, direction); 38 | 39 | if (canMove) { 40 | _randomChess(chess, false); 41 | } 42 | return { 43 | 'score': score, 44 | 'chess': chess 45 | }; 46 | } 47 | 48 | int _findDestPos(chess, srcPos) { 49 | int dest = -1; 50 | if (chess[srcPos] > 0) { 51 | int n = sqrt(chess.length).toInt(); 52 | int row = (srcPos / n).floor(); 53 | int column = srcPos % n; 54 | int lastIndex = -1; 55 | for (int i = n - 1; i > column; i--) { 56 | int index = row * n + i; 57 | if (chess[index] > 0) { 58 | lastIndex = index; 59 | } else { 60 | dest = index; 61 | break; 62 | } 63 | } 64 | if (lastIndex >= 0 && chess[lastIndex] > 0 65 | && (chess[lastIndex] == chess[srcPos])) { 66 | dest = lastIndex; 67 | } 68 | } 69 | return dest; 70 | } 71 | 72 | _mergeTo(chess, fromPos, toPos) { 73 | var to = chess[toPos]; 74 | chess[fromPos] = 0; 75 | chess[toPos] = to * 2; 76 | return chess[toPos]; 77 | } 78 | 79 | _moveTo(chess, fromPos, toPos) { 80 | chess[toPos] = chess[fromPos]; 81 | chess[fromPos] = 0; 82 | } 83 | 84 | _transform(chess, direction) { 85 | switch (direction) { 86 | case 0: 87 | return chess; 88 | case 1: 89 | return MatrixUtil.flipLR(chess); 90 | case 2: 91 | return MatrixUtil.rot(chess); 92 | case 3: 93 | return MatrixUtil.inv(chess); 94 | } 95 | } 96 | 97 | _recovery(chess, direction) { 98 | switch (direction) { 99 | case 0: 100 | return chess; 101 | case 1: 102 | return MatrixUtil.flipLR(chess); 103 | case 2: 104 | return MatrixUtil.antiRot(chess); 105 | case 3: 106 | return MatrixUtil.inv(chess); 107 | } 108 | } 109 | 110 | _randomChess(chess, bool firstTime) { 111 | int rap = _randomAvailablePos(chess); 112 | int twoOrFour = firstTime || _random.nextDouble() < 0.9 ? 2 : 4; 113 | chess[rap] = twoOrFour; 114 | } 115 | 116 | int _randomAvailablePos(chess) { 117 | List ap = _availablePos(chess); 118 | int pos = (_random.nextDouble() * ap.length).floor(); 119 | return ap[pos]; 120 | } 121 | 122 | List _availablePos(chess) { 123 | List ap = []; 124 | for (int i = 0; i < chess.length; i++) { 125 | if (chess[i] == 0) { 126 | ap.add(i); 127 | } 128 | } 129 | return ap; 130 | } -------------------------------------------------------------------------------- /flutter2048/lib/widget/scoreTitle.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class ScoreTitle extends StatelessWidget { 4 | final int score; 5 | final int best; 6 | 7 | ScoreTitle({ 8 | Key key, 9 | @required this.score, 10 | @required this.best 11 | }) : super(key: key); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return new Container( 16 | height: 110.0, 17 | margin: EdgeInsets.only(left: 15.0, right: 15.0), 18 | child: new Row( 19 | crossAxisAlignment: CrossAxisAlignment.start, 20 | children: [ 21 | _buildLogo(), 22 | _buildScorePanel() 23 | ], 24 | ), 25 | ); 26 | } 27 | 28 | Widget _buildLogo() { 29 | return new Container( 30 | decoration: new BoxDecoration( 31 | color: new Color(0xffecc140), 32 | borderRadius: new BorderRadius.all(new Radius.circular(5.0)) 33 | ), 34 | width: 110.0, 35 | height: 110.0, 36 | margin: EdgeInsets.only(right: 20.0), 37 | child: new Center( 38 | child: new Text( 39 | '2048', 40 | style: new TextStyle( 41 | fontSize: 30.0, 42 | fontWeight: FontWeight.bold, 43 | color: new Color(0xfffbfdfb) 44 | ), 45 | ), 46 | ), 47 | ); 48 | } 49 | 50 | Widget _buildScorePanel() { 51 | return new Expanded( 52 | child: new Column( 53 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 54 | children: [ 55 | new Row( 56 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 57 | children: [ 58 | _buildScore('SCORE', score), 59 | _buildScore('BEST', best), 60 | ], 61 | ), 62 | new Expanded( 63 | child: new Center( 64 | child: new Text( 65 | 'Join numbers to reach 2048.', 66 | style: new TextStyle( 67 | fontSize: 14.0, 68 | fontWeight: FontWeight.bold, 69 | color: new Color(0xff736d64) 70 | ), 71 | ), 72 | ) 73 | ), 74 | ], 75 | ), 76 | ); 77 | } 78 | 79 | Widget _buildScore(String title, int score) { 80 | return new Container( 81 | decoration: new BoxDecoration( 82 | color: new Color(0xffbbada3), 83 | borderRadius: new BorderRadius.all(new Radius.circular(5.0)) 84 | ), 85 | width: 90.0, 86 | padding: EdgeInsets.only(top: 10.0, bottom: 10.0), 87 | child: new Column( 88 | mainAxisAlignment: MainAxisAlignment.spaceAround, 89 | children: [ 90 | new Text( 91 | title, 92 | style: new TextStyle( 93 | fontSize: 16.0, 94 | fontWeight: FontWeight.bold, 95 | color: new Color(0xfff0e9db) 96 | ), 97 | ), 98 | new Container( 99 | margin: EdgeInsets.only(top: 4.0), 100 | child: new Text( 101 | score.toString(), 102 | style: new TextStyle( 103 | fontSize: 18.0, 104 | fontWeight: FontWeight.bold, 105 | color: new Color(0xfffbfdfb) 106 | ), 107 | ), 108 | ) 109 | ], 110 | ), 111 | ); 112 | } 113 | } -------------------------------------------------------------------------------- /zhihu_daily/lib/manager/collectionManager.dart: -------------------------------------------------------------------------------- 1 | import 'package:sqflite/sqflite.dart'; 2 | import 'package:path/path.dart'; 3 | import 'dart:async'; 4 | import 'package:zhihu_daily/model/story.dart'; 5 | 6 | class CollectionManager { 7 | static CollectionManager _instance; 8 | 9 | _CollectionDBHelper _dbHelper; 10 | 11 | CollectionManager._internal() { 12 | _dbHelper = _CollectionDBHelper(); 13 | } 14 | 15 | factory CollectionManager() { 16 | if (_instance == null) { 17 | _instance = CollectionManager._internal(); 18 | } 19 | return _instance; 20 | } 21 | 22 | destroy() { 23 | _dbHelper.close(); 24 | } 25 | 26 | Future> getAllCollections() async { 27 | return _dbHelper.getAllCollections(); 28 | } 29 | 30 | Future collect(StoryModel story) { 31 | return _dbHelper.collect(story); 32 | } 33 | 34 | Future delete(StoryModel story) { 35 | return _dbHelper.delete(story); 36 | } 37 | 38 | Future hasCollected(StoryModel story) { 39 | return _dbHelper.hasCollected(story); 40 | } 41 | } 42 | 43 | class _CollectionDBHelper { 44 | static const String DB_NAME = 'ZHIHU_DAILY'; 45 | static const int DB_VERSION = 1; 46 | 47 | static const String TABLE_NAME = 'COLLECTION'; 48 | 49 | static const String COLUMN_ID = 'id'; 50 | static const String COLUMN_TITLE = 'title'; 51 | static const String COLUMN_IMAGE = 'image'; 52 | 53 | static const String SQL_CREATE_TABLE = 'CREATE TABLE ' + TABLE_NAME + ' (' 54 | + COLUMN_ID + ' INTEGER PRIMARY KEY, ' 55 | + COLUMN_TITLE + ' TEXT, ' 56 | + COLUMN_IMAGE + ' TEXT)'; 57 | 58 | static const String SQL_GET_ALL = 'SELECT * FROM ' + TABLE_NAME; 59 | 60 | static const String SQL_COLLECT = 'INSERT INTO ' + TABLE_NAME + ' (' 61 | + COLUMN_ID + ', ' 62 | + COLUMN_TITLE + ', ' 63 | + COLUMN_IMAGE + ') VALUES(?, ?, ?)'; 64 | 65 | static const String SQL_DELETE = 'DELETE FROM ' + TABLE_NAME 66 | + ' WHERE ' + COLUMN_ID + ' = ?'; 67 | 68 | static const String SQL_HAS_COLLECTED = 'SELECT COUNT(*) FROM ' + TABLE_NAME 69 | + ' WHERE ' + COLUMN_ID + ' = ?'; 70 | 71 | Database database; 72 | 73 | createAndOpenDB() async { 74 | String basePath = await getDatabasesPath(); 75 | String dbPath = join(basePath, DB_NAME); 76 | database = await openDatabase( 77 | dbPath, 78 | version: DB_VERSION, 79 | onCreate: onCreate, 80 | ); 81 | } 82 | 83 | onCreate(Database db, int version) async { 84 | await db.execute(SQL_CREATE_TABLE); 85 | } 86 | 87 | close() async { 88 | await createAndOpenDB(); 89 | await database.close(); 90 | } 91 | 92 | Future> getAllCollections() async { 93 | await createAndOpenDB(); 94 | List stories = []; 95 | List> list = await database.rawQuery(SQL_GET_ALL); 96 | list.forEach((json) { 97 | stories.add(StoryModel.fromJson(json)); 98 | }); 99 | return stories; 100 | } 101 | 102 | Future collect(StoryModel story) async { 103 | await createAndOpenDB(); 104 | return await database.rawInsert( 105 | SQL_COLLECT, [story.id, story.title, story.image]) > 0; 106 | } 107 | 108 | Future delete(StoryModel story) async { 109 | await createAndOpenDB(); 110 | return await database.rawDelete(SQL_DELETE, [story.id]) > 0; 111 | } 112 | 113 | Future hasCollected(StoryModel story) async { 114 | await createAndOpenDB(); 115 | return Sqflite.firstIntValue(await database.rawQuery(SQL_HAS_COLLECTED, [story.id])) > 0; 116 | } 117 | } -------------------------------------------------------------------------------- /flutter2048/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /zhihu_daily/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /music_player/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /zhihu_daily/lib/pages/splash.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:transparent_image/transparent_image.dart'; 4 | import 'package:zhihu_daily/constants/pages.dart'; 5 | import '../widgets/animatedLogo.dart'; 6 | 7 | class PageSplash extends StatefulWidget { 8 | @override 9 | State createState() { 10 | return new _PageState(); 11 | } 12 | } 13 | 14 | class _PageState extends State with SingleTickerProviderStateMixin { 15 | Animation animation; 16 | AnimationController controller; 17 | bool showLogoAnimation = false; 18 | bool showBackgroundImage = false; 19 | 20 | @override 21 | void initState() { 22 | super.initState(); 23 | controller = new AnimationController( 24 | duration: const Duration(milliseconds: 1000), vsync: this); 25 | Animation curve = new CurvedAnimation( 26 | parent: controller, curve: Curves.easeOut); 27 | animation = new Tween(begin: 84.0, end: 0.0).animate(curve) 28 | ..addListener(() { 29 | setState(() {}); 30 | }) 31 | ..addStatusListener((status) { 32 | if (status == AnimationStatus.completed) { 33 | setState(() { 34 | showLogoAnimation = true; 35 | }); 36 | } 37 | }); 38 | controller.forward(); 39 | } 40 | 41 | @override 42 | Widget build(BuildContext context) { 43 | return Scaffold( 44 | body: Container( 45 | color: Color(0xff17181a), 46 | child: Column( 47 | children: [ 48 | Expanded(child: _buildBackgroundImage()), 49 | Container( 50 | height: 84.0, 51 | child: _buildLogoAndSlogan(context), 52 | ) 53 | ], 54 | ), 55 | ),); 56 | } 57 | 58 | @override 59 | void dispose() { 60 | controller.dispose(); 61 | super.dispose(); 62 | } 63 | 64 | Widget _buildBackgroundImage() { 65 | if (showBackgroundImage) { 66 | return FadeInImage( 67 | width: 360.0, 68 | placeholder: MemoryImage(kTransparentImage), 69 | image: AssetImage('res/images/splash.png'), 70 | fit: BoxFit.fill, 71 | fadeInDuration: Duration(milliseconds: 400)); 72 | } else { 73 | return Container(); 74 | } 75 | } 76 | 77 | Widget _buildLogoAndSlogan(BuildContext context) { 78 | return new Container( 79 | padding: EdgeInsets.only(top: animation.value), 80 | child: new Row( 81 | children: [ 82 | _buildLogo(context), 83 | _buildSlogan() 84 | ], 85 | ), 86 | ); 87 | } 88 | 89 | Widget _buildLogo(BuildContext context) { 90 | return new Container( 91 | width: 45.0, 92 | height: 45.0, 93 | margin: EdgeInsets.only(left: 25.5, right: 12.5), 94 | child: new AnimatedLogo( 95 | showAnimation: showLogoAnimation, 96 | callback: (status) { 97 | if (status == AnimationStatus.completed) { 98 | setState(() { 99 | showBackgroundImage = true; 100 | }); 101 | Future.delayed(Duration(milliseconds: 2400), () { 102 | _openHomePage(context); 103 | }); 104 | } 105 | }), 106 | ); 107 | } 108 | 109 | Widget _buildSlogan() { 110 | return new Column( 111 | mainAxisAlignment: MainAxisAlignment.center, 112 | crossAxisAlignment: CrossAxisAlignment.start, 113 | children: [ 114 | new Text( 115 | '知乎日报', 116 | style: new TextStyle( 117 | fontSize: 20.0, 118 | color: new Color(0xffced2d9), 119 | ), 120 | ), 121 | new Text( 122 | '每天三次,每次七分钟', 123 | style: new TextStyle( 124 | fontSize: 14.0, 125 | color: new Color(0xff85888c), 126 | ), 127 | ) 128 | ], 129 | ); 130 | } 131 | 132 | _openHomePage(BuildContext context) { 133 | Navigator.pushReplacementNamed(context, Pages.HOME); 134 | } 135 | } -------------------------------------------------------------------------------- /zhihu_daily/lib/manager/skinManager.dart: -------------------------------------------------------------------------------- 1 | import 'package:shared_preferences/shared_preferences.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | const String _sharedPreferencesKey = "isDark"; 5 | 6 | typedef Widget ThemedWidgetBuilder(BuildContext context, ThemeData data); 7 | 8 | typedef ThemeData ThemeDataWithBrightnessBuilder(Brightness brightness); 9 | 10 | class SkinManager { 11 | static SkinManager _instance; 12 | bool _loaded = false; 13 | Brightness _brightness = Brightness.light; 14 | 15 | SkinManager._internal(); 16 | 17 | factory SkinManager() { 18 | if (_instance == null) { 19 | _instance = SkinManager._internal(); 20 | } 21 | return _instance; 22 | } 23 | 24 | setBrightness(BuildContext context, Brightness brightness) { 25 | if (brightness != _brightness) { 26 | _brightness = brightness; 27 | _DynamicThemeState state; 28 | if (context is StatefulElement) { 29 | StatefulElement element = context; 30 | if (element.state is _DynamicThemeState) { 31 | state = context.state; 32 | } 33 | } 34 | if (state == null) { 35 | state = context.ancestorStateOfType( 36 | const TypeMatcher<_DynamicThemeState>()); 37 | } 38 | if (state != null) { 39 | state.setBrightness(_brightness); 40 | } 41 | _saveConfig(_brightness); 42 | } 43 | } 44 | 45 | get brightness { 46 | return _brightness; 47 | } 48 | 49 | Widget wrap( 50 | {Key key, ThemeDataWithBrightnessBuilder themeBuilder, ThemedWidgetBuilder themedWidgetBuilder}) { 51 | return _DynamicTheme( 52 | key: key, 53 | data: themeBuilder, 54 | themedWidgetBuilder: (context, data) { 55 | _loadConfig(context); 56 | return themedWidgetBuilder(context, data); 57 | }, 58 | defaultBrightness: _brightness); 59 | } 60 | 61 | _loadConfig(BuildContext context) async { 62 | if (!_loaded) { 63 | SharedPreferences sp = await SharedPreferences.getInstance(); 64 | bool isDark = sp.getBool(_sharedPreferencesKey); 65 | Brightness localBrightness = isDark != null && isDark 66 | ? Brightness.dark 67 | : Brightness.light; 68 | setBrightness(context, localBrightness); 69 | _loaded = true; 70 | } 71 | } 72 | 73 | _saveConfig(Brightness brightness) async { 74 | SharedPreferences sp = await SharedPreferences.getInstance(); 75 | sp.setBool( 76 | _sharedPreferencesKey, brightness == Brightness.dark ? true : false); 77 | } 78 | } 79 | 80 | class _DynamicTheme extends StatefulWidget { 81 | 82 | final ThemedWidgetBuilder themedWidgetBuilder; 83 | 84 | final ThemeDataWithBrightnessBuilder data; 85 | 86 | final Brightness defaultBrightness; 87 | 88 | const _DynamicTheme( 89 | {Key key, this.data, this.themedWidgetBuilder, this.defaultBrightness}) 90 | : super(key: key); 91 | 92 | @override 93 | _DynamicThemeState createState() => new _DynamicThemeState(); 94 | } 95 | 96 | class _DynamicThemeState extends State<_DynamicTheme> { 97 | 98 | ThemeData _data; 99 | 100 | Brightness _brightness; 101 | 102 | @override 103 | void initState() { 104 | super.initState(); 105 | _brightness = widget.defaultBrightness; 106 | _data = widget.data(_brightness); 107 | } 108 | 109 | @override 110 | void didChangeDependencies() { 111 | super.didChangeDependencies(); 112 | _data = widget.data(_brightness); 113 | } 114 | 115 | @override 116 | void didUpdateWidget(_DynamicTheme oldWidget) { 117 | super.didUpdateWidget(oldWidget); 118 | _data = widget.data(_brightness); 119 | } 120 | 121 | @override 122 | Widget build(BuildContext context) { 123 | return widget.themedWidgetBuilder(context, _data); 124 | } 125 | 126 | void setBrightness(Brightness brightness) async { 127 | setState(() { 128 | this._data = widget.data(brightness); 129 | this._brightness = brightness; 130 | }); 131 | } 132 | 133 | void setThemeData(ThemeData data) { 134 | setState(() { 135 | this._data = data; 136 | }); 137 | } 138 | } 139 | 140 | -------------------------------------------------------------------------------- /zhihu_daily/lib/pages/storyDetail.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'package:http/http.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_webview_plugin/flutter_webview_plugin.dart'; 5 | import 'package:zhihu_daily/constants/urls.dart'; 6 | import 'package:zhihu_daily/constants/pages.dart'; 7 | import 'package:zhihu_daily/model/story.dart'; 8 | import 'package:zhihu_daily/manager/collectionManager.dart'; 9 | 10 | class PageStoryDetail extends StatefulWidget { 11 | final StoryModel story; 12 | 13 | PageStoryDetail(this.story); 14 | 15 | PageStoryDetail.fromParams(Map params) 16 | : this(StoryModel.fromJson(json.decode(params['story']))); 17 | 18 | @override 19 | State createState() { 20 | return _PageState(); 21 | } 22 | } 23 | 24 | class _PageState extends State { 25 | int commentCount; 26 | int longComments; 27 | int shortComments; 28 | int favCount; 29 | bool collected; 30 | String storyUrl; 31 | 32 | @override 33 | void initState() { 34 | super.initState(); 35 | commentCount = 0; 36 | favCount = 0; 37 | collected = false; 38 | storyUrl = Urls.NEWS_DETAIL_WEB + widget.story.id.toString(); 39 | 40 | _loadData(); 41 | _checkCollectState(); 42 | } 43 | 44 | @override 45 | Widget build(BuildContext context) { 46 | return WebviewScaffold( 47 | url: storyUrl, 48 | appBar: _buildAppBar(), 49 | withZoom: true, 50 | withLocalStorage: true, 51 | ); 52 | } 53 | 54 | Widget _buildAppBar() { 55 | return AppBar( 56 | actions: [ 57 | _buildActionItem(Icons.share, _onPressShare), 58 | _buildActionItem( 59 | collected ? Icons.star : Icons.star_border, _onPressStar), 60 | _buildActionItem( 61 | Icons.comment, _onPressComment, text: commentCount.toString()), 62 | _buildActionItem( 63 | Icons.thumb_up, _onPressThumb, text: favCount.toString()), 64 | ], 65 | ); 66 | } 67 | 68 | Widget _buildActionItem(IconData icon, VoidCallback onPressed, 69 | {String text}) { 70 | if (text == null) { 71 | return IconButton(icon: Icon(icon), onPressed: onPressed); 72 | } else { 73 | return GestureDetector( 74 | onTap: onPressed, 75 | child: Padding( 76 | padding: EdgeInsets.all(8.0), 77 | child: Row(children: [ 78 | Icon(icon), 79 | Padding(padding: EdgeInsets.only(left: 4.0), child: Text(text)) 80 | ]),), 81 | ); 82 | } 83 | } 84 | 85 | _onPressShare() { 86 | 87 | } 88 | 89 | _onPressStar() async { 90 | if(collected) { 91 | if(await CollectionManager().delete(widget.story)) { 92 | setState(() { 93 | collected = false; 94 | }); 95 | } 96 | } else { 97 | if (await CollectionManager().collect(widget.story)) { 98 | setState(() { 99 | collected = true; 100 | }); 101 | } 102 | } 103 | } 104 | 105 | _onPressComment() { 106 | StringBuffer sb = StringBuffer(Pages.COMMENT); 107 | sb.write('?storyID='); 108 | sb.write(widget.story.id); 109 | sb.write('&longComments='); 110 | sb.write(longComments); 111 | sb.write('&shortComments='); 112 | sb.write(shortComments); 113 | Navigator.of(context).pushNamed(sb.toString()); 114 | } 115 | 116 | _onPressThumb() { 117 | 118 | } 119 | 120 | _loadData() async { 121 | String url = Urls.NEWS_EXTRA_INFO + widget.story.id.toString(); 122 | Response response = await get(url); 123 | if (response.statusCode == 200) { 124 | Map result = json.decode(response.body); 125 | setState(() { 126 | commentCount = result['comments']; 127 | longComments = result['long_comments']; 128 | shortComments = result['long_comments']; 129 | favCount = result['popularity']; 130 | }); 131 | } 132 | } 133 | 134 | _checkCollectState() { 135 | CollectionManager().hasCollected(widget.story) 136 | .then((hasCollected) { 137 | if (hasCollected) { 138 | setState(() { 139 | collected = hasCollected; 140 | }); 141 | } 142 | }); 143 | } 144 | } -------------------------------------------------------------------------------- /zhihu_daily/lib/widgets/homeBanner.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:zhihu_daily/model/story.dart'; 4 | 5 | class HomeBanner extends StatefulWidget { 6 | final List bannerStories; 7 | final OnTapBannerItem onTap; 8 | 9 | HomeBanner(this.bannerStories, this.onTap, {Key key}) 10 | :super(key: key); 11 | 12 | @override 13 | State createState() { 14 | return _BannerState(); 15 | } 16 | } 17 | 18 | class _BannerState extends State { 19 | int virtualIndex = 0; 20 | int realIndex = 1; 21 | PageController controller; 22 | Timer timer; 23 | 24 | @override 25 | void initState() { 26 | super.initState(); 27 | controller = PageController(initialPage: realIndex); 28 | timer = Timer.periodic(Duration(seconds: 5), (timer) { 29 | controller.animateToPage(realIndex + 1, 30 | duration: Duration(milliseconds: 300), 31 | curve: Curves.linear); 32 | }); 33 | } 34 | 35 | @override 36 | void dispose() { 37 | super.dispose(); 38 | controller.dispose(); 39 | timer.cancel(); 40 | } 41 | 42 | @override 43 | Widget build(BuildContext context) { 44 | return Container( 45 | height: 226.0, 46 | child: Stack( 47 | alignment: Alignment.bottomCenter, 48 | children: [ 49 | PageView( 50 | controller: controller, 51 | onPageChanged: _onPageChanged, 52 | children: _buildItems(),), 53 | _buildIndicator(), 54 | ]), 55 | ); 56 | } 57 | 58 | List _buildItems() { 59 | List items = []; 60 | if (widget.bannerStories.length > 0) { 61 | // 头部添加一个尾部Item,模拟循环 62 | items.add( 63 | _buildItem(widget.bannerStories[widget.bannerStories.length - 1])); 64 | // 正常添加Item 65 | items.addAll( 66 | widget.bannerStories.map((story) => _buildItem(story)).toList( 67 | growable: false)); 68 | // 尾部 69 | items.add( 70 | _buildItem(widget.bannerStories[0])); 71 | } 72 | return items; 73 | } 74 | 75 | Widget _buildItem(StoryModel story) { 76 | return GestureDetector( 77 | onTap: () { 78 | if (widget.onTap != null) { 79 | widget.onTap(story); 80 | } 81 | }, 82 | child: Stack( 83 | fit: StackFit.expand, 84 | children: [ 85 | Image.network(story.image, fit: BoxFit.cover), 86 | _buildItemTitle(story.title), 87 | ],),); 88 | } 89 | 90 | Widget _buildItemTitle(String title) { 91 | return Container( 92 | decoration: BoxDecoration( 93 | gradient: LinearGradient( 94 | begin: Alignment.bottomCenter, 95 | end: const Alignment(0.0, -0.8), 96 | colors: [const Color(0xa0000000), Colors.transparent], 97 | ), 98 | ), 99 | alignment: Alignment.bottomCenter, 100 | child: Container( 101 | margin: EdgeInsets.symmetric(vertical: 22.0, horizontal: 16.0), 102 | child: Text( 103 | title, style: TextStyle(color: Colors.white, fontSize: 22.0),),), 104 | ); 105 | } 106 | 107 | Widget _buildIndicator() { 108 | List indicators = []; 109 | for (int i = 0; i < widget.bannerStories.length; i++) { 110 | indicators.add(Container( 111 | width: 6.0, 112 | height: 6.0, 113 | margin: EdgeInsets.symmetric(horizontal: 1.5, vertical: 10.0), 114 | decoration: BoxDecoration( 115 | shape: BoxShape.circle, 116 | color: i == virtualIndex ? Colors.white : Colors.grey))); 117 | } 118 | return Row( 119 | mainAxisAlignment: MainAxisAlignment.center, 120 | children: indicators); 121 | } 122 | 123 | _onPageChanged(int index) { 124 | realIndex = index; 125 | int count = widget.bannerStories.length; 126 | if (index == 0) { 127 | virtualIndex = count - 1; 128 | controller.jumpToPage(count); 129 | } else if (index == count + 1) { 130 | virtualIndex = 0; 131 | controller.jumpToPage(1); 132 | } else { 133 | virtualIndex = index - 1; 134 | } 135 | setState(() {}); 136 | } 137 | } 138 | 139 | typedef void OnTapBannerItem(StoryModel story); -------------------------------------------------------------------------------- /music_player/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void main() => runApp(new MyApp()); 4 | 5 | class MyApp extends StatelessWidget { 6 | // This widget is the root of your application. 7 | @override 8 | Widget build(BuildContext context) { 9 | return new MaterialApp( 10 | title: 'Flutter Demo', 11 | theme: new ThemeData( 12 | // This is the theme of your application. 13 | // 14 | // Try running your application with "flutter run". You'll see the 15 | // application has a blue toolbar. Then, without quitting the app, try 16 | // changing the primarySwatch below to Colors.green and then invoke 17 | // "hot reload" (press "r" in the console where you ran "flutter run", 18 | // or press Run > Flutter Hot Reload in IntelliJ). Notice that the 19 | // counter didn't reset back to zero; the application is not restarted. 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: new MyHomePage(title: 'Flutter Demo Home Page'), 23 | ); 24 | } 25 | } 26 | 27 | class MyHomePage extends StatefulWidget { 28 | MyHomePage({Key key, this.title}) : super(key: key); 29 | 30 | // This widget is the home page of your application. It is stateful, meaning 31 | // that it has a State object (defined below) that contains fields that affect 32 | // how it looks. 33 | 34 | // This class is the configuration for the state. It holds the values (in this 35 | // case the title) provided by the parent (in this case the App widget) and 36 | // used by the build method of the State. Fields in a Widget subclass are 37 | // always marked "final". 38 | 39 | final String title; 40 | 41 | @override 42 | _MyHomePageState createState() => new _MyHomePageState(); 43 | } 44 | 45 | class _MyHomePageState extends State { 46 | int _counter = 0; 47 | 48 | void _incrementCounter() { 49 | setState(() { 50 | // This call to setState tells the Flutter framework that something has 51 | // changed in this State, which causes it to rerun the build method below 52 | // so that the display can reflect the updated values. If we changed 53 | // _counter without calling setState(), then the build method would not be 54 | // called again, and so nothing would appear to happen. 55 | _counter++; 56 | }); 57 | } 58 | 59 | @override 60 | Widget build(BuildContext context) { 61 | // This method is rerun every time setState is called, for instance as done 62 | // by the _incrementCounter method above. 63 | // 64 | // The Flutter framework has been optimized to make rerunning build methods 65 | // fast, so that you can just rebuild anything that needs updating rather 66 | // than having to individually change instances of widgets. 67 | return new Scaffold( 68 | appBar: new AppBar( 69 | // Here we take the value from the MyHomePage object that was created by 70 | // the App.build method, and use it to set our appbar title. 71 | title: new Text(widget.title), 72 | ), 73 | body: new Center( 74 | // Center is a layout widget. It takes a single child and positions it 75 | // in the middle of the parent. 76 | child: new Column( 77 | // Column is also layout widget. It takes a list of children and 78 | // arranges them vertically. By default, it sizes itself to fit its 79 | // children horizontally, and tries to be as tall as its parent. 80 | // 81 | // Invoke "debug paint" (press "p" in the console where you ran 82 | // "flutter run", or select "Toggle Debug Paint" from the Flutter tool 83 | // window in IntelliJ) to see the wireframe for each widget. 84 | // 85 | // Column has various properties to control how it sizes itself and 86 | // how it positions its children. Here we use mainAxisAlignment to 87 | // center the children vertically; the main axis here is the vertical 88 | // axis because Columns are vertical (the cross axis would be 89 | // horizontal). 90 | mainAxisAlignment: MainAxisAlignment.center, 91 | children: [ 92 | new Text( 93 | 'You have pushed the button this many times:', 94 | ), 95 | new Text( 96 | '$_counter', 97 | style: Theme.of(context).textTheme.display1, 98 | ), 99 | ], 100 | ), 101 | ), 102 | floatingActionButton: new FloatingActionButton( 103 | onPressed: _incrementCounter, 104 | tooltip: 'Increment', 105 | child: new Icon(Icons.add), 106 | ), // This trailing comma makes auto-formatting nicer for build methods. 107 | ); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /music_player/android/app/src/main/java/cz/musicplayer/methodChannel/PlayerMethodHandler.java: -------------------------------------------------------------------------------- 1 | package cz.musicplayer.methodChannel; 2 | 3 | import android.media.AudioManager; 4 | import android.media.MediaPlayer; 5 | 6 | import java.io.IOException; 7 | 8 | import io.flutter.plugin.common.BinaryMessenger; 9 | import io.flutter.plugin.common.MethodCall; 10 | import io.flutter.plugin.common.MethodChannel; 11 | 12 | /** 13 | * @author haozhou 14 | */ 15 | 16 | public class PlayerMethodHandler implements MethodChannel.MethodCallHandler { 17 | private static final String CHANNEL_NAME = "cz.musicplayer/player"; 18 | 19 | private static final String METHOD_PLAY = "play"; 20 | private static final String METHOD_PAUSE = "pause"; 21 | private static final String METHOD_RESUME = "resume"; 22 | private static final String METHOD_STOP = "stop"; 23 | private static final String METHOD_SEEK = "seek"; 24 | private static final String METHOD_GET_CURRENT_POSITION = "getCurrentPosition"; 25 | private static final String METHOD_GET_DURATION = "getDuration"; 26 | private static final String METHOD_IS_PLAYING = "isPlaying"; 27 | 28 | private static final String PARAM_PATH = "path"; 29 | 30 | public static void register(BinaryMessenger messenger) { 31 | MethodChannel methodChannel = new MethodChannel(messenger, CHANNEL_NAME); 32 | methodChannel.setMethodCallHandler(new PlayerMethodHandler(methodChannel)); 33 | } 34 | 35 | private MethodChannel methodChannel; 36 | private MediaPlayer mediaPlayer; 37 | 38 | private PlayerMethodHandler(MethodChannel channel) { 39 | methodChannel = channel; 40 | mediaPlayer = new MediaPlayer(); 41 | mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 42 | 43 | initPlayerListener(); 44 | } 45 | 46 | private void initPlayerListener() { 47 | mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { 48 | @Override 49 | public void onPrepared(MediaPlayer mediaPlayer) { 50 | mediaPlayer.start(); 51 | } 52 | }); 53 | mediaPlayer.setOnInfoListener(new MediaPlayer.OnInfoListener() { 54 | @Override 55 | public boolean onInfo(MediaPlayer mediaPlayer, int i, int i1) { 56 | return false; 57 | } 58 | }); 59 | mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 60 | @Override 61 | public void onCompletion(MediaPlayer mediaPlayer) { 62 | 63 | } 64 | }); 65 | mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { 66 | @Override 67 | public boolean onError(MediaPlayer mediaPlayer, int i, int i1) { 68 | return false; 69 | } 70 | }); 71 | } 72 | 73 | @Override 74 | public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) { 75 | String method = methodCall.method; 76 | switch (method) { 77 | case METHOD_PLAY: 78 | onPlayCall(methodCall, result); 79 | break; 80 | case METHOD_PAUSE: 81 | onPauseCall(methodCall, result); 82 | break; 83 | case METHOD_RESUME: 84 | onResumeCall(methodCall, result); 85 | break; 86 | case METHOD_STOP: 87 | onStopCall(methodCall, result); 88 | break; 89 | case METHOD_SEEK: 90 | onSeekCall(methodCall, result); 91 | break; 92 | default: 93 | result.notImplemented(); 94 | break; 95 | } 96 | } 97 | 98 | private void onPlayCall(MethodCall methodCall, MethodChannel.Result result) { 99 | String path = methodCall.argument(PARAM_PATH); 100 | if (path != null) { 101 | try { 102 | play(path); 103 | } catch (IOException e) { 104 | result.error("error", e.getMessage(), null); 105 | } 106 | } else { 107 | result.error("error", "path can't be null", null); 108 | } 109 | } 110 | 111 | private void onPauseCall(MethodCall methodCall, MethodChannel.Result result) { 112 | 113 | } 114 | 115 | private void onResumeCall(MethodCall methodCall, MethodChannel.Result result) { 116 | 117 | } 118 | 119 | private void onStopCall(MethodCall methodCall, MethodChannel.Result result) { 120 | 121 | } 122 | 123 | private void onSeekCall(MethodCall methodCall, MethodChannel.Result result) { 124 | 125 | } 126 | 127 | private void play(String path) throws IOException { 128 | mediaPlayer.setDataSource(path); 129 | mediaPlayer.prepareAsync(); 130 | } 131 | } 132 | --------------------------------------------------------------------------------