├── .flutter-plugins-dependencies
├── .gitignore
├── .metadata
├── README.md
├── Scheme.md
├── android
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── flutter_share
│ │ │ │ └── MainActivity.java
│ │ └── res
│ │ │ ├── drawable
│ │ │ └── launch_background.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
│ │ │ └── values
│ │ │ └── styles.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── settings.gradle
└── settings_aar.gradle
├── assets
└── data
│ └── users.json
├── images
├── aone.jpg
├── athree.jpg
├── atwo.jpg
├── avatar.jpg
├── barchart.jpg
├── bg.jpg
├── linechart.png
└── piechart.jpg
├── ios
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ ├── Flutter.podspec
│ └── Release.xcconfig
├── Podfile
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── Runner
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-App-1024x1024@1x.png
│ │ ├── 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-83.5x83.5@2x.png
│ └── LaunchImage.imageset
│ │ ├── Contents.json
│ │ ├── LaunchImage.png
│ │ ├── LaunchImage@2x.png
│ │ ├── LaunchImage@3x.png
│ │ └── README.md
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ └── main.m
├── lib
├── FutureBuilderProblem
│ └── FutureBuilderMain.dart
├── animatedIcon
│ └── AnimatedIconPage.dart
├── animatedSwitcher
│ ├── AnimatedSwitcherCounterRoute.dart
│ └── SlideTransitionX.dart
├── autocomplete
│ ├── CountriesField.dart
│ └── OverlayMain.dart
├── chartsDisplay
│ ├── ChartDispalyMain.dart
│ ├── bar_chart.dart
│ ├── grades_data.dart
│ ├── line_chart.dart
│ ├── pie_chart.dart
│ ├── population_data.dart
│ └── sales_data.dart
├── downloadDemo
│ └── DownDemoMain.dart
├── flutterSearch
│ └── searchbarview.dart
├── heroAnimation
│ ├── HeroAnimPage.dart
│ ├── HeroAnimationRouteB.dart
│ ├── Photo.dart
│ ├── RadialExpansion.dart
│ └── RadialExpansionDemo.dart
├── implicitAnimation
│ ├── AnimatedContainerDemo.dart
│ └── FadeInDemo.dart
├── main.dart
├── navigationrail
│ └── NavigationRailMain.dart
├── nestedScrollView
│ ├── DemoOne.dart
│ └── DemoTwo.dart
├── path
│ ├── CircleProgressBarPainter.dart
│ ├── Circles.dart
│ ├── DashLinePainter.dart
│ ├── LinePainter.dart
│ ├── PathAdvancedMain.dart
│ ├── PathBasicsMain.dart
│ ├── PathPainter.dart
│ ├── Planets.dart
│ ├── Polygon.dart
│ └── Spiral.dart
├── perspective
│ ├── FlipAnimationMain.dart
│ ├── FlipPanel.dart
│ ├── FlipWidget.dart
│ └── PerspectiveMain.dart
├── refreshData
│ └── refresh_data.dart
├── scheme
│ ├── home_index.dart
│ ├── router.dart
│ ├── user_index.dart
│ └── web_view_page.dart
├── stateManager
│ ├── BasicCounter.dart
│ ├── BasicUse
│ │ └── provider_basic.dart
│ ├── EventProvider.dart
│ ├── User.dart
│ ├── UserList.dart
│ ├── common
│ │ └── theme.dart
│ ├── index_main.dart
│ ├── models
│ │ ├── cart.dart
│ │ └── catalog.dart
│ ├── my_event_page.dart
│ ├── my_userpage.dart
│ ├── screens
│ │ ├── cart.dart
│ │ └── catalog.dart
│ └── user_provider.dart
└── utils
│ └── json_config.dart
├── pubspec.lock
├── pubspec.yaml
└── test
└── widget_test.dart
/.flutter-plugins-dependencies:
--------------------------------------------------------------------------------
1 | {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_webview_plugin","path":"/Users/wanghaichao/Develop/FlutterSDK/flutter/.pub-cache/hosted/pub.flutter-io.cn/flutter_webview_plugin-0.3.0+2/","dependencies":[]},{"name":"path_provider","path":"/Users/wanghaichao/Develop/FlutterSDK/flutter/.pub-cache/hosted/pub.flutter-io.cn/path_provider-1.6.9/","dependencies":[]},{"name":"simple_permissions","path":"/Users/wanghaichao/Develop/FlutterSDK/flutter/.pub-cache/hosted/pub.flutter-io.cn/simple_permissions-0.1.9/","dependencies":[]},{"name":"uni_links","path":"/Users/wanghaichao/Develop/FlutterSDK/flutter/.pub-cache/hosted/pub.flutter-io.cn/uni_links-0.4.0/","dependencies":[]}],"android":[{"name":"flutter_webview_plugin","path":"/Users/wanghaichao/Develop/FlutterSDK/flutter/.pub-cache/hosted/pub.flutter-io.cn/flutter_webview_plugin-0.3.0+2/","dependencies":[]},{"name":"path_provider","path":"/Users/wanghaichao/Develop/FlutterSDK/flutter/.pub-cache/hosted/pub.flutter-io.cn/path_provider-1.6.9/","dependencies":[]},{"name":"simple_permissions","path":"/Users/wanghaichao/Develop/FlutterSDK/flutter/.pub-cache/hosted/pub.flutter-io.cn/simple_permissions-0.1.9/","dependencies":[]},{"name":"uni_links","path":"/Users/wanghaichao/Develop/FlutterSDK/flutter/.pub-cache/hosted/pub.flutter-io.cn/uni_links-0.4.0/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/wanghaichao/Develop/FlutterSDK/flutter/.pub-cache/hosted/pub.flutter-io.cn/path_provider_macos-0.0.4+3/","dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"flutter_webview_plugin","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]},{"name":"simple_permissions","dependencies":[]},{"name":"uni_links","dependencies":[]}],"date_created":"2021-02-16 11:05:53.962445","version":"1.22.6"}
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | .dart_tool/
26 | .flutter-plugins
27 | .packages
28 | .pub-cache/
29 | .pub/
30 | /build/
31 |
32 | # Android related
33 | **/android/**/gradle-wrapper.jar
34 | **/android/.gradle
35 | **/android/captures/
36 | **/android/gradlew
37 | **/android/gradlew.bat
38 | **/android/local.properties
39 | **/android/**/GeneratedPluginRegistrant.java
40 |
41 | # iOS/XCode related
42 | **/ios/**/*.mode1v3
43 | **/ios/**/*.mode2v3
44 | **/ios/**/*.moved-aside
45 | **/ios/**/*.pbxuser
46 | **/ios/**/*.perspectivev3
47 | **/ios/**/*sync/
48 | **/ios/**/.sconsign.dblite
49 | **/ios/**/.tags*
50 | **/ios/**/.vagrant/
51 | **/ios/**/DerivedData/
52 | **/ios/**/Icon?
53 | **/ios/**/Pods/
54 | **/ios/**/.symlinks/
55 | **/ios/**/profile
56 | **/ios/**/xcuserdata
57 | **/ios/.generated/
58 | **/ios/Flutter/App.framework
59 | **/ios/Flutter/Flutter.framework
60 | **/ios/Flutter/Generated.xcconfig
61 | **/ios/Flutter/app.flx
62 | **/ios/Flutter/app.zip
63 | **/ios/Flutter/flutter_assets/
64 | **/ios/Flutter/flutter_export_environment.sh
65 | **/ios/ServiceDefinitions.json
66 | **/ios/Runner/GeneratedPluginRegistrant.*
67 |
68 | # Exceptions to above rules.
69 | !**/ios/**/default.mode1v3
70 | !**/ios/**/default.mode2v3
71 | !**/ios/**/default.pbxuser
72 | !**/ios/**/default.perspectivev3
73 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
74 |
--------------------------------------------------------------------------------
/.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: 78cca6250a7104cc1dd89edf1982878530e55ee6
8 | channel: master
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | flutter sdk 升级为最新版本。
2 |
3 | 打开 Android 项目,同步代码,并迁移至 Androidx。
4 |
5 |
6 | ===
7 |
8 |
9 |
10 | [1、RefreshIndicator+FutureBuilder 实现下拉刷新上滑加载数据](https://juejin.im/post/5d6b26755188255d3d29acea)
11 |
12 | [2、NestedScrollView 和 SliverAppBar 的使用](https://juejin.im/post/5d71091a6fb9a06af824fbad)
13 |
14 | [3、Flutter 全局状态管理之 Provider 初探](https://juejin.im/post/5d8f324ee51d45781e0f5dca)
15 |
16 | [4、Flutter showSearch 与 AnimatedIcon 的使用](https://juejin.im/post/5da27fd86fb9a04dd95e846d)
17 |
18 | [5、Flutter Provider 之 FutureProvider 与 StreamProvider](https://juejin.im/post/5dea6259f265da33c14d0951)
19 |
20 | [6、Flutter 图表绘制](https://juejin.im/post/5e7eafc26fb9a03c53517244)
21 |
22 | [7、Flutter 使用 Overlay 实现全局弹窗](https://juejin.im/post/5e87f43051882573cd41a342)
23 |
24 | [8、Flutter 3D 动画](https://juejin.im/post/5e90739ee51d4546fd48169a)
25 |
26 | [9、停止 FutrueBuilder 的重复刷新和执行](https://juejin.im/post/5e9a95f4e51d4546eb52566b)
27 |
28 | [10、Path 基础 ](https://juejin.im/post/5ea2f88851882573be11e082)
29 |
30 | [11、Path 进阶 ](https://juejin.im/post/5eaf85c6e51d454ddc100f97)
31 |
32 | [12、实现文件下载 ](https://juejin.im/post/5eab9b376fb9a0434a2e55a8)
33 |
34 | [13、Flutter 使用 Github 进行 CI/CD](https://juejin.im/post/5ebfaeac6fb9a0435a01e241)
35 |
36 | [14、Flutter NavigationRail Demo](https://juejin.im/post/5ed10da66fb9a0479a800c5e)
37 |
38 |
39 | [15、Flutter 隐式动画](https://juejin.im/post/5eecc7baf265da028e749f47)
40 |
41 | [16、Widget、RenderObject 与 Element](https://juejin.im/post/5eff34c76fb9a07e8b2137f2)
42 |
43 | [17、Hero 动画](https://juejin.im/post/6861533747716554766)
44 |
45 |
--------------------------------------------------------------------------------
/Scheme.md:
--------------------------------------------------------------------------------
1 | #### 一、GitHub 上配置一个 html(或者任何本地可以打开的 html 都可以)
2 |
3 | github 上 setting 上 GitHub Pages 可以看到 html 的 访问链接
4 | ```
5 |
6 |
7 |
8 |
9 |
10 | Scheme 跳转
11 |
17 |
18 |
19 |
20 | tyfapp://
21 |
26 | tyfapp://homepage
27 |
32 | tyfapp://userpage
33 |
38 |
39 |
40 | ```
41 |
42 |
43 | #### 二、flutter 端配置
44 | main 中需要配置 router
45 | ```
46 | routes: MyRouter().registerRouter(),
47 | ```
48 |
49 | 外部链接跳转逻辑
50 | ```
51 | /// 使用[String]链接实现
52 | Future initPlatformStateForStringUniLinks() async {
53 | String initialLink;
54 | // Platform messages may fail, so we use a try/catch PlatformException.
55 | try {
56 | initialLink = await getInitialLink();
57 | if (initialLink != null) {
58 | // 跳转到指定页面
59 | router.push(context, initialLink);
60 | }
61 | } on PlatformException {
62 | initialLink = 'Failed to get initial link.';
63 | } on FormatException {
64 | initialLink = 'Failed to parse the initial link as Uri.';
65 | }
66 | // Attach a listener to the links stream
67 | _sub = getLinksStream().listen((String link) {
68 | if (!mounted || link == null) return;
69 | // 跳转到指定页面
70 | router.push(context, link);
71 | }, onError: (Object err) {
72 | if (!mounted) return;
73 | });
74 | }
75 |
76 |
77 | ```
78 |
79 |
80 |
81 | #### 三 、Android 端配置
82 | ```
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
92 |
93 |
94 |
95 | ```
96 |
97 | #### 四、iOS 中配置
98 | ios/Runner/info.plist
99 |
100 | 在 dict 内增加下面的配置:
101 |
102 |
103 | ```
104 | CFBundleURLTypes
105 |
106 |
107 |
108 |
109 |
110 | CFBundleTypeRole
111 |
112 | Editor
113 |
114 | CFBundleURLName
115 |
116 | Two You
117 |
118 | CFBundleURLSchemes
119 |
120 |
121 |
122 | tyfapp
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 | ```
--------------------------------------------------------------------------------
/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 28
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 "com.example.flutter_share"
37 | minSdkVersion 16
38 | targetSdkVersion 28
39 | versionCode flutterVersionCode.toInteger()
40 | versionName flutterVersionName
41 | testInstrumentationRunner "androidx.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 'androidx.test:runner:1.1.0'
60 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
61 | }
62 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
19 |
26 |
30 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/example/flutter_share/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.flutter_share;
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 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | maven { url 'https://maven.aliyun.com/repository/public/' }
4 | maven {
5 | url 'http://download.flutter.io'
6 | }
7 | google()
8 | jcenter()
9 | }
10 |
11 | dependencies {
12 | classpath 'com.android.tools.build:gradle:3.2.1'
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | maven { url 'https://maven.aliyun.com/repository/public/' }
19 | google()
20 | jcenter()
21 | maven {
22 | url 'http://download.flutter.io'
23 | }
24 | }
25 | }
26 |
27 | rootProject.buildDir = '../build'
28 | subprojects {
29 | project.buildDir = "${rootProject.buildDir}/${project.name}"
30 | }
31 | subprojects {
32 | project.evaluationDependsOn(':app')
33 | }
34 |
35 | task clean(type: Delete) {
36 | delete rootProject.buildDir
37 | }
38 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 |
3 | android.enableR8=true
4 | android.useAndroidX=true
5 | android.enableJetifier=true
6 |
7 |
--------------------------------------------------------------------------------
/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.10.2-all.zip
7 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/android/settings_aar.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/assets/data/users.json:
--------------------------------------------------------------------------------
1 | {
2 | "users": [
3 | {
4 | "first_name": "Douglas",
5 | "last_name": "Tober",
6 | "website": "Codetober.com"
7 | },
8 | {
9 | "first_name": "Brad",
10 | "last_name": "Traversy",
11 | "website": "traversymedia.com"
12 | },
13 | {
14 | "first_name": "Bucky",
15 | "last_name": "Roberts",
16 | "website": "lhventures.us"
17 | },
18 | {
19 | "first_name": "Doug",
20 | "last_name": "Tober",
21 | "website": "j5technology.com"
22 | }
23 | ]
24 | }
--------------------------------------------------------------------------------
/images/aone.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/images/aone.jpg
--------------------------------------------------------------------------------
/images/athree.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/images/athree.jpg
--------------------------------------------------------------------------------
/images/atwo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/images/atwo.jpg
--------------------------------------------------------------------------------
/images/avatar.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/images/avatar.jpg
--------------------------------------------------------------------------------
/images/barchart.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/images/barchart.jpg
--------------------------------------------------------------------------------
/images/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/images/bg.jpg
--------------------------------------------------------------------------------
/images/linechart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/images/linechart.png
--------------------------------------------------------------------------------
/images/piechart.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/images/piechart.jpg
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Flutter/Flutter.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # NOTE: This podspec is NOT to be published. It is only used as a local source!
3 | #
4 |
5 | Pod::Spec.new do |s|
6 | s.name = 'Flutter'
7 | s.version = '1.0.0'
8 | s.summary = 'High-performance, high-fidelity mobile apps.'
9 | s.description = <<-DESC
10 | Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS.
11 | DESC
12 | s.homepage = 'https://flutter.io'
13 | s.license = { :type => 'MIT' }
14 | s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
15 | s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s }
16 | s.ios.deployment_target = '8.0'
17 | s.vendored_frameworks = 'Flutter.framework'
18 | end
19 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '9.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
32 | end
33 |
34 | post_install do |installer|
35 | installer.pods_project.targets.each do |target|
36 | flutter_additional_ios_build_settings(target)
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : FlutterAppDelegate
5 |
6 | @end
7 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hcc007/FlutterShare/e1a417df3491722c915ac7bf70190f5803e6d200/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/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.
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | flutter_share
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 | CFBundleURLTypes
46 |
47 |
48 |
49 |
50 |
51 | CFBundleTypeRole
52 |
53 | Editor
54 |
55 | CFBundleURLName
56 |
57 | Two You
58 |
59 | CFBundleURLSchemes
60 |
61 |
62 |
63 | tyfapp
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/lib/FutureBuilderProblem/FutureBuilderMain.dart:
--------------------------------------------------------------------------------
1 | import 'package:async/async.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_share/perspective/FlipWidget.dart';
4 |
5 |
6 | class FutureBuilderMain extends StatefulWidget {
7 | @override
8 | _FutureBuilderMainMainState createState() => _FutureBuilderMainMainState();
9 | }
10 |
11 | class _FutureBuilderMainMainState extends State {
12 |
13 |
14 | bool _switchValue;
15 | final AsyncMemoizer _memoizer = AsyncMemoizer();
16 |
17 |
18 | @override
19 | void initState() {
20 | super.initState();
21 | this._switchValue = false;
22 |
23 | }
24 |
25 |
26 |
27 | @override
28 | Widget build(BuildContext context) {
29 |
30 |
31 | return new Scaffold(
32 |
33 | body: Column(
34 | mainAxisAlignment: MainAxisAlignment.center,
35 | children: [
36 | Switch(
37 | value: this._switchValue,
38 | onChanged: (newValue) {
39 | setState(() {
40 | this._switchValue = newValue;
41 | });
42 | },
43 |
44 |
45 |
46 | ),
47 | FutureBuilder(
48 | future: this._fetchData(_switchValue),
49 | builder: (context, snapshot) {
50 | switch (snapshot.connectionState) {
51 | case ConnectionState.none:
52 | case ConnectionState.waiting:
53 | return Center(
54 | child: CircularProgressIndicator()
55 | );
56 | default:
57 | return Center(
58 | child: Text(snapshot.data)
59 | );
60 | }
61 | }
62 | ),
63 | ],
64 | ),
65 |
66 | );
67 |
68 |
69 | }
70 |
71 | _fetchData(bool flag) async{
72 | if(flag){
73 | return this._memoizer.runOnce(() async {
74 | await Future.delayed(Duration(seconds: 2));
75 | return 'REMOTE DATA';
76 | });
77 | }else{
78 | await Future.delayed(Duration(seconds: 5));
79 | return 'REMOTE DATA';
80 | }
81 | }
82 |
83 | }
--------------------------------------------------------------------------------
/lib/animatedIcon/AnimatedIconPage.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class AnimatedIconPage extends StatefulWidget {
4 | @override
5 | _AnimatedIconPageState createState() => _AnimatedIconPageState();
6 | }
7 |
8 | class _AnimatedIconPageState extends State
9 | with SingleTickerProviderStateMixin {
10 |
11 | AnimationController controller;
12 | List _icons;
13 | List _names;
14 |
15 |
16 | @override
17 | void initState() {
18 | super.initState();
19 | controller = AnimationController(vsync: this)
20 | ..drive(Tween(begin: 0, end: 1))
21 | ..duration = Duration(milliseconds: 500);
22 |
23 | _names = [
24 | 'play_pause',
25 | 'add_event',
26 | 'arrow_menu',
27 | 'close_menu',
28 | 'ellipsis_search',
29 | 'event_add',
30 | 'home_menu',
31 | 'list_view',
32 | 'menu_arrow',
33 | 'menu_close',
34 | 'menu_home',
35 | 'pause_play',
36 | 'search_ellipsis',
37 | 'view_list',
38 | ];
39 |
40 |
41 | }
42 |
43 | @override
44 | Widget build(BuildContext context) {
45 |
46 | _icons = [
47 | AnimatedIcon(
48 | icon: AnimatedIcons.play_pause,
49 | progress: controller,
50 | size: 35,
51 | semanticLabel: "play_pause",
52 | ),
53 | AnimatedIcon(
54 | icon: AnimatedIcons.add_event,
55 | progress: controller,
56 | size: 35,
57 | ),
58 | AnimatedIcon(
59 | icon: AnimatedIcons.arrow_menu,
60 | progress: controller,
61 | size: 35,
62 | ),
63 | AnimatedIcon(
64 | icon: AnimatedIcons.close_menu,
65 | progress: controller,
66 | size: 35,
67 | ),
68 | AnimatedIcon(
69 | icon: AnimatedIcons.ellipsis_search,
70 | progress: controller,
71 | size: 35,
72 | ),
73 | AnimatedIcon(
74 | icon: AnimatedIcons.event_add,
75 | progress: controller,
76 | size: 35,
77 | ),
78 | AnimatedIcon(
79 | icon: AnimatedIcons.home_menu,
80 | progress: controller,
81 | size: 35,
82 | ),
83 | AnimatedIcon(
84 | icon: AnimatedIcons.list_view,
85 | progress: controller,
86 | size: 35,
87 | ),
88 | AnimatedIcon(
89 | icon: AnimatedIcons.menu_arrow,
90 | progress: controller,
91 | size: 35,
92 | ),
93 | AnimatedIcon(
94 | icon: AnimatedIcons.menu_close,
95 | progress: controller,
96 | size: 35,
97 | ),
98 | AnimatedIcon(
99 | icon: AnimatedIcons.menu_home,
100 | progress: controller,
101 | size: 35,
102 | ),
103 | AnimatedIcon(
104 | icon: AnimatedIcons.pause_play,
105 | progress: controller,
106 | size: 35,
107 | ),
108 | AnimatedIcon(
109 | icon: AnimatedIcons.search_ellipsis,
110 | progress: controller,
111 | size: 35,
112 | ),
113 | AnimatedIcon(
114 | icon: AnimatedIcons.view_list,
115 | progress: controller,
116 | size: 35,
117 | ),
118 | ];
119 |
120 |
121 | return Scaffold(
122 | appBar: AppBar(
123 | title: Text('AnimatedIconPage'),
124 | ),
125 | //body: _buildPausePlayIcon(),
126 | body: _buildGridView(),
127 | );
128 | }
129 |
130 | Widget _buildGridView() {
131 | return GridView.builder(
132 | itemCount: _icons.length,
133 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
134 | crossAxisCount: 3,
135 | mainAxisSpacing: 10,
136 | crossAxisSpacing: 10,
137 | ),
138 | itemBuilder: (context, index) {
139 | return Center(
140 | child: Column(
141 | mainAxisSize: MainAxisSize.min,
142 | children: [
143 |
144 | InkWell(
145 | child: _icons[index],
146 |
147 | onTap: () {
148 | if (controller.status == AnimationStatus.completed) {
149 | controller.reverse();
150 | } else if (controller.status == AnimationStatus.dismissed) {
151 | controller.forward();
152 | }
153 | },
154 | ),
155 |
156 | Padding(
157 | padding: const EdgeInsets.only(top: 20.0),
158 | child: Text(_names[index]),
159 | ),
160 | ],
161 | ),
162 | );
163 | },
164 | );
165 | }
166 |
167 |
168 | @override
169 | void dispose() {
170 | super.dispose();
171 | controller.dispose();
172 | }
173 | }
--------------------------------------------------------------------------------
/lib/animatedSwitcher/AnimatedSwitcherCounterRoute.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'SlideTransitionX.dart';
4 |
5 | class AnimatedSwitcherCounterRoute extends StatefulWidget {
6 | const AnimatedSwitcherCounterRoute({Key key}) : super(key: key);
7 |
8 | @override
9 | _AnimatedSwitcherCounterRouteState createState() => _AnimatedSwitcherCounterRouteState();
10 | }
11 |
12 | class _AnimatedSwitcherCounterRouteState extends State {
13 | int _count = 0;
14 |
15 | @override
16 | Widget build(BuildContext context) {
17 | return Center(
18 | child: Column(
19 | mainAxisAlignment: MainAxisAlignment.center,
20 | children: [
21 | AnimatedSwitcher(
22 | duration: const Duration(milliseconds: 500),
23 | transitionBuilder: (Widget child, Animation animation) {
24 |
25 | ///缩放动画
26 | // return ScaleTransition(child: child, scale: animation);
27 |
28 | ///上下左右平移动画
29 | return SlideTransitionX(
30 | child: child,
31 | direction: AxisDirection.up, //上入下出
32 | position: animation,
33 | );
34 |
35 | },
36 | child: Text(
37 | '$_count',
38 | //显示指定key,不同的key会被认为是不同的Text,这样才能执行动画
39 | key: ValueKey(_count),
40 | style: Theme.of(context).textTheme.display1,
41 | ),
42 | ),
43 |
44 |
45 | RaisedButton(
46 | child: const Text('+1',),
47 | onPressed: () {
48 | setState(() {
49 | _count += 1;
50 | });
51 | },
52 | ),
53 |
54 |
55 | ],
56 | ),
57 | );
58 | }
59 | }
--------------------------------------------------------------------------------
/lib/animatedSwitcher/SlideTransitionX.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class SlideTransitionX extends AnimatedWidget {
4 | SlideTransitionX({
5 | Key key,
6 | @required Animation position,
7 | this.transformHitTests = true,
8 | this.direction = AxisDirection.down,
9 | this.child,
10 | })
11 | : assert(position != null),
12 | super(key: key, listenable: position) {
13 | // 偏移在内部处理
14 | switch (direction) {
15 | case AxisDirection.up:
16 | _tween = Tween(begin: Offset(0, 1), end: Offset(0, 0));
17 | break;
18 | case AxisDirection.right:
19 | _tween = Tween(begin: Offset(-1, 0), end: Offset(0, 0));
20 | break;
21 | case AxisDirection.down:
22 | _tween = Tween(begin: Offset(0, -1), end: Offset(0, 0));
23 | break;
24 | case AxisDirection.left:
25 | _tween = Tween(begin: Offset(1, 0), end: Offset(0, 0));
26 | break;
27 | }
28 | }
29 |
30 |
31 | Animation get position => listenable;
32 |
33 | final bool transformHitTests;
34 |
35 | final Widget child;
36 |
37 | //退场(出)方向
38 | final AxisDirection direction;
39 |
40 | Tween _tween;
41 |
42 | @override
43 | Widget build(BuildContext context) {
44 | Offset offset = _tween.evaluate(position);
45 | if (position.status == AnimationStatus.reverse) {
46 | switch (direction) {
47 | case AxisDirection.up:
48 | offset = Offset(offset.dx, -offset.dy);
49 | break;
50 | case AxisDirection.right:
51 | offset = Offset(-offset.dx, offset.dy);
52 | break;
53 | case AxisDirection.down:
54 | offset = Offset(offset.dx, -offset.dy);
55 | break;
56 | case AxisDirection.left:
57 | offset = Offset(-offset.dx, offset.dy);
58 | break;
59 | }
60 | }
61 | return FractionalTranslation(
62 | translation: offset,
63 | transformHitTests: transformHitTests,
64 | child: child,
65 | );
66 | }
67 | }
--------------------------------------------------------------------------------
/lib/autocomplete/CountriesField.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class CountriesField extends StatefulWidget {
4 | @override
5 | _CountriesFieldState createState() => _CountriesFieldState();
6 | }
7 |
8 | class _CountriesFieldState extends State {
9 |
10 | final FocusNode _focusNode = FocusNode();
11 |
12 | OverlayEntry _overlayEntry;
13 |
14 | final LayerLink _layerLink = LayerLink();
15 |
16 | TextEditingController controller;
17 |
18 | @override
19 | void initState() {
20 |
21 | controller = new TextEditingController();
22 | _focusNode.addListener(() {
23 | if (_focusNode.hasFocus) {
24 |
25 | this._overlayEntry = this._createOverlayEntry();
26 | Overlay.of(context).insert(this._overlayEntry);
27 |
28 | } else {
29 | this._overlayEntry.remove();
30 | }
31 | });
32 | }
33 |
34 |
35 | @override
36 | void dispose() {
37 | this._overlayEntry.remove();
38 | super.dispose();
39 | }
40 |
41 |
42 |
43 | OverlayEntry _createOverlayEntry() {
44 |
45 | RenderBox renderBox = context.findRenderObject();
46 | var size = renderBox.size;
47 |
48 | return OverlayEntry(
49 | builder: (context) => Positioned(
50 | width: size.width,
51 | child: CompositedTransformFollower(
52 | link: this._layerLink,
53 | showWhenUnlinked: false,
54 | offset: Offset(0.0, size.height + 5.0),
55 | child: Material(
56 | elevation: 4.0,
57 | child: ListView(
58 | padding: EdgeInsets.zero,
59 | shrinkWrap: true,
60 | children: [
61 | ListTile(
62 | title: Text('中国'),
63 | onTap: () {
64 | controller.text = "中国";
65 | this._overlayEntry.remove();
66 | setState(() {
67 |
68 | });
69 | },
70 | ),
71 | ListTile(
72 | title: Text('美国'),
73 | onTap: () {
74 | controller.text = "美国";
75 | this._overlayEntry.remove();
76 | setState(() {
77 |
78 | });
79 | },
80 | )
81 | ],
82 | ),
83 | ),
84 | ),
85 | )
86 | );
87 |
88 |
89 | }
90 |
91 | @override
92 | Widget build(BuildContext context) {
93 | return CompositedTransformTarget(
94 | link: this._layerLink,
95 | child: TextFormField(
96 | focusNode: this._focusNode,
97 | controller:controller ,
98 | decoration: InputDecoration(
99 | labelText: 'Country'
100 | ),
101 | ),
102 | );
103 | }
104 | }
--------------------------------------------------------------------------------
/lib/autocomplete/OverlayMain.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:flutter/material.dart';
3 |
4 | import 'CountriesField.dart';
5 |
6 |
7 | class OverlayMain extends StatefulWidget {
8 | @override
9 | _OverlayMainState createState() => _OverlayMainState();
10 | }
11 |
12 |
13 | class _OverlayMainState extends State {
14 |
15 | @override
16 | Widget build(BuildContext context) {
17 | return Scaffold(
18 | body: Padding(
19 | padding: const EdgeInsets.all(50.0),
20 | child: Form(
21 | child: ListView(
22 | children: [
23 |
24 | CountriesField(
25 | ),
26 |
27 | TextFormField(
28 | decoration: InputDecoration(
29 | labelText: 'Address',
30 | ),
31 |
32 | ),
33 |
34 | SizedBox(height: 16.0,),
35 | TextFormField(
36 | decoration: InputDecoration(
37 | labelText: 'City'
38 | ),
39 | ),
40 | SizedBox(height: 16.0,),
41 |
42 | SizedBox(height: 16.0,),
43 | RaisedButton(
44 | child: Text('SUBMIT'),
45 | onPressed: () {
46 | Toast.show(context: context, message: "信息已经提交!");
47 | },
48 | )
49 | ],
50 | ),
51 | ),
52 | ),
53 | );
54 |
55 |
56 | }
57 |
58 |
59 |
60 |
61 | }
62 |
63 |
64 | //通过 Overlay 实现 Toast
65 | class Toast {
66 | static void show({@required BuildContext context, @required String message}) {
67 |
68 | //1、创建 overlayEntry
69 | OverlayEntry overlayEntry = new OverlayEntry(builder: (context) {
70 | return new Positioned(
71 | top: MediaQuery.of(context).size.height * 0.8,
72 | child: new Material(
73 | child: new Container(
74 | width: MediaQuery.of(context).size.width,
75 | alignment: Alignment.center,
76 | child: new Center(
77 | child: new Card(
78 | child: new Padding(
79 | padding: EdgeInsets.all(8),
80 | child: new Text(message),
81 | ),
82 |
83 | color: Colors.grey.withOpacity(0.6),
84 | ),
85 | ),
86 | ),
87 | ));
88 | });
89 |
90 |
91 | //插入到 Overlay中显示 OverlayEntry
92 | Overlay.of(context).insert(overlayEntry);
93 |
94 |
95 | //延时两秒,移除 OverlayEntry
96 | new Future.delayed(Duration(seconds: 2)).then((value) {
97 | overlayEntry.remove();
98 | }
99 | );
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/lib/chartsDisplay/ChartDispalyMain.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_share/chartsDisplay/pie_chart.dart';
3 |
4 | import 'bar_chart.dart';
5 | import 'line_chart.dart';
6 |
7 | class ChartDispalyMain extends StatefulWidget {
8 | ChartDispalyMain({Key key,}) : super(key: key);
9 |
10 | @override
11 | _ChartDispalyMainState createState() =>_ChartDispalyMainState();
12 |
13 | }
14 |
15 | class _ChartDispalyMainState extends State {
16 |
17 |
18 | @override
19 | Widget build(BuildContext context) {
20 | Widget _buildCard(String assetUrl, String title, int index) {
21 | final double deviceHeight = MediaQuery.of(context).size.height;
22 | return SizedBox(
23 | width: deviceHeight * 0.45,
24 | child: ClipRRect(
25 | borderRadius: BorderRadius.circular(20.0),
26 | child: InkWell(
27 | onTap: () {
28 | if (index == 1) {
29 | Navigator.push(
30 | context,
31 | MaterialPageRoute(
32 | builder: (context) => BarChart()
33 | )
34 | );
35 | } else if (index == 2) {
36 | Navigator.push(
37 | context,
38 | MaterialPageRoute(
39 | builder: (context) => LineChart()
40 | )
41 | );
42 | } else if (index == 3) {
43 | Navigator.push(
44 | context,
45 | MaterialPageRoute(
46 | builder: (context) => PieChart()
47 | )
48 | );
49 | }
50 | },
51 | child: Stack(
52 | children: [
53 | Container(
54 | height: deviceHeight * 0.3,
55 | decoration: BoxDecoration(
56 | color: Colors.black,
57 | image: DecorationImage(
58 | fit: BoxFit.fill,
59 | colorFilter: new ColorFilter.mode(Colors.black.withOpacity(0.7), BlendMode.dstATop),
60 | image: AssetImage(assetUrl)
61 | )
62 | ),
63 | ),
64 | Container(
65 | margin: EdgeInsets.only(top: deviceHeight * 0.125),
66 | alignment: Alignment.center,
67 | child: Text(
68 | title,
69 | textAlign: TextAlign.center,
70 | style: TextStyle(
71 | color: Colors.white,
72 | fontWeight: FontWeight.w500,
73 | fontSize: 29
74 | ),
75 | ),
76 | )
77 | ],
78 | ),
79 | ),
80 | ),
81 | );
82 | }
83 |
84 |
85 | return Scaffold(
86 | appBar: AppBar(title: Text("图表绘制"), centerTitle: true,),
87 | body: Padding(
88 | padding: const EdgeInsets.all(15.0),
89 | child: ListView(
90 | children: [
91 | SizedBox(height: 25,),
92 | _buildCard('images/barchart.jpg', 'Bar-Chart Example', 1),
93 | SizedBox(height: 25,),
94 | _buildCard('images/linechart.png', 'Line-Chart Example', 2),
95 | SizedBox(height: 25,),
96 | _buildCard('images/piechart.jpg', 'Pie-Chart Example', 3)
97 | ],
98 | ),
99 | ),
100 | );
101 | }
102 |
103 | }
--------------------------------------------------------------------------------
/lib/chartsDisplay/bar_chart.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:flutter/material.dart';
3 | import 'package:charts_flutter/flutter.dart' as charts;
4 | import 'package:flutter_share/chartsDisplay/population_data.dart';
5 |
6 | class BarChart extends StatelessWidget {
7 |
8 | // Defining the data
9 | final List data = [
10 | PopulationData(
11 | year: 1880,
12 | population: 50189209,
13 | barColor: charts.ColorUtil.fromDartColor(Colors.lightBlue)
14 | ),
15 | PopulationData(
16 | year: 1890,
17 | population: 62979766,
18 | barColor: charts.ColorUtil.fromDartColor(Colors.lightBlue)
19 | ),
20 | PopulationData(
21 | year: 1900,
22 | population: 76212168,
23 | barColor: charts.ColorUtil.fromDartColor(Colors.lightBlue)
24 | ),
25 | PopulationData(
26 | year: 1910,
27 | population: 92228496,
28 | barColor: charts.ColorUtil.fromDartColor(Colors.lightBlue)
29 | ),
30 | PopulationData(
31 | year: 1920,
32 | population: 106021537,
33 | barColor: charts.ColorUtil.fromDartColor(Colors.blue)
34 | ),
35 | PopulationData(
36 | year: 1930,
37 | population: 123202624,
38 | barColor: charts.ColorUtil.fromDartColor(Colors.blue)
39 | ),
40 | PopulationData(
41 | year: 1940,
42 | population: 132164569,
43 | barColor: charts.ColorUtil.fromDartColor(Colors.blue)
44 | ),
45 | PopulationData(
46 | year: 1950,
47 | population: 151325798,
48 | barColor: charts.ColorUtil.fromDartColor(Colors.blue)
49 | ),
50 | PopulationData(
51 | year: 1960,
52 | population: 179323175,
53 | barColor: charts.ColorUtil.fromDartColor(Colors.blue)
54 | ),
55 | PopulationData(
56 | year: 1970,
57 | population: 203302031,
58 | barColor: charts.ColorUtil.fromDartColor(Colors.purple)
59 | ),
60 | PopulationData(
61 | year: 1980,
62 | population: 226542199,
63 | barColor: charts.ColorUtil.fromDartColor(Colors.purple)
64 | ),
65 | PopulationData(
66 | year: 1990,
67 | population: 248709873,
68 | barColor: charts.ColorUtil.fromDartColor(Colors.purple)
69 | ),
70 | PopulationData(
71 | year: 2000,
72 | population: 281421906,
73 | barColor: charts.ColorUtil.fromDartColor(Colors.purple)
74 | ),
75 | PopulationData(
76 | year: 2010,
77 | population: 307745538,
78 | barColor: charts.ColorUtil.fromDartColor(Colors.black)
79 | ),
80 | PopulationData(
81 | year: 2017,
82 | population: 323148586,
83 | barColor: charts.ColorUtil.fromDartColor(Colors.black)
84 | ),
85 |
86 | ];
87 |
88 | _getSeriesData() {
89 | List> series = [
90 | charts.Series(
91 | id: "Population",
92 | data: data,
93 | domainFn: (PopulationData series, _) => series.year.toString(),
94 | measureFn: (PopulationData series, _) => series.population,
95 | colorFn: (PopulationData series, _) => series.barColor
96 | )
97 | ];
98 | return series;
99 | }
100 |
101 | @override
102 | Widget build(BuildContext context) {
103 | return Scaffold(
104 | appBar: AppBar(title: Text('Bar Chart Example'), centerTitle: true,),
105 | body: Center(
106 | child: Container(
107 | height: 400,
108 | padding: EdgeInsets.all(20),
109 | child: Card(
110 | child: Padding(
111 | padding: const EdgeInsets.all(8.0),
112 | child: Column(
113 | children: [
114 | Text(
115 | "Population of U.S. over the years",
116 | style: TextStyle(
117 | fontWeight: FontWeight.bold
118 | ),
119 | ),
120 | SizedBox(height: 20,),
121 | Expanded(
122 | child: charts.BarChart(
123 | _getSeriesData(),
124 | animate: true,
125 | domainAxis: charts.OrdinalAxisSpec(
126 | renderSpec: charts.SmallTickRendererSpec(labelRotation: 60)
127 | ),
128 | ),
129 | )
130 | ],
131 | ),
132 | ),
133 | ),
134 | ),
135 | ),
136 | );
137 | }
138 | }
--------------------------------------------------------------------------------
/lib/chartsDisplay/grades_data.dart:
--------------------------------------------------------------------------------
1 |
2 | class GradesData {
3 | final String gradeSymbol;
4 | final int numberOfStudents;
5 |
6 | GradesData(this.gradeSymbol, this.numberOfStudents);
7 | }
--------------------------------------------------------------------------------
/lib/chartsDisplay/line_chart.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'sales_data.dart';
3 | import 'package:charts_flutter/flutter.dart' as charts;
4 |
5 | class LineChart extends StatelessWidget {
6 |
7 | // Defining the data
8 | final data = [
9 | new SalesData(0, 1500000),
10 | new SalesData(1, 1735000),
11 | new SalesData(2, 1678000),
12 | new SalesData(3, 1890000),
13 | new SalesData(4, 1907000),
14 | new SalesData(5, 2300000),
15 | new SalesData(6, 2360000),
16 | new SalesData(7, 1980000),
17 | new SalesData(8, 2654000),
18 | new SalesData(9, 2789070),
19 | new SalesData(10, 3020000),
20 | new SalesData(11, 3245900),
21 | new SalesData(12, 4098500),
22 | new SalesData(13, 4500000),
23 | new SalesData(14, 4456500),
24 | new SalesData(15, 3900500),
25 | new SalesData(16, 5123400),
26 | new SalesData(17, 5589000),
27 | new SalesData(18, 5940000),
28 | new SalesData(19, 6367000),
29 | ];
30 |
31 | _getSeriesData() {
32 | List> series = [
33 | charts.Series(
34 | id: "Sales",
35 | data: data,
36 | domainFn: (SalesData series, _) => series.year,
37 | measureFn: (SalesData series, _) => series.sales,
38 | colorFn: (SalesData series, _) => charts.MaterialPalette.blue.shadeDefault
39 | )
40 | ];
41 | return series;
42 | }
43 |
44 | @override
45 | Widget build(BuildContext context) {
46 | return Scaffold(
47 | appBar: AppBar(
48 | title: Text('Line Chart Example'),
49 | centerTitle: true,
50 | ),
51 | body: Center(
52 | child: Container(
53 | height: 550,
54 | padding: EdgeInsets.all(10),
55 | child: Card(
56 | child: Padding(
57 | padding: const EdgeInsets.all(8.0),
58 | child: Column(
59 | children: [
60 | Text(
61 | "Sales of a company over the years",
62 | style: TextStyle(
63 | fontWeight: FontWeight.bold
64 | ),
65 | ),
66 | SizedBox(
67 | height: 20,
68 | ),
69 | Expanded(
70 | child: new charts.LineChart(_getSeriesData(), animate: true,),
71 | )
72 | ],
73 | ),
74 | ),
75 | ),
76 | ),
77 | )
78 | );
79 | }
80 | }
81 |
82 |
--------------------------------------------------------------------------------
/lib/chartsDisplay/pie_chart.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:flutter/material.dart';
3 | import 'package:charts_flutter/flutter.dart' as charts;
4 |
5 | import 'grades_data.dart';
6 |
7 | class PieChart extends StatelessWidget {
8 |
9 |
10 | final data = [
11 | GradesData('A', 190),
12 | GradesData('B', 230),
13 | GradesData('C', 150),
14 | GradesData('D', 73),
15 | GradesData('E', 31),
16 | GradesData('Fail', 13),
17 | ];
18 |
19 | _getSeriesData() {
20 | List> series = [
21 | charts.Series(
22 | id: "Grades",
23 | data: data,
24 | labelAccessorFn: (GradesData row, _) => '${row.gradeSymbol}: ${row.numberOfStudents}',
25 | domainFn: (GradesData grades, _) => grades.gradeSymbol,
26 | measureFn: (GradesData grades, _) => grades.numberOfStudents
27 | )
28 | ];
29 | return series;
30 | }
31 |
32 | @override
33 | Widget build(BuildContext context) {
34 | return Scaffold(
35 | appBar: AppBar(title: Text("Pie Chart"), centerTitle: true,),
36 | body: Center(
37 | child: Container(
38 | height: 400,
39 | padding: EdgeInsets.all(10),
40 | child: Card(
41 | child: Padding(
42 | padding: const EdgeInsets.all(8.0),
43 | child: Column(
44 | children: [
45 | Text(
46 | "Grades of the students of school in the calendar year",
47 | textAlign: TextAlign.center,
48 | style: TextStyle(
49 | fontWeight: FontWeight.bold
50 | ),
51 | ),
52 | SizedBox(
53 | height: 20,
54 | ),
55 | Expanded(
56 | child: new charts.PieChart(
57 | _getSeriesData(),
58 | animate: true,
59 | defaultRenderer: new charts.ArcRendererConfig(
60 | arcWidth: 60,
61 | arcRendererDecorators: [new charts.ArcLabelDecorator()]
62 | ),
63 | ),
64 | )
65 | ],
66 | ),
67 | ),
68 | ),
69 | ),
70 | ),
71 | );
72 | }
73 | }
--------------------------------------------------------------------------------
/lib/chartsDisplay/population_data.dart:
--------------------------------------------------------------------------------
1 | import 'package:charts_flutter/flutter.dart' as charts;
2 | import 'package:flutter/material.dart';
3 |
4 |
5 | class PopulationData {
6 | int year;
7 | int population;
8 | charts.Color barColor;
9 | PopulationData({
10 | @required this.year,
11 | @required this.population,
12 | @required this.barColor
13 | });
14 | }
--------------------------------------------------------------------------------
/lib/chartsDisplay/sales_data.dart:
--------------------------------------------------------------------------------
1 |
2 | class SalesData {
3 | final int year;
4 | final int sales;
5 |
6 | SalesData(this.year, this.sales);
7 | }
--------------------------------------------------------------------------------
/lib/downloadDemo/DownDemoMain.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'dart:io';
3 | import 'dart:math';
4 |
5 | import 'package:dio/dio.dart';
6 | import 'package:file_utils/file_utils.dart';
7 | import 'package:flutter/material.dart';
8 | import 'package:path_provider/path_provider.dart';
9 | import 'package:simple_permissions/simple_permissions.dart';
10 |
11 |
12 | class DownDemoMain extends StatefulWidget {
13 | @override
14 | _DownDemoMainMainState createState() => _DownDemoMainMainState();
15 | }
16 |
17 |
18 | class _DownDemoMainMainState extends State with SingleTickerProviderStateMixin {
19 | AnimationController _controller;
20 |
21 | final fileURl = "http://music.163.com/song/media/outer/url?id=413829859.mp3";
22 | bool downloading = false;
23 | double progress ;
24 | var path = "No Data";
25 | var platformVersion = "Unknown";
26 | Permission permission1 = Permission.WriteExternalStorage;
27 | var _onPressed;
28 | static final Random random = Random();
29 | Directory externalDir;
30 |
31 |
32 | @override
33 | void initState() {
34 | super.initState();
35 |
36 |
37 | //动画时间 5 秒
38 | _controller = new AnimationController(vsync: this, duration: Duration(seconds: 5));
39 | _controller.addListener(() => setState(() => {}));
40 | onAnimationStart();
41 | }
42 |
43 | void onAnimationStart() {
44 | _controller.forward(from: 0.0);
45 | }
46 |
47 | @override
48 | void dispose() {
49 | super.dispose();
50 | _controller.dispose();
51 | }
52 |
53 |
54 |
55 | Future downloadFile() async {
56 | Dio dio = Dio();
57 | bool checkPermission1 =
58 | //1、权限检查
59 | await SimplePermissions.checkPermission(permission1);
60 | if (checkPermission1 == false) {
61 | await SimplePermissions.requestPermission(permission1);
62 | checkPermission1 = await SimplePermissions.checkPermission(permission1);
63 | }
64 |
65 | if (checkPermission1 == true) {
66 | String dirloc = "";
67 | if (Platform.isAndroid) {
68 | dirloc = "/sdcard/download/";
69 | } else {
70 | dirloc = (await getApplicationDocumentsDirectory()).path;
71 | }
72 |
73 | var randid = random.nextInt(10000);
74 |
75 | try {
76 |
77 | //2、创建文件
78 | FileUtils.mkdir([dirloc]);
79 |
80 | //3、使用 dio 下载文件
81 | await dio.download(fileURl, dirloc + randid.toString() + ".mp3",
82 | onReceiveProgress: (receivedBytes, totalBytes) {
83 | setState(() {
84 | downloading = true;
85 | //4、连接资源成功开始下载后更新状态
86 | progress = (receivedBytes / totalBytes) ;
87 | });
88 | });
89 |
90 | } catch (e) {
91 | print(e);
92 | }
93 |
94 |
95 | setState(() {
96 | downloading = false;
97 | progress = 0;
98 | path = dirloc + randid.toString() + ".mp3";
99 | });
100 |
101 |
102 | } else {
103 | setState(() {
104 | progress = 0;
105 | _onPressed = () {
106 | downloadFile();
107 | };
108 | });
109 | }
110 | }
111 |
112 |
113 |
114 |
115 | @override
116 | Widget build(BuildContext context) {
117 | final size =MediaQuery.of(context).size;
118 | final width =size.width;
119 | final height =size.height;
120 |
121 | return SingleChildScrollView(
122 | child: Column(
123 | children: [
124 |
125 | SizedBox(
126 | width: width,
127 | height: 100,
128 | ),
129 |
130 | //线性进度条进度动画
131 | Padding(
132 | padding: EdgeInsets.all(16),
133 | child: LinearProgressIndicator(
134 | backgroundColor: Colors.grey[200],
135 | valueColor: ColorTween(begin: Colors.grey, end: Colors.red)
136 | .animate(_controller),
137 | value: _controller.value,
138 | ),
139 | ),
140 |
141 |
142 |
143 | //线性进度条模糊动画
144 | Padding(
145 | padding: EdgeInsets.all(16),
146 | child: LinearProgressIndicator(
147 | backgroundColor: Colors.grey[200],
148 | valueColor: AlwaysStoppedAnimation(Colors.blue),
149 | ),
150 | ),
151 |
152 |
153 |
154 | Padding(
155 | padding: EdgeInsets.all(16),
156 | child:
157 | // 模糊进度条(会执行一个旋转动画)
158 | CircularProgressIndicator(
159 | backgroundColor: Colors.grey[200],
160 | valueColor: AlwaysStoppedAnimation(Colors.blue),
161 | ),
162 | ),
163 |
164 |
165 |
166 | //精准进度
167 | Padding(
168 | padding: EdgeInsets.all(10),
169 | child:
170 | SizedBox(
171 | width: 150,
172 | height: 150,
173 | child:
174 | CircularProgressIndicator(
175 | backgroundColor: Colors.grey[200],
176 | valueColor: ColorTween(begin: Colors.grey, end: Colors.red)
177 | .animate(_controller),
178 | value: _controller.value,
179 |
180 | ),
181 | ),
182 |
183 | ),
184 |
185 |
186 |
187 | Container(
188 | child: downloading
189 | ? Container(
190 | height: 200.0,
191 | width: 200.0,
192 | child:
193 | Padding(
194 | padding: EdgeInsets.all(10),
195 | child:
196 | SizedBox(
197 | width: 200,
198 | height: 200,
199 | child:
200 | CircularProgressIndicator(
201 | backgroundColor: Colors.grey[200],
202 | value: progress,
203 | ),
204 | ),
205 | ),
206 |
207 | )
208 | : Column(
209 | mainAxisAlignment: MainAxisAlignment.center,
210 | children: [
211 | Text("下载文件路径:" + path),
212 | MaterialButton(
213 | child: Text('开始下载文件'),
214 | onPressed: (){
215 | downloadFile();
216 | },
217 | disabledColor: Colors.blueGrey,
218 | color: Colors.pink,
219 | textColor: Colors.white,
220 | height: 40.0,
221 | minWidth: 100.0,
222 | ),
223 | ],
224 | )
225 | )
226 |
227 |
228 | ],
229 | ),
230 | );
231 |
232 |
233 | }
234 |
235 |
236 |
237 | }
--------------------------------------------------------------------------------
/lib/flutterSearch/searchbarview.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 |
4 | class SearchBarView extends StatefulWidget {
5 | @override
6 | _SearchBarViewState createState() => _SearchBarViewState();
7 | }
8 |
9 | class _SearchBarViewState extends State {
10 | @override
11 | Widget build(BuildContext context) {
12 | return Scaffold(
13 | appBar: AppBar(
14 | title: Text('搜索'),
15 | actions: [
16 | IconButton(
17 | icon: Icon(Icons.search),
18 | onPressed: (){
19 | showSearch(context: context, delegate: SearchBarViewDelegate());
20 | }
21 | )
22 | ],
23 | ),
24 | );
25 | }
26 | }
27 |
28 | class SearchBarViewDelegate extends SearchDelegate{
29 |
30 | String searchHint = "请输入搜索内容...";
31 | var sourceList = [
32 | "dart",
33 | "dart 入门",
34 | "flutter",
35 | "flutter 编程",
36 | "flutter 编程开发",
37 | ];
38 |
39 | var suggestList = [
40 | "flutter",
41 | "flutter 编程开发"
42 | ];
43 |
44 |
45 | @override
46 | String get searchFieldLabel => searchHint;
47 |
48 |
49 | @override
50 | List buildActions(BuildContext context) {
51 |
52 | ///显示在最右边的控件列表
53 | return [
54 |
55 | IconButton(
56 | icon: Icon(Icons.clear),
57 | onPressed: (){
58 | query = "";
59 |
60 | ///搜索建议的内容
61 | showSuggestions(context);
62 | },
63 | ),
64 | IconButton(
65 | icon: Icon(Icons.search),
66 | onPressed: ()=>query = "",
67 | )
68 | ];
69 | }
70 |
71 |
72 | ///左侧带动画的控件,一般都是返回
73 | @override
74 | Widget buildLeading(BuildContext context) {
75 | return IconButton(
76 | icon: AnimatedIcon(icon: AnimatedIcons.menu_arrow, progress: transitionAnimation
77 | ),
78 | ///调用 close 关闭 search 界面
79 | onPressed: ()=>close(context,null),
80 | );
81 | }
82 |
83 |
84 | ///展示搜索结果
85 | @override
86 | Widget buildResults(BuildContext context) {
87 |
88 | List result = List();
89 |
90 | ///模拟搜索过程
91 | for (var str in sourceList){
92 | ///query 就是输入框的 TextEditingController
93 | if (query.isNotEmpty && str.contains(query)){
94 | result.add(str);
95 | }
96 | }
97 |
98 | ///展示搜索结果
99 | return ListView.builder(
100 | itemCount: result.length,
101 | itemBuilder: (BuildContext context, int index)=>ListTile(
102 | title: Text(result[index]),
103 | ),
104 | );
105 | }
106 |
107 | @override
108 | Widget buildSuggestions(BuildContext context) {
109 |
110 | List suggest = query.isEmpty ? suggestList : sourceList.where((input)=>input.startsWith(query)).toList();
111 | return ListView.builder(
112 | itemCount: suggest.length,
113 | itemBuilder: (BuildContext context, int index)=>
114 | InkWell(
115 | child: ListTile(
116 | title: RichText(
117 | text: TextSpan(
118 | text: suggest[index].substring(0, query.length),
119 | style: TextStyle(color: Colors.blue,fontWeight: FontWeight.bold),
120 | children: [
121 | TextSpan(
122 | text: suggest[index].substring(query.length),
123 | style: TextStyle(color: Colors.grey),
124 | ),
125 | ],
126 | ),
127 | ),
128 | ),
129 | onTap: (){
130 | // query.replaceAll("", suggest[index].toString());
131 | searchHint = "";
132 | query = suggest[index].toString();
133 | showResults(context);
134 | },
135 | ),
136 |
137 |
138 | );
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/lib/heroAnimation/HeroAnimPage.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'HeroAnimationRouteB.dart';
4 |
5 | class Heroanimpage extends StatefulWidget {
6 | Heroanimpage({Key key}) : super(key: key);
7 |
8 | @override
9 | _HeroanimpageState createState() => _HeroanimpageState();
10 | }
11 |
12 | class _HeroanimpageState extends State {
13 | @override
14 | Widget build(BuildContext context) {
15 | return Container(
16 | alignment: Alignment.topCenter,
17 | child: InkWell(
18 | child: Hero(
19 | tag: "avatar", //唯一标记,前后两个路由页Hero的tag必须相同
20 | child:Container(
21 |
22 | margin: EdgeInsets.only(top: 50),
23 | child: ClipOval(
24 | child: Image.asset("images/avatar.jpg",
25 | width: 50.0,
26 | ),
27 | ),
28 | ),
29 | ),
30 | onTap: () {
31 | //打开B路由
32 | Navigator.push(context, PageRouteBuilder(
33 | pageBuilder: (BuildContext context, Animation animation,
34 | Animation secondaryAnimation) {
35 | return new FadeTransition(
36 | opacity: animation,
37 | child: Scaffold(
38 | appBar: AppBar(
39 | title: Text("原图"),
40 | ),
41 | body: HeroAnimationRouteB(),
42 | ),
43 | );
44 | })
45 | );
46 | },
47 | ),
48 | ); }
49 | }
--------------------------------------------------------------------------------
/lib/heroAnimation/HeroAnimationRouteB.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class HeroAnimationRouteB extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) {
6 | return Center(
7 | child: Hero(
8 | tag: "avatar", //唯一标记,前后两个路由页Hero的tag必须相同
9 | child: Image.asset("images/avatar.jpg"),
10 | ),
11 | );
12 | }
13 | }
--------------------------------------------------------------------------------
/lib/heroAnimation/Photo.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class Photo extends StatelessWidget {
4 | Photo({ Key key, this.photo, this.color, this.onTap }) : super(key: key);
5 |
6 | final String photo;
7 | final Color color;
8 | final VoidCallback onTap;
9 |
10 | Widget build(BuildContext context) {
11 | return new Material(
12 | // Slightly opaque color appears where the image has transparency.
13 | color: Theme.of(context).primaryColor.withOpacity(0.25),
14 | child: new InkWell(
15 | onTap: onTap,
16 | child: new Image.asset(
17 | photo,
18 | fit: BoxFit.contain,
19 | )
20 | ),
21 | );
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lib/heroAnimation/RadialExpansion.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'dart:math' as math;
3 | class RadialExpansion extends StatelessWidget {
4 | RadialExpansion({
5 | Key key,
6 | this.maxRadius,
7 | this.child,
8 | }) : clipRectSize = 2.0 * (maxRadius / math.sqrt2),
9 | super(key: key);
10 |
11 | final double maxRadius;
12 | final clipRectSize;
13 | final Widget child;
14 |
15 | @override
16 | Widget build(BuildContext context) {
17 | return new ClipOval(
18 | child: new Center(
19 | child: new SizedBox(
20 | width: clipRectSize,
21 | height: clipRectSize,
22 | child: new ClipRect(
23 | child: child, // Photo
24 | ),
25 | ),
26 | ),
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lib/heroAnimation/RadialExpansionDemo.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'Photo.dart';
4 | import 'RadialExpansion.dart';
5 |
6 | class RadialExpansionDemo extends StatelessWidget {
7 | static const double kMinRadius = 32.0;
8 | static const double kMaxRadius = 128.0;
9 | static const opacityCurve = const Interval(0.0, 0.75, curve: Curves.fastOutSlowIn);
10 |
11 | static RectTween _createRectTween(Rect begin, Rect end) {
12 | return MaterialRectCenterArcTween(begin: begin, end: end);
13 | }
14 |
15 | static Widget _buildPage(BuildContext context, String imageName, String description) {
16 | return Container(
17 | color: Theme.of(context).canvasColor,
18 | child: Center(
19 | child: Card(
20 | elevation: 8.0,
21 | child: Column(
22 | mainAxisSize: MainAxisSize.min,
23 | children: [
24 | SizedBox(
25 | width: kMaxRadius * 2.0,
26 | height: kMaxRadius * 2.0,
27 | child: Hero(
28 | createRectTween: _createRectTween,
29 | tag: imageName,
30 | child: RadialExpansion(
31 | maxRadius: kMaxRadius,
32 | child: Photo(
33 | photo: imageName,
34 | onTap: () {
35 | Navigator.of(context).pop();
36 | },
37 | ),
38 | ),
39 | ),
40 | ),
41 | Text(
42 | description,
43 | style: TextStyle(fontWeight: FontWeight.bold),
44 | textScaleFactor: 3.0,
45 | ),
46 | const SizedBox(height: 16.0),
47 | ],
48 | ),
49 | ),
50 | ),
51 | );
52 | }
53 |
54 | Widget _buildHero(BuildContext context, String imageName, String description) {
55 | return Container(
56 | width: kMinRadius * 2.0,
57 | height: kMinRadius * 2.0,
58 | child: Hero(
59 | createRectTween: _createRectTween,
60 | tag: imageName,
61 | child: RadialExpansion(
62 | maxRadius: kMaxRadius,
63 | child: Photo(
64 | photo: imageName,
65 | onTap: () {
66 | Navigator.of(context).push(
67 | PageRouteBuilder(
68 | pageBuilder: (BuildContext context, Animation animation, Animation secondaryAnimation) {
69 | return AnimatedBuilder(
70 | animation: animation,
71 | builder: (BuildContext context, Widget child) {
72 | return Opacity(
73 | opacity: opacityCurve.transform(animation.value),
74 | child: _buildPage(context, imageName, description),
75 | );
76 | }
77 | );
78 | },
79 | ),
80 | );
81 | },
82 | ),
83 | ),
84 | ),
85 | );
86 | }
87 |
88 | @override
89 | Widget build(BuildContext context) {
90 | var timeDilation = 5.0; // 1.0 is normal animation speed.
91 |
92 | return Scaffold(
93 | appBar: AppBar(
94 | title: const Text('Radial Transition Demo'),
95 | ),
96 | body: Container(
97 | padding: const EdgeInsets.all(32.0),
98 | alignment: FractionalOffset.bottomLeft,
99 | child: Row(
100 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
101 | children: [
102 | _buildHero(context, 'images/aone.jpg', 'Chair'),
103 | _buildHero(context, 'images/atwo.jpg', 'Binoculars'),
104 | _buildHero(context, 'images/athree.jpg', 'Beach ball'),
105 | ],
106 | ),
107 | ),
108 | );
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/lib/implicitAnimation/AnimatedContainerDemo.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import 'package:flutter/material.dart';
4 |
5 | const _duration = Duration(milliseconds: 400);
6 |
7 | double randomBorderRadius() {
8 | return Random().nextDouble() * 64;
9 | }
10 |
11 | double randomMargin() {
12 | return Random().nextDouble() * 64;
13 | }
14 |
15 | Color randomColor() {
16 | return Color(0xFFFFFFFF & Random().nextInt(0xFFFFFFFF));
17 | }
18 |
19 | class AnimatedContainerDemo extends StatefulWidget {
20 | _AnimatedContainerDemoState createState() => _AnimatedContainerDemoState();
21 | }
22 |
23 | class _AnimatedContainerDemoState extends State {
24 | Color color;
25 | double borderRadius;
26 | double margin;
27 |
28 | @override
29 | void initState() {
30 | super.initState();
31 | color = Colors.deepPurple;
32 | borderRadius = randomBorderRadius();
33 | margin = randomMargin();
34 | }
35 |
36 | void change() {
37 | setState(() {
38 | color = randomColor();
39 | borderRadius = randomBorderRadius();
40 | margin = randomMargin();
41 | });
42 | }
43 |
44 | @override
45 | Widget build(BuildContext context) {
46 | return Scaffold(
47 | body: Center(
48 | child: Column(
49 | mainAxisAlignment: MainAxisAlignment.center,
50 | children: [
51 | SizedBox(
52 | width: 128,
53 | height: 128,
54 | child: AnimatedContainer(
55 | margin: EdgeInsets.all(margin),
56 | decoration: BoxDecoration(
57 | color: color,
58 | borderRadius: BorderRadius.circular(borderRadius),
59 | ),
60 | duration: _duration,
61 | curve: Curves.easeInOutBack,
62 | ),
63 | ),
64 | MaterialButton(
65 | color: Theme.of(context).primaryColor,
66 | child: Text(
67 | 'change',
68 | style: TextStyle(color: Colors.white),
69 | ),
70 | onPressed: () => change(),
71 | ),
72 | ],
73 | ),
74 | ),
75 | );
76 | }
77 | }
78 |
79 |
--------------------------------------------------------------------------------
/lib/implicitAnimation/FadeInDemo.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | class FadeInDemo extends StatefulWidget {
5 | _FadeInDemoState createState() => _FadeInDemoState();
6 | }
7 |
8 | class _FadeInDemoState extends State {
9 | double opacity = 0.0;
10 | @override
11 | Widget build(BuildContext context) {
12 | return Column(
13 | crossAxisAlignment: CrossAxisAlignment.center,
14 | mainAxisAlignment: MainAxisAlignment.center,
15 | children: [
16 | Image.network(
17 | 'https://picsum.photos/250?image=9',
18 | ),
19 | MaterialButton(
20 | child: Text(
21 | 'Show Details',
22 | style: TextStyle(color: Colors.blueAccent),
23 | ),
24 | onPressed: () => setState(() {
25 | opacity = 1;
26 | }),
27 | ),
28 | AnimatedOpacity(
29 | duration: Duration(seconds: 3),
30 | opacity: opacity,
31 | child: Column(
32 | children: [
33 | Text('Type: Owl'),
34 | Text('Age: 39'),
35 | Text('Employment: None'),
36 | ],
37 | ),
38 | )
39 | ]);
40 | }
41 | }
42 |
43 |
--------------------------------------------------------------------------------
/lib/navigationrail/NavigationRailMain.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class NanigationRailMain extends StatefulWidget {
4 | @override
5 | NanigationRailMainState createState() => NanigationRailMainState();
6 | }
7 |
8 |
9 | class NanigationRailMainState extends State {
10 | int _selectedIndex = 0;
11 | final padding = 8.0;
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 |
16 | // return Scaffold(
17 | // body: Row(
18 | // children: [
19 | // // Here's the important stuff
20 | // NavigationRail(
21 | // selectedIndex: _selectedIndex,
22 | // onDestinationSelected: (int index) {
23 | // setState(() {
24 | // _selectedIndex = index;
25 | // });
26 | // },
27 | // labelType: NavigationRailLabelType.selected,
28 | // destinations: [
29 | // NavigationRailDestination(
30 | // icon: Icon(Icons.favorite_border),
31 | // selectedIcon: Icon(Icons.favorite),
32 | // label: Text('First'),
33 | // ),
34 | // NavigationRailDestination(
35 | // icon: Icon(Icons.bookmark_border),
36 | // selectedIcon: Icon(Icons.book),
37 | // label: Text('Second'),
38 | // ),
39 | // NavigationRailDestination(
40 | // icon: Icon(Icons.star_border),
41 | // selectedIcon: Icon(Icons.star),
42 | // label: Text('Third'),
43 | // ),
44 | // ],
45 | // ),
46 | // // And now it's not that interesting
47 | // Expanded(
48 | // child: Center(
49 | // child: Container(
50 | // color: Colors.blue,
51 | // child:
52 | // Center(child: Text("Page № ${_selectedIndex.toString()}")),
53 | // ),
54 | // ),
55 | // )
56 | // ],
57 | // ),
58 | // );
59 |
60 | return Scaffold(
61 | backgroundColor: Color(0xff28292E),
62 | body: SafeArea(
63 | child: Row(
64 | children: [
65 | NavigationRail(
66 | minWidth: 56.0,
67 | groupAlignment: 1.0,
68 | backgroundColor: Color(0xff2D3035),
69 | selectedIndex: _selectedIndex,
70 | onDestinationSelected: (int index) {
71 | setState(() {
72 | _selectedIndex = index;
73 | });
74 | },
75 | labelType: NavigationRailLabelType.all,
76 | leading: Column(
77 | children: [
78 | SizedBox(
79 | height: 8,
80 | ),
81 | Center(
82 | child: CircleAvatar(
83 | radius: 16,
84 | backgroundImage: NetworkImage(
85 | "https://t9.baidu.com/it/u=86853839,3576305254&fm=79&app=86&size=h300&n=0&g=4n&f=jpeg?sec=1591363041&t=58576d535d450f80e9248bd0ee84c8c0"),
86 | ),
87 | ),
88 | SizedBox(
89 | height: 108,
90 | ),
91 | RotatedBox(
92 | quarterTurns: -1,
93 | child: IconButton(
94 | icon: Icon(Icons.tune),
95 | color: Color(0xffFCCFA8),
96 | onPressed: () {},
97 | ),
98 | )
99 | ],
100 | ),
101 | selectedLabelTextStyle: TextStyle(
102 | color: Color(0xffFCCFA8),
103 | fontSize: 13,
104 | letterSpacing: 0.8,
105 | decoration: TextDecoration.underline,
106 | decorationThickness: 2.0,
107 | ),
108 | unselectedLabelTextStyle: TextStyle(
109 | fontSize: 13,
110 | letterSpacing: 0.8,
111 | ),
112 | destinations: [
113 | buildRotatedTextRailDestination("Popular", padding),
114 | buildRotatedTextRailDestination("Favourites", padding),
115 | buildRotatedTextRailDestination("Inspiration", padding),
116 | buildRotatedTextRailDestination("All", padding),
117 | ],
118 | ),
119 | // This is the main content.
120 | ContentSpace(_selectedIndex)
121 | ],
122 | ),
123 | ),
124 | );
125 | }
126 | }
127 |
128 | NavigationRailDestination buildRotatedTextRailDestination(
129 | String text, double padding) {
130 | return NavigationRailDestination(
131 | icon: SizedBox.shrink(),
132 | label: Padding(
133 | padding: EdgeInsets.symmetric(vertical: padding),
134 | child: RotatedBox(
135 | quarterTurns: -1,
136 | child: Text(text),
137 | ),
138 | ),
139 | );
140 | }
141 |
142 | class ContentSpace extends StatelessWidget {
143 | final int _selectedIndex;
144 |
145 | ContentSpace(this._selectedIndex);
146 |
147 | final List images = [
148 | "https://images.unsplash.com/photo-1524758631624-e2822e304c36?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80",
149 | "https://images.unsplash.com/photo-1493663284031-b7e3aefcae8e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80",
150 | "https://images.unsplash.com/photo-1538688525198-9b88f6f53126?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1267&q=80",
151 | "https://images.unsplash.com/photo-1513161455079-7dc1de15ef3e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80",
152 | "https://images.unsplash.com/photo-1544457070-4cd773b4d71e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=843&q=80",
153 | "https://images.unsplash.com/photo-1532323544230-7191fd51bc1b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80",
154 | "https://images.unsplash.com/photo-1549488344-cbb6c34cf08b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80",
155 | ];
156 |
157 | final List titles = [
158 | "Popular\nIdeas",
159 | "Favourites",
160 | "Inspiration\nIdeas",
161 | "All"
162 | ];
163 |
164 | @override
165 | Widget build(BuildContext context) {
166 | return Expanded(
167 | child: Padding(
168 | padding: const EdgeInsets.fromLTRB(24, 8, 0, 0),
169 | child: MediaQuery.removePadding(
170 | removeTop: true,
171 | context: context,
172 | child: ListView(
173 | children: [
174 | Row(
175 | mainAxisAlignment: MainAxisAlignment.end,
176 | children: [
177 | IconButton(
178 | icon: Icon(Icons.search),
179 | onPressed: () {},
180 | ),
181 | IconButton(
182 | icon: Icon(Icons.calendar_today),
183 | onPressed: () {},
184 | ),
185 | ],
186 | ),
187 | SizedBox(
188 | height: 24,
189 | ),
190 | Text(titles[_selectedIndex],
191 | style: TextStyle(
192 | color: Color(0xffFCCFA8),
193 | fontSize: 16,
194 | letterSpacing: 0.8,
195 | decoration: TextDecoration.underline,
196 | decorationThickness: 2.0,
197 | ),
198 |
199 | ),
200 | SizedBox(
201 | height: 24,
202 | ),
203 |
204 | for (var i in images) ImageCard(i),
205 |
206 | ],
207 | ),
208 | ),
209 | ),
210 | );
211 | }
212 | }
213 |
214 | class ImageCard extends StatelessWidget {
215 | final uri;
216 |
217 | @override
218 | Widget build(BuildContext context) {
219 | return Card(
220 | margin: const EdgeInsets.fromLTRB(0, 0, 24, 24),
221 | child: Image.network(uri),
222 | clipBehavior: Clip.antiAliasWithSaveLayer,
223 | elevation: 0.0,
224 | shape: RoundedRectangleBorder(
225 | borderRadius: BorderRadius.circular(16),
226 |
227 | ),
228 | );
229 | }
230 |
231 | const ImageCard(this.uri);
232 |
233 | }
--------------------------------------------------------------------------------
/lib/nestedScrollView/DemoOne.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class NestedScrollViewDemoOne extends StatefulWidget {
4 | NestedScrollViewDemoOne({Key key,}) : super(key: key);
5 |
6 | @override
7 | _DemoOnePageState createState() =>_DemoOnePageState();
8 |
9 | }
10 |
11 | class _DemoOnePageState extends State with SingleTickerProviderStateMixin{
12 |
13 | TabController _tabController;
14 | ScrollController _scrollviewController;
15 | @override
16 | void initState() {
17 | // TODO: implement initState
18 | super.initState();
19 | _tabController = TabController(length: 4, vsync: this);
20 | _scrollviewController = ScrollController(initialScrollOffset: 0.0);
21 | }
22 |
23 | @override
24 | void dispose() {
25 | // TODO: implement dispose
26 | super.dispose();
27 | _tabController.dispose();
28 | _scrollviewController.dispose();
29 | }
30 |
31 |
32 |
33 | @override
34 | Widget build(BuildContext context) {
35 | return Scaffold(
36 | body: NestedScrollView(
37 | controller: _scrollviewController,
38 | headerSliverBuilder: (context, boxIsScrolled) {
39 |
40 | return [
41 | SliverAppBar(
42 | pinned: true,
43 | floating: true,
44 | elevation: 0.5,
45 | forceElevated: true,
46 | //backgroundColor: Colors.grey,
47 | expandedHeight: 240,
48 | flexibleSpace: FlexibleSpaceBar(
49 | collapseMode: CollapseMode.pin, //视差效果
50 | background: Container(
51 | //color: Colors.grey,
52 | child: Column(
53 | children: [
54 | Container(
55 | height: 210.0,
56 | width: 420,
57 | color: Colors.blue,
58 | child: Image.asset(
59 | "images/bg.jpg",
60 | fit: BoxFit.fitWidth,
61 | ),
62 | )
63 | ],
64 | ),
65 | ),
66 | ),
67 | bottom: TabBar(controller: _tabController, tabs: [
68 | Tab(
69 | text: "首页",
70 | ),
71 | Tab(
72 | text: "消息",
73 | ),
74 | Tab(
75 | text: "购物",
76 | ),
77 | Tab(
78 | text: "我的",
79 | )
80 | ]),
81 | ),
82 |
83 |
84 |
85 | ];
86 |
87 | },
88 |
89 | body: TabBarView(
90 | controller: _tabController,
91 | children: [
92 | Center(
93 | child: Text("one"),
94 | ),
95 |
96 | Center(
97 | child: Text("two"),
98 | ),
99 |
100 | Center(
101 | child: Text("three"),
102 | ),
103 |
104 | Center(
105 | child: Text("four"),
106 | ),
107 |
108 | ]
109 |
110 | )
111 | ),
112 | );
113 |
114 | }
115 |
116 | }
--------------------------------------------------------------------------------
/lib/nestedScrollView/DemoTwo.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class NestedScrollViewDemoTwo extends StatefulWidget {
4 | NestedScrollViewDemoTwo({Key key,}) : super(key: key);
5 |
6 | @override
7 | _DemoTwoPageState createState() =>_DemoTwoPageState();
8 |
9 | }
10 |
11 | class _DemoTwoPageState extends State {
12 |
13 |
14 | @override
15 | void initState() {
16 |
17 | }
18 |
19 | @override
20 | void dispose() {
21 | super.dispose();
22 | }
23 |
24 | @override
25 | Widget build(BuildContext context) {
26 |
27 |
28 |
29 | return Scaffold(
30 | body: NestedScrollView(
31 | headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
32 | return [
33 |
34 |
35 | /* SliverAppBar(
36 | title: Text("标题"),
37 | floating: false,
38 | snap: false,
39 | pinned: true,
40 | )
41 | */
42 |
43 |
44 | SliverAppBar(
45 | expandedHeight: 200.0,
46 | floating: true,
47 | snap: false,
48 | pinned: true,
49 | flexibleSpace: FlexibleSpaceBar(
50 | centerTitle: true,
51 | title: Text("标题",
52 | style: TextStyle(
53 | color: Colors.redAccent,
54 | fontSize: 16.0,
55 | )),
56 | background: Image.asset(
57 | "images/bg.jpg",
58 | fit: BoxFit.fill,
59 | )
60 | ),
61 | )
62 |
63 |
64 | ];
65 | },
66 | body: ListView.builder(
67 | itemBuilder: (BuildContext context, int index) {
68 | return ListTile(title:Text( "标题$index"),);
69 | },
70 | itemCount: 50,
71 | ),
72 | ),
73 |
74 | );
75 |
76 | }
77 |
78 | }
--------------------------------------------------------------------------------
/lib/path/CircleProgressBarPainter.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'dart:math' as Math;
3 |
4 | class CircleProgressBarPainter extends CustomPainter {
5 | //背景
6 | Paint _paintBackground;
7 |
8 | //前景
9 | Paint _paintForeground;
10 |
11 | var currentValue;
12 |
13 | CircleProgressBarPainter(this.currentValue) {
14 |
15 | _paintBackground = Paint()
16 | ..color = Colors.blue
17 | ..strokeCap = StrokeCap.round
18 | ..style = PaintingStyle.stroke
19 | ..strokeWidth = 10.0
20 | ..isAntiAlias = true;
21 |
22 | _paintForeground = Paint()
23 | ..color = Colors.red
24 | ..strokeCap = StrokeCap.round
25 | ..style = PaintingStyle.stroke
26 | ..strokeWidth = 10.0
27 | ..isAntiAlias = true;
28 |
29 | }
30 | @override
31 | void paint(Canvas canvas, Size size) {
32 |
33 | //画背景
34 | canvas.drawCircle(Offset(size.width / 2, size.height / 2), size.width / 2,
35 | _paintBackground);
36 |
37 |
38 | Rect rect = Rect.fromCircle(
39 | center: Offset(size.width / 2, size.height / 2),
40 | radius: size.width / 2,
41 | );
42 |
43 | //画弧形进度
44 | canvas.drawArc(rect, 0.0, currentValue * Math.pi / 180, false, _paintForeground);
45 | }
46 |
47 |
48 |
49 | @override
50 | bool shouldRepaint(CustomPainter oldDelegate) {
51 | return false;
52 | }
53 | }
--------------------------------------------------------------------------------
/lib/path/Circles.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math' as math;
2 | import 'dart:ui';
3 |
4 | import 'package:flutter/material.dart';
5 |
6 | class Circles extends StatefulWidget {
7 | @override
8 | _CirclesState createState() => _CirclesState();
9 | }
10 |
11 | class _CirclesState extends State with SingleTickerProviderStateMixin {
12 | AnimationController _controller;
13 | double circles = 5.0;
14 | bool showDots = false, showPath = true;
15 |
16 | @override
17 | void initState() {
18 | super.initState();
19 | _controller = AnimationController(
20 | vsync: this,
21 | duration: Duration(seconds: 3),
22 | );
23 | _controller.value = 1.0;
24 | }
25 |
26 | @override
27 | Widget build(BuildContext context) {
28 | return Scaffold(
29 | appBar: AppBar(
30 | title: Text('Circles'),
31 | ),
32 | body: SafeArea(
33 | child: Column(
34 | crossAxisAlignment: CrossAxisAlignment.start,
35 | mainAxisSize: MainAxisSize.max,
36 | children: [
37 | Expanded(
38 | child: AnimatedBuilder(
39 | animation: _controller,
40 | builder: (context, snapshot) {
41 | return Center(
42 | child: CustomPaint(
43 | painter: CirclesPainter(
44 | circles: circles,
45 | progress: _controller.value,
46 | showDots: showDots,
47 | showPath: showPath,
48 | ),
49 | ),
50 | );
51 | }),
52 | ),
53 | Row(
54 | children: [
55 | Padding(
56 | padding: const EdgeInsets.only(left: 24.0, right: 0.0),
57 | child: Text('Show Dots'),
58 | ),
59 | Switch(
60 | value: showDots,
61 | onChanged: (value) {
62 | setState(() {
63 | showDots = value;
64 | });
65 | },
66 | ),
67 | Padding(
68 | padding: const EdgeInsets.only(left: 24.0, right: 0.0),
69 | child: Text('Show Path'),
70 | ),
71 | Switch(
72 | value: showPath,
73 | onChanged: (value) {
74 | setState(() {
75 | showPath = value;
76 | });
77 | },
78 | ),
79 | ],
80 | ),
81 | Padding(
82 | padding: const EdgeInsets.only(left: 24.0),
83 | child: Text('Circles'),
84 | ),
85 | Slider(
86 | value: circles,
87 | min: 1.0,
88 | max: 10.0,
89 | divisions: 9,
90 | label: circles.toInt().toString(),
91 | onChanged: (value) {
92 | setState(() {
93 | circles = value;
94 | });
95 | },
96 | ),
97 | Padding(
98 | padding: const EdgeInsets.only(left: 24.0),
99 | child: Text('Progress'),
100 | ),
101 | Slider(
102 | value: _controller.value,
103 | min: 0.0,
104 | max: 1.0,
105 | onChanged: (value) {
106 | setState(() {
107 | _controller.value = value;
108 | });
109 | },
110 | ),
111 | Center(
112 | child: RaisedButton(
113 | child: Text('Animate'),
114 | onPressed: () {
115 | _controller.reset();
116 | _controller.forward();
117 | },
118 | ),
119 | ),
120 | ],
121 | ),
122 | ),
123 | );
124 | }
125 | }
126 |
127 | class CirclesPainter extends CustomPainter {
128 | CirclesPainter({this.circles, this.progress, this.showDots, this.showPath});
129 |
130 | final double circles, progress;
131 | bool showDots, showPath;
132 |
133 | var myPaint = Paint()
134 | ..color = Colors.purple
135 | ..style = PaintingStyle.stroke
136 | ..strokeWidth = 5.0;
137 |
138 | double radius = 80;
139 |
140 | @override
141 | void paint(Canvas canvas, Size size) {
142 | var path = createPath();
143 | PathMetrics pathMetrics = path.computeMetrics();
144 | for (PathMetric pathMetric in pathMetrics) {
145 | Path extractPath = pathMetric.extractPath(
146 | 0.0,
147 | pathMetric.length * progress,
148 | );
149 | if (showPath) {
150 | canvas.drawPath(extractPath, myPaint);
151 | }
152 | if (showDots) {
153 | try {
154 | var metric = extractPath.computeMetrics().first;
155 | final offset = metric.getTangentForOffset(metric.length).position;
156 | canvas.drawCircle(offset, 8.0, Paint());
157 | } catch (e) {}
158 | }
159 | }
160 | }
161 |
162 | Path createPath() {
163 | var path = Path();
164 | int n = circles.toInt();
165 | var range = List.generate(n, (i) => i + 1);
166 | double angle = 2 * math.pi / n;
167 | for (int i in range) {
168 | double x = radius * math.cos(i * angle);
169 | double y = radius * math.sin(i * angle);
170 | path.addOval(Rect.fromCircle(center: Offset(x, y), radius: radius));
171 | }
172 | return path;
173 | }
174 |
175 | @override
176 | bool shouldRepaint(CirclesPainter oldDelegate) {
177 | return true;
178 | }
179 | }
--------------------------------------------------------------------------------
/lib/path/DashLinePainter.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:flutter/material.dart';
4 |
5 | class DashLinePainter extends CustomPainter {
6 | final double progress;
7 |
8 | DashLinePainter({this.progress});
9 |
10 | Paint _paint = Paint()
11 | ..color = Colors.black
12 | ..strokeWidth = 4.0
13 | ..style = PaintingStyle.stroke
14 | ..strokeJoin = StrokeJoin.round;
15 |
16 | @override
17 | void paint(Canvas canvas, Size size) {
18 | var path = Path()
19 | ..moveTo(0, size.height / 2)
20 | ..lineTo(size.width * progress, size.height / 2);
21 |
22 | Path dashPath = Path();
23 |
24 | double dashWidth = 10.0;
25 | double dashSpace = 5.0;
26 | double distance = 0.0;
27 |
28 | for (PathMetric pathMetric in path.computeMetrics()) {
29 | while (distance < pathMetric.length) {
30 | dashPath.addPath(
31 | pathMetric.extractPath(distance, distance + dashWidth),
32 | Offset.zero,
33 | );
34 | distance += dashWidth;
35 | distance += dashSpace;
36 | }
37 | }
38 | canvas.drawPath(dashPath, _paint);
39 | }
40 |
41 | @override
42 | bool shouldRepaint(DashLinePainter oldDelegate) {
43 | return oldDelegate.progress != progress;
44 | }
45 | }
--------------------------------------------------------------------------------
/lib/path/LinePainter.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class LinePainter extends CustomPainter {
4 | final double progress;
5 |
6 | LinePainter({this.progress});
7 |
8 | Paint _paint = Paint()
9 | ..color = Colors.black
10 | ..strokeWidth = 4.0
11 | ..style = PaintingStyle.stroke
12 | ..strokeJoin = StrokeJoin.round;
13 |
14 | @override
15 | void paint(Canvas canvas, Size size) {
16 | var path = Path();
17 | path.moveTo(0, size.height / 2);
18 | path.lineTo(size.width * progress, size.height / 2);
19 | canvas.drawPath(path, _paint);
20 | }
21 |
22 | @override
23 | bool shouldRepaint(LinePainter oldDelegate) {
24 | return oldDelegate.progress != progress;
25 | }
26 | }
--------------------------------------------------------------------------------
/lib/path/PathAdvancedMain.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_share/path/Circles.dart';
3 | import 'package:flutter_share/path/DashLinePainter.dart';
4 | import 'package:flutter_share/path/LinePainter.dart';
5 |
6 | import 'Planets.dart';
7 | import 'Polygon.dart';
8 | import 'Spiral.dart';
9 |
10 | class PathAdvancedMain extends StatefulWidget {
11 | @override
12 | _PathAdvancedMainState createState() => _PathAdvancedMainState();
13 | }
14 |
15 | class _PathAdvancedMainState extends State {
16 |
17 |
18 | @override
19 | void initState() {
20 | super.initState();
21 |
22 | }
23 |
24 |
25 | @override
26 | Widget build(BuildContext context) {
27 | final size =MediaQuery.of(context).size;
28 | final width =size.width;
29 | final height =size.height;
30 |
31 |
32 |
33 | return ListView(
34 | children: [
35 |
36 | SizedBox(width: width,height: 20,),
37 | //
38 | // Container(
39 | // width: width,
40 | // height: 50,
41 | // alignment: Alignment.center,
42 | // child: Text("直线(百分之50比例)"),
43 | // ),
44 | //
45 | // CustomPaint(
46 | // painter:LinePainter(progress: 0.5),
47 | // ) ,
48 | //
49 | //
50 | //
51 | // Container(
52 | // width: width,
53 | // height: 50,
54 | // alignment: Alignment.center,
55 | // child: Text("虚线"),
56 | // ),
57 | //
58 | // CustomPaint(
59 | // painter:DashLinePainter(progress: 0.9),
60 | // )
61 | //
62 |
63 |
64 |
65 | FlatButton(
66 | color: Colors.blue,
67 | highlightColor: Colors.blue[700],
68 | colorBrightness: Brightness.dark,
69 | splashColor: Colors.grey,
70 | child: Text("画圆"),
71 | shape:RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
72 | onPressed: () {
73 | Navigator.push( context,
74 | new MaterialPageRoute(builder: (context) {
75 | return new Scaffold(body: Circles(),);
76 | //return new NestedScrollViewDemoTwo();
77 | }));
78 | },
79 | ),
80 |
81 |
82 |
83 |
84 |
85 | FlatButton(
86 | color: Colors.blue,
87 | highlightColor: Colors.blue[700],
88 | colorBrightness: Brightness.dark,
89 | splashColor: Colors.grey,
90 | child: Text("绘制多边形"),
91 | shape:RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
92 | onPressed: () {
93 | Navigator.push( context,
94 | new MaterialPageRoute(builder: (context) {
95 | return new Scaffold(body: Polygon(),);
96 | //return new NestedScrollViewDemoTwo();
97 | }));
98 | },
99 | ),
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 | FlatButton(
109 | color: Colors.blue,
110 | highlightColor: Colors.blue[700],
111 | colorBrightness: Brightness.dark,
112 | splashColor: Colors.grey,
113 | child: Text("螺旋曲线"),
114 | shape:RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
115 | onPressed: () {
116 | Navigator.push( context,
117 | new MaterialPageRoute(builder: (context) {
118 | return new Scaffold(body: Spiral(),);
119 | //return new NestedScrollViewDemoTwo();
120 | }));
121 | },
122 | ),
123 |
124 |
125 |
126 |
127 |
128 | FlatButton(
129 | color: Colors.blue,
130 | highlightColor: Colors.blue[700],
131 | colorBrightness: Brightness.dark,
132 | splashColor: Colors.grey,
133 | child: Text("星空动画"),
134 | shape:RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
135 | onPressed: () {
136 | Navigator.push( context,
137 | new MaterialPageRoute(builder: (context) {
138 | return new Scaffold(body: Planets(),);
139 | //return new NestedScrollViewDemoTwo();
140 | }));
141 | },
142 | ),
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 | ],
157 | );
158 |
159 |
160 | }
161 |
162 |
163 | }
--------------------------------------------------------------------------------
/lib/path/PathBasicsMain.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'CircleProgressBarPainter.dart';
4 | import 'PathPainter.dart';
5 |
6 |
7 |
8 | class PathBasicsMain extends StatefulWidget {
9 | @override
10 | _PathBasicsMainMainState createState() => _PathBasicsMainMainState();
11 | }
12 |
13 | class _PathBasicsMainMainState extends State with SingleTickerProviderStateMixin {
14 |
15 | Animation progressAnimation;
16 | AnimationController _controller;
17 |
18 |
19 | @override
20 | void initState() {
21 | super.initState();
22 |
23 | _controller = AnimationController(vsync: this, duration: Duration(seconds: 2));
24 |
25 | progressAnimation = Tween(begin: 0.0, end: 360.0).animate(_controller);
26 |
27 | _controller.addListener(() {
28 | this.setState(() {});
29 | });
30 |
31 |
32 |
33 |
34 | onAnimationStart();
35 | }
36 |
37 | void onAnimationStart() {
38 | _controller.forward(from: 0.0);
39 | }
40 |
41 | @override
42 | void dispose() {
43 | super.dispose();
44 | _controller.dispose();
45 | }
46 |
47 |
48 | @override
49 | Widget build(BuildContext context) {
50 | final size =MediaQuery.of(context).size;
51 | final width =size.width;
52 | final height =size.height;
53 |
54 |
55 | return Container(
56 | width: width,
57 | height: height,
58 | padding: EdgeInsets.all(20),
59 | child: CustomPaint(
60 |
61 | child: Center(
62 | child: Text(
63 | (progressAnimation.value / 3.6).round().toString(),
64 | style: TextStyle(fontSize: 24,color: Colors.blue),
65 | ),
66 | ),
67 |
68 | painter: CircleProgressBarPainter(progressAnimation.value)
69 |
70 | ),
71 |
72 | );
73 |
74 | }
75 |
76 |
77 | }
--------------------------------------------------------------------------------
/lib/path/PathPainter.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:flutter/material.dart';
3 | import 'dart:math' as Math;
4 |
5 | class PathPainter extends CustomPainter {
6 | @override
7 | void paint(Canvas canvas, Size size) {
8 |
9 | Paint paint = Paint()
10 | ..color = Colors.red
11 | ..style = PaintingStyle.stroke
12 | ..strokeWidth = 8.0;
13 |
14 | Path path = Path();
15 | // 从左上角起点到右下角终点
16 | path.relativeMoveTo(size.width/4,size.height/4);
17 | path.relativeLineTo(size.width, size.height);
18 | canvas.drawPath(path, paint);
19 |
20 |
21 |
22 |
23 | }
24 |
25 | @override
26 | bool shouldRepaint(CustomPainter oldDelegate) => true;
27 | }
--------------------------------------------------------------------------------
/lib/path/Planets.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/material.dart';
5 |
6 | class Planets extends StatefulWidget {
7 | @override
8 | _PlanetsState createState() => _PlanetsState();
9 | }
10 |
11 | class _PlanetsState extends State with TickerProviderStateMixin {
12 | AnimationController _controller;
13 | AnimationController _controller1;
14 | AnimationController _controller2;
15 |
16 | @override
17 | void initState() {
18 | super.initState();
19 | _controller = AnimationController(
20 | vsync: this,
21 | duration: Duration(seconds: 3),
22 | );
23 | _controller1 = AnimationController(
24 | vsync: this,
25 | duration: Duration(seconds: 4),
26 | );
27 | _controller2 = AnimationController(
28 | vsync: this,
29 | duration: Duration(seconds: 5),
30 | );
31 | }
32 |
33 | @override
34 | Widget build(BuildContext context) {
35 | return Scaffold(
36 | backgroundColor: const Color(0xFF6C63FF),
37 | appBar: AppBar(
38 | title: Text('Planets'),
39 | backgroundColor: Colors.transparent,
40 | elevation: 0.0,
41 | ),
42 | body: AnimatedBuilder(
43 | animation: _controller,
44 | builder: (context, snapshot) {
45 | return Center(
46 | child: CustomPaint(
47 | painter: AtomPaint(
48 | value: _controller.value,
49 | value1: _controller1.value,
50 | value2: _controller2.value,
51 | ),
52 | ),
53 | );
54 | }),
55 | floatingActionButton: FloatingActionButton(
56 | child: Icon(Icons.play_arrow),
57 | onPressed: () {
58 | _controller.reset();
59 | _controller1.reset();
60 | _controller2.reset();
61 | _controller.repeat();
62 | _controller1.repeat();
63 | _controller2.repeat();
64 | },
65 | ),
66 | );
67 | }
68 | }
69 |
70 | class AtomPaint extends CustomPainter {
71 | AtomPaint({
72 | this.value,
73 | this.value1,
74 | this.value2,
75 | });
76 |
77 | final double value, value1, value2;
78 |
79 | Paint _axisPaint = Paint()
80 | ..color = const Color(0xFFE6E6E6)
81 | ..strokeWidth = 2.0
82 | ..style = PaintingStyle.stroke;
83 |
84 | @override
85 | void paint(Canvas canvas, Size size) {
86 | canvas.drawCircle(Offset(0, 0), 20.0, Paint()..color = Colors.yellow);
87 | drawAxis(value, canvas, 60, Paint()..color = Colors.grey);
88 | drawAxis(value1, canvas, 100, Paint()..color = Colors.brown);
89 | drawAxis(value2, canvas, 140, Paint()..color = Colors.blueAccent);
90 | drawAxis(value, canvas, 180, Paint()..color = Colors.redAccent);
91 | drawAxis(value1, canvas, 220, Paint()..color = Colors.lightGreen);
92 | drawAxis(value2, canvas, 260, Paint()..color = Colors.purpleAccent);
93 | }
94 |
95 | drawAxis(double value, Canvas canvas, double radius, Paint paint) {
96 | var firstAxis = getCirclePath(radius);
97 | canvas.drawPath(firstAxis, _axisPaint);
98 | PathMetrics pathMetrics = firstAxis.computeMetrics();
99 | for (PathMetric pathMetric in pathMetrics) {
100 | Path extractPath = pathMetric.extractPath(
101 | 0.0,
102 | pathMetric.length * value,
103 | );
104 | try {
105 | var metric = extractPath.computeMetrics().first;
106 | final offset = metric.getTangentForOffset(metric.length).position;
107 | canvas.drawCircle(offset, 12.0, paint);
108 | } catch (e) {}
109 | }
110 | }
111 |
112 | Path getCirclePath(double radius) =>
113 | Path()..addOval(Rect.fromCircle(center: Offset(0, 0), radius: radius));
114 |
115 | @override
116 | bool shouldRepaint(CustomPainter oldDelegate) {
117 | return true;
118 | }
119 | }
--------------------------------------------------------------------------------
/lib/path/Polygon.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'dart:ui';
3 |
4 | import 'package:flutter/material.dart';
5 | import 'dart:math' as math;
6 |
7 |
8 | class Polygon extends StatefulWidget {
9 | @override
10 | _PolygonState createState() => _PolygonState();
11 | }
12 |
13 | class _PolygonState extends State with SingleTickerProviderStateMixin {
14 | double sides = 3.0;
15 | bool showDots = false, showPath = true;
16 | AnimationController _controller;
17 |
18 | @override
19 | void initState() {
20 | super.initState();
21 | _controller = AnimationController(
22 | vsync: this,
23 | duration: Duration(seconds: 3),
24 | );
25 | _controller.value = 1.0;
26 | }
27 |
28 | @override
29 | Widget build(BuildContext context) {
30 |
31 | return Scaffold(
32 | appBar: AppBar(
33 | title: Text('Polygon'),
34 | ),
35 | body: SafeArea(
36 | child: Column(
37 | crossAxisAlignment: CrossAxisAlignment.start,
38 | mainAxisSize: MainAxisSize.max,
39 | children: [
40 | Expanded(
41 | child: AnimatedBuilder(
42 | animation: _controller,
43 | builder: (context, snapshot) {
44 | return Center(
45 | child: CustomPaint(
46 | painter: PolygonPainter(
47 | sides: sides,
48 | progress: _controller.value,
49 | showDots: showDots,
50 | showPath: showPath,
51 | ),
52 | ),
53 | );
54 | }),
55 | ),
56 | Row(
57 | children: [
58 | Padding(
59 | padding: const EdgeInsets.only(left: 24.0, right: 0.0),
60 | child: Text('Show Dots'),
61 | ),
62 | Switch(
63 | value: showDots,
64 | onChanged: (value) {
65 | setState(() {
66 | showDots = value;
67 | });
68 | },
69 | ),
70 | Padding(
71 | padding: const EdgeInsets.only(left: 24.0, right: 0.0),
72 | child: Text('Show Path'),
73 | ),
74 | Switch(
75 | value: showPath,
76 | onChanged: (value) {
77 | setState(() {
78 | showPath = value;
79 | });
80 | },
81 | ),
82 | ],
83 | ),
84 | Padding(
85 | padding: const EdgeInsets.only(left: 24.0),
86 | child: Text('Sides'),
87 | ),
88 | Slider(
89 | value: sides,
90 | min: 3.0,
91 | max: 10.0,
92 | label: sides.toInt().toString(),
93 | divisions: 7,
94 | onChanged: (value) {
95 | setState(() {
96 | sides = value;
97 | });
98 | },
99 | ),
100 | Padding(
101 | padding: const EdgeInsets.only(left: 24.0),
102 | child: Text('Progress'),
103 | ),
104 | Slider(
105 | value: _controller.value,
106 | min: 0.0,
107 | max: 1.0,
108 | onChanged: (value) {
109 | setState(() {
110 | _controller.value = value;
111 | });
112 | },
113 | ),
114 | Center(
115 | child: RaisedButton(
116 | child: Text('Animate'),
117 | onPressed: () {
118 | _controller.reset();
119 | _controller.forward();
120 | },
121 | ),
122 | ),
123 | ],
124 | ),
125 | ),
126 | );
127 | }
128 | }
129 |
130 | class PolygonPainter extends CustomPainter {
131 | PolygonPainter({
132 | this.sides,
133 | this.progress,
134 | this.showPath,
135 | this.showDots,
136 | });
137 |
138 | final double sides;
139 | final double progress;
140 | bool showDots, showPath;
141 |
142 | final Paint _paint = Paint()
143 | ..color = Colors.purple
144 | ..strokeWidth = 4.0
145 | ..style = PaintingStyle.stroke
146 | ..strokeCap = StrokeCap.round;
147 |
148 | @override
149 | void paint(Canvas canvas, Size size) {
150 | var path = createPath(sides.toInt(), 100);
151 | PathMetric pathMetric = path.computeMetrics().first;
152 | Path extractPath =
153 | pathMetric.extractPath(0.0, pathMetric.length * progress);
154 | if (showPath) {
155 | canvas.drawPath(extractPath, _paint);
156 | }
157 | if (showDots) {
158 | try {
159 | var metric = extractPath.computeMetrics().first;
160 | final offset = metric.getTangentForOffset(metric.length).position;
161 | canvas.drawCircle(offset, 8.0, Paint());
162 | } catch (e) {}
163 | }
164 | }
165 |
166 | @override
167 | bool shouldRepaint(CustomPainter oldDelegate) {
168 | return true;
169 | }
170 |
171 | Path createPath(int sides, double radius) {
172 | var path = Path();
173 | var angle = (math.pi * 2) / sides;
174 | path.moveTo(radius * math.cos(0.0), radius * math.sin(0.0));
175 | for (int i = 1; i <= sides; i++) {
176 | double x = radius * math.cos(angle * i);
177 | double y = radius * math.sin(angle * i);
178 | path.lineTo(x, y);
179 | }
180 | path.close();
181 | return path;
182 | }
183 | }
--------------------------------------------------------------------------------
/lib/path/Spiral.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math' as math;
2 | import 'dart:ui';
3 |
4 | import 'package:flutter/material.dart';
5 |
6 | class Spiral extends StatefulWidget {
7 | @override
8 | _SpiralState createState() => _SpiralState();
9 | }
10 |
11 | class _SpiralState extends State with SingleTickerProviderStateMixin {
12 | bool showDots = false, showPath = true;
13 | AnimationController _controller;
14 |
15 | @override
16 | void initState() {
17 | super.initState();
18 | _controller = AnimationController(
19 | vsync: this,
20 | duration: Duration(seconds: 5),
21 | );
22 | _controller.value = 1.0;
23 | }
24 |
25 | @override
26 | Widget build(BuildContext context) {
27 | return Scaffold(
28 | appBar: AppBar(
29 | title: Text('Spiral'),
30 | ),
31 | body: SafeArea(
32 | child: Column(
33 | crossAxisAlignment: CrossAxisAlignment.start,
34 | mainAxisSize: MainAxisSize.max,
35 | children: [
36 | AnimatedBuilder(
37 | animation: _controller,
38 | builder: (context, child) {
39 | print('${_controller.value}');
40 | return Expanded(
41 | child: Center(
42 | child: CustomPaint(
43 | painter: SpiralPainter(
44 | progress: _controller.value,
45 | showPath: showPath,
46 | showDots: showDots,
47 | ),
48 | ),
49 | ),
50 | );
51 | },
52 | ),
53 | Row(
54 | children: [
55 | Padding(
56 | padding: const EdgeInsets.only(left: 24.0, right: 0.0),
57 | child: Text('Show Dots'),
58 | ),
59 | Switch(
60 | value: showDots,
61 | onChanged: (value) {
62 | setState(() {
63 | showDots = value;
64 | });
65 | },
66 | ),
67 | Padding(
68 | padding: const EdgeInsets.only(left: 24.0, right: 0.0),
69 | child: Text('Show Path'),
70 | ),
71 | Switch(
72 | value: showPath,
73 | onChanged: (value) {
74 | setState(() {
75 | showPath = value;
76 | });
77 | },
78 | ),
79 | ],
80 | ),
81 | Padding(
82 | padding: const EdgeInsets.only(left: 24.0),
83 | child: Text('Progress'),
84 | ),
85 | Slider(
86 | value: _controller.value,
87 | min: 0.0,
88 | max: 1.0,
89 | onChanged: (value) {
90 | setState(() {
91 | _controller.value = value;
92 | });
93 | },
94 | ),
95 | Center(
96 | child: RaisedButton(
97 | onPressed: () {
98 | _controller.reset();
99 | _controller.forward();
100 | },
101 | child: Text('Animate'),
102 | ),
103 | ),
104 | ],
105 | ),
106 | ),
107 | );
108 | }
109 |
110 | @override
111 | void dispose() {
112 | _controller.dispose();
113 | super.dispose();
114 | }
115 | }
116 |
117 | class SpiralPainter extends CustomPainter {
118 | SpiralPainter({
119 | this.progress,
120 | this.showPath,
121 | this.showDots,
122 | });
123 |
124 | final double progress;
125 | bool showDots, showPath;
126 |
127 | Paint _paint = Paint()
128 | ..color = Colors.deepPurple
129 | ..strokeWidth = 4.0
130 | ..style = PaintingStyle.stroke
131 | ..strokeCap = StrokeCap.round;
132 |
133 | @override
134 | void paint(Canvas canvas, Size size) {
135 | Path path = createSpiralPath(size);
136 | PathMetric pathMetric = path.computeMetrics().first;
137 | Path extractPath =
138 | pathMetric.extractPath(0.0, pathMetric.length * progress);
139 | if (showPath) {
140 | canvas.drawPath(extractPath, _paint);
141 | }
142 | if (showDots) {
143 | try {
144 | var metric = extractPath.computeMetrics().first;
145 | final offset = metric.getTangentForOffset(metric.length).position;
146 | canvas.drawCircle(offset, 8.0, Paint());
147 | } catch (e) {}
148 | }
149 | }
150 |
151 | Path createSpiralPath(Size size) {
152 | double radius = 0, angle = 0;
153 | Path path = Path();
154 | for (int n = 0; n < 200; n++) {
155 | radius += 0.75;
156 | angle += (math.pi * 2) / 50;
157 | var x = size.width / 2 + radius * math.cos(angle);
158 | var y = size.height / 2 + radius * math.sin(angle);
159 | path.lineTo(x, y);
160 | }
161 | return path;
162 | }
163 |
164 | @override
165 | bool shouldRepaint(CustomPainter oldDelegate) {
166 | return true;
167 | }
168 | }
--------------------------------------------------------------------------------
/lib/perspective/FlipAnimationMain.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_share/perspective/FlipWidget.dart';
3 |
4 | import 'FlipPanel.dart';
5 |
6 | class FlipAnimationMain extends StatefulWidget {
7 | @override
8 | _FlipAnimationMainState createState() => _FlipAnimationMainState();
9 | }
10 |
11 |
12 | class _FlipAnimationMainState extends State {
13 |
14 | final digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9,];
15 |
16 |
17 | @override
18 | Widget build(BuildContext context) {
19 |
20 | //实现绕 X 轴旋转效果
21 | // return Scaffold(
22 | // body: Center(
23 | // child:FlipWidget(
24 | // child: Container(
25 | // width: 300,
26 | // height: 200,
27 | // // color: Colors.green,
28 | // child: Image.asset(
29 | // "images/bg.jpg",
30 | // fit: BoxFit.fill,
31 | // ),
32 | // ),
33 | // )
34 | //
35 | //
36 | // ),
37 | // );
38 |
39 |
40 |
41 | ///实现翻页效果
42 | return new Scaffold(
43 |
44 | body: new Center(
45 | child: FlipPanel.builder(
46 | itemBuilder: (context, index) => Container(
47 | alignment: Alignment.center,
48 | width: 96.0,
49 | height: 128.0,
50 | decoration: BoxDecoration(
51 | color: Colors.black,
52 | borderRadius: BorderRadius.all(Radius.circular(4.0)),
53 | ),
54 | child: Text(
55 | '${digits[index]}',
56 | style: TextStyle(
57 | fontWeight: FontWeight.bold,
58 | fontSize: 80.0,
59 | color: Colors.yellow),
60 | ),
61 | ),
62 | itemsCount: digits.length,
63 | period: Duration(milliseconds: 1000),
64 | loop: -1,
65 | ),
66 | ),
67 | );
68 |
69 |
70 |
71 |
72 |
73 | }
74 |
75 |
76 |
77 |
78 | }
--------------------------------------------------------------------------------
/lib/perspective/FlipPanel.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'dart:async';
3 |
4 | import 'package:flutter/material.dart';
5 |
6 | import 'dart:math' as math;
7 |
8 | /// Signature for a function that creates a widget for a given index, e.g., in a
9 | /// list.
10 | typedef Widget IndexedItemBuilder(BuildContext, int);
11 |
12 | /// Signature for a function that creates a widget for a value emitted from a [Stream]
13 | typedef Widget StreamItemBuilder(BuildContext, T);
14 |
15 | /// A widget for flip panel with built-in animation
16 | /// Content of the panel is built from [IndexedItemBuilder] or [StreamItemBuilder]
17 | ///
18 | /// Note: the content size should be equal
19 | enum FlipDirection { up, down }
20 |
21 | class FlipPanel extends StatefulWidget {
22 | final IndexedItemBuilder indexedItemBuilder;
23 | final StreamItemBuilder streamItemBuilder;
24 | final Stream itemStream;
25 | final int itemsCount;
26 | final Duration period;
27 | final Duration duration;
28 | final int loop;
29 | final int startIndex;
30 | final T initValue;
31 | final double spacing;
32 | final FlipDirection direction;
33 |
34 | FlipPanel({
35 | Key key,
36 | this.indexedItemBuilder,
37 | this.streamItemBuilder,
38 | this.itemStream,
39 | this.itemsCount,
40 | this.period,
41 | this.duration,
42 | this.loop,
43 | this.startIndex,
44 | this.initValue,
45 | this.spacing,
46 | this.direction,
47 | }) : super(key: key);
48 |
49 | /// Create a flip panel from iterable source
50 | /// [itemBuilder] is called periodically in each time of [period]
51 | /// The animation is looped in [loop] times before finished.
52 | /// Setting [loop] to -1 makes flip animation run forever.
53 | /// The [period] should be two times greater than [duration] of flip animation,
54 | /// if not the animation becomes jerky/stuttery.
55 | FlipPanel.builder({
56 | Key key,
57 | @required IndexedItemBuilder itemBuilder,
58 | @required this.itemsCount,
59 | @required this.period,
60 | this.duration = const Duration(milliseconds: 500),
61 | this.loop = 1,
62 | this.startIndex = 0,
63 | this.spacing = 0.5,
64 | this.direction = FlipDirection.up,
65 | }) : assert(itemBuilder != null),
66 | assert(itemsCount != null),
67 | assert(startIndex < itemsCount),
68 | assert(period == null ||
69 | period.inMilliseconds >= 2 * duration.inMilliseconds),
70 | indexedItemBuilder = itemBuilder,
71 | streamItemBuilder = null,
72 | itemStream = null,
73 | initValue = null,
74 | super(key: key);
75 |
76 | /// Create a flip panel from stream source
77 | /// [itemBuilder] is called whenever a new value is emitted from [itemStream]
78 | FlipPanel.stream({
79 | Key key,
80 | @required this.itemStream,
81 | @required StreamItemBuilder itemBuilder,
82 | this.initValue,
83 | this.duration = const Duration(milliseconds: 500),
84 | this.spacing = 0.5,
85 | this.direction = FlipDirection.up,
86 | }) : assert(itemStream != null),
87 | indexedItemBuilder = null,
88 | streamItemBuilder = itemBuilder,
89 | itemsCount = 0,
90 | period = null,
91 | loop = 0,
92 | startIndex = 0,
93 | super(key: key);
94 |
95 | @override
96 | _FlipPanelState createState() => _FlipPanelState();
97 | }
98 |
99 | class _FlipPanelState extends State
100 | with TickerProviderStateMixin {
101 | AnimationController _controller;
102 | Animation _animation;
103 | int _currentIndex;
104 | bool _isReversePhase;
105 | bool _isStreamMode;
106 | bool _running;
107 | final _perspective = 0.003;
108 | final _zeroAngle = 0.0001; // There's something wrong in the perspective transform, I use a very small value instead of zero to temporarily get it around.
109 | int _loop;
110 | T _currentValue, _nextValue;
111 | Timer _timer;
112 | StreamSubscription _subscription;
113 |
114 | Widget _child1, _child2;
115 | Widget _upperChild1, _upperChild2;
116 | Widget _lowerChild1, _lowerChild2;
117 |
118 | @override
119 | void initState() {
120 | super.initState();
121 | _currentIndex = widget.startIndex;
122 | _isStreamMode = widget.itemStream != null;
123 | _isReversePhase = false;
124 | _running = false;
125 | _loop = 0;
126 |
127 | _controller =
128 | new AnimationController(duration: widget.duration, vsync: this)
129 | ..addStatusListener((status) {
130 | if (status == AnimationStatus.completed) {
131 | _isReversePhase = true;
132 | _controller.reverse();
133 | }
134 | if (status == AnimationStatus.dismissed) {
135 | _currentValue = _nextValue;
136 | _running = false;
137 | }
138 | })
139 | ..addListener(() {
140 | setState(() {
141 | _running = true;
142 | });
143 | });
144 | _animation = Tween(begin: _zeroAngle, end: math.pi / 2).animate(_controller);
145 |
146 | if (widget.period != null) {
147 | _timer = Timer.periodic(widget.period, (_) {
148 | if (widget.loop < 0 || _loop < widget.loop) {
149 | if (_currentIndex + 1 == widget.itemsCount - 2) {
150 | _loop++;
151 | }
152 | _currentIndex = (_currentIndex + 1) % widget.itemsCount;
153 | _child1 = null;
154 | _isReversePhase = false;
155 | _controller.forward();
156 | } else {
157 | _timer.cancel();
158 | _currentIndex = (_currentIndex + 1) % widget.itemsCount;
159 | setState(() {
160 | _running = false;
161 | });
162 | }
163 | });
164 | }
165 |
166 | if (_isStreamMode) {
167 | _currentValue = widget.initValue;
168 | _subscription = widget.itemStream.distinct().listen((value) {
169 | if (_currentValue == null) {
170 | _currentValue = value;
171 | } else if (value != _currentValue) {
172 | _nextValue = value;
173 | _child1 = null;
174 | _isReversePhase = false;
175 | _controller.forward();
176 | }
177 | });
178 | } else if (widget.loop < 0 || _loop < widget.loop) {
179 | _controller.forward();
180 | }
181 | }
182 |
183 | @override
184 | void dispose() {
185 | _controller.dispose();
186 | if (_subscription != null) _subscription.cancel();
187 | if (_timer != null) _timer.cancel();
188 | super.dispose();
189 | }
190 |
191 | @override
192 | Widget build(BuildContext context) {
193 | _buildChildWidgetsIfNeed(context);
194 |
195 | return _buildPanel();
196 | }
197 |
198 | void _buildChildWidgetsIfNeed(BuildContext context) {
199 | Widget makeUpperClip(Widget widget) {
200 | return ClipRect(
201 | child: Align(
202 | alignment: Alignment.topCenter,
203 | heightFactor: 0.5,
204 | child: widget,
205 | ),
206 | );
207 | }
208 |
209 | Widget makeLowerClip(Widget widget) {
210 | return ClipRect(
211 | child: Align(
212 | alignment: Alignment.bottomCenter,
213 | heightFactor: 0.5,
214 | child: widget,
215 | ),
216 | );
217 | }
218 |
219 | if (_running) {
220 | if (_child1 == null) {
221 | _child1 = _child2 != null
222 | ? _child2
223 | : _isStreamMode
224 | ? widget.streamItemBuilder(context, _currentValue)
225 | : widget.indexedItemBuilder(
226 | context, _currentIndex % widget.itemsCount);
227 | _child2 = null;
228 | _upperChild1 =
229 | _upperChild2 != null ? _upperChild2 : makeUpperClip(_child1);
230 | _lowerChild1 =
231 | _lowerChild2 != null ? _lowerChild2 : makeLowerClip(_child1);
232 | }
233 | if (_child2 == null) {
234 | _child2 = _isStreamMode
235 | ? widget.streamItemBuilder(context, _nextValue)
236 | : widget.indexedItemBuilder(
237 | context, (_currentIndex + 1) % widget.itemsCount);
238 | _upperChild2 = makeUpperClip(_child2);
239 | _lowerChild2 = makeLowerClip(_child2);
240 | }
241 | } else {
242 | _child1 = _child2 != null
243 | ? _child2
244 | : _isStreamMode
245 | ? widget.streamItemBuilder(context, _currentValue)
246 | : widget.indexedItemBuilder(
247 | context, _currentIndex % widget.itemsCount);
248 | _upperChild1 =
249 | _upperChild2 != null ? _upperChild2 : makeUpperClip(_child1);
250 | _lowerChild1 =
251 | _lowerChild2 != null ? _lowerChild2 : makeLowerClip(_child1);
252 | }
253 | }
254 |
255 | Widget _buildUpperFlipPanel() => widget.direction == FlipDirection.up
256 | ? Stack(
257 | children: [
258 | Transform(
259 | alignment: Alignment.bottomCenter,
260 | transform: Matrix4.identity()
261 | ..setEntry(3, 2, _perspective)
262 | ..rotateX(_zeroAngle),
263 | child: _upperChild1
264 | ),
265 | Transform(
266 | alignment: Alignment.bottomCenter,
267 | transform: Matrix4.identity()
268 | ..setEntry(3, 2, _perspective)
269 | ..rotateX(_isReversePhase ? _animation.value : math.pi / 2),
270 | child: _upperChild2,
271 | ),
272 | ],
273 | )
274 | : Stack(
275 | children: [
276 | Transform(
277 | alignment: Alignment.bottomCenter,
278 | transform: Matrix4.identity()
279 | ..setEntry(3, 2, _perspective)
280 | ..rotateX(_zeroAngle),
281 | child: _upperChild2
282 | ),
283 | Transform(
284 | alignment: Alignment.bottomCenter,
285 | transform: Matrix4.identity()
286 | ..setEntry(3, 2, _perspective)
287 | ..rotateX(_isReversePhase ? math.pi / 2 : _animation.value),
288 | child: _upperChild1,
289 | ),
290 | ],
291 | );
292 |
293 | Widget _buildLowerFlipPanel() => widget.direction == FlipDirection.up
294 | ? Stack(
295 | children: [
296 | Transform(
297 | alignment: Alignment.topCenter,
298 | transform: Matrix4.identity()
299 | ..setEntry(3, 2, _perspective)
300 | ..rotateX(_zeroAngle),
301 | child: _lowerChild2
302 | ),
303 | Transform(
304 | alignment: Alignment.topCenter,
305 | transform: Matrix4.identity()
306 | ..setEntry(3, 2, _perspective)
307 | ..rotateX(_isReversePhase ? math.pi / 2 : -_animation.value),
308 | child: _lowerChild1,
309 | )
310 | ],
311 | )
312 | : Stack(
313 | children: [
314 | Transform(
315 | alignment: Alignment.topCenter,
316 | transform: Matrix4.identity()
317 | ..setEntry(3, 2, _perspective)
318 | ..rotateX(_zeroAngle),
319 | child: _lowerChild1
320 | ),
321 | Transform(
322 | alignment: Alignment.topCenter,
323 | transform: Matrix4.identity()
324 | ..setEntry(3, 2, _perspective)
325 | ..rotateX(_isReversePhase ? -_animation.value : math.pi / 2),
326 | child: _lowerChild2,
327 | )
328 | ],
329 | );
330 |
331 | Widget _buildPanel() {
332 | return _running
333 | ? Column(
334 | mainAxisSize: MainAxisSize.min,
335 | mainAxisAlignment: MainAxisAlignment.center,
336 | crossAxisAlignment: CrossAxisAlignment.center,
337 | children: [
338 | _buildUpperFlipPanel(),
339 | Padding(
340 | padding: EdgeInsets.only(top: widget.spacing),
341 | ),
342 | _buildLowerFlipPanel(),
343 | ],
344 | )
345 | : _isStreamMode && _currentValue == null
346 | ? Container()
347 | : Column(
348 | mainAxisSize: MainAxisSize.min,
349 | mainAxisAlignment: MainAxisAlignment.center,
350 | crossAxisAlignment: CrossAxisAlignment.center,
351 | children: [
352 | Transform(
353 | alignment: Alignment.bottomCenter,
354 | transform: Matrix4.identity()
355 | ..setEntry(3, 2, _perspective)
356 | ..rotateX(_zeroAngle),
357 | child: _upperChild1
358 | ),
359 | Padding(
360 | padding: EdgeInsets.only(top: widget.spacing),
361 | ),
362 | Transform(
363 | alignment: Alignment.topCenter,
364 | transform: Matrix4.identity()
365 | ..setEntry(3, 2, _perspective)
366 | ..rotateX(_zeroAngle),
367 | child: _lowerChild1
368 | )
369 | ],
370 | );
371 | }
372 | }
--------------------------------------------------------------------------------
/lib/perspective/FlipWidget.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import 'package:flutter/material.dart';
4 |
5 | class FlipWidget extends StatelessWidget {
6 | Widget child;
7 |
8 | FlipWidget({Key key, this.child}) : super(key: key);
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return Column(
13 | mainAxisSize: MainAxisSize.min,
14 | children: [
15 |
16 | Transform(
17 | transform: Matrix4.identity()..setEntry(3, 2, 0.006)..rotateX(pi / 4),
18 | alignment: Alignment.bottomCenter,
19 | child: ClipRect(
20 | child: Align(
21 | alignment: Alignment.topCenter,
22 | heightFactor: 0.5,
23 | child: child,
24 | )),
25 | ),
26 |
27 |
28 | // ClipRect(
29 | // child: Align(
30 | // alignment: Alignment.topCenter,
31 | // heightFactor: 0.5,
32 | // child: child,
33 | // )),
34 | //
35 |
36 |
37 | Padding(
38 | padding: EdgeInsets.only(top: 2.0),
39 | ),
40 | ClipRect(
41 | child: Align(
42 | alignment: Alignment.bottomCenter,
43 | heightFactor: 0.5,
44 | child: child,
45 | )),
46 | ],
47 | );
48 | }
49 | }
--------------------------------------------------------------------------------
/lib/perspective/PerspectiveMain.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class PerspectiveMain extends StatefulWidget {
4 | @override
5 | _PerspectiveMainState createState() => _PerspectiveMainState();
6 | }
7 |
8 |
9 | class _PerspectiveMainState extends State {
10 |
11 |
12 | int _counter = 0;
13 | Offset _offset = Offset(0.4, 0.7); // new
14 |
15 | void _incrementCounter() {
16 | setState(() {
17 | _counter++;
18 | });
19 | }
20 |
21 |
22 | _defaultApp(BuildContext context) { // new
23 | return Scaffold(
24 | appBar: AppBar(
25 | title: Text('The Matrix 3D'), // changed
26 | ),
27 | body: Center(
28 | child: Column(
29 | mainAxisAlignment: MainAxisAlignment.center,
30 | children: [
31 | Text(
32 | 'You have pushed the button this many times:',
33 | ),
34 | Text(
35 | '$_counter',
36 | style: Theme.of(context).textTheme.display1,
37 | ),
38 | ],
39 | ),
40 | ),
41 | floatingActionButton: FloatingActionButton(
42 | onPressed: _incrementCounter,
43 | tooltip: 'Increment',
44 | child: Icon(Icons.add),
45 | ),
46 | );
47 | }
48 |
49 |
50 |
51 | @override
52 | Widget build(BuildContext context) {
53 | return Transform( // Transform widget
54 | transform: Matrix4.identity()
55 | ..setEntry(3, 2, 0.001) // perspective
56 | ..rotateX(0.01 * _offset.dy) // changed
57 | ..rotateY(-0.01 * _offset.dx), // changed
58 | alignment: FractionalOffset.center,
59 | child: GestureDetector( // new
60 | onPanUpdate: (details) => setState(() => _offset += details.delta),
61 | onDoubleTap: () => setState(() => _offset = Offset.zero),
62 | child: _defaultApp(context),
63 | )
64 | );
65 |
66 |
67 | }
68 |
69 |
70 |
71 |
72 | }
--------------------------------------------------------------------------------
/lib/refreshData/refresh_data.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | class RefreshDataPage extends StatefulWidget {
5 |
6 | RefreshDataPage({Key key, this.title}) : super(key: key);
7 | final String title;
8 |
9 | @override
10 | _RefreshDataPageState createState() => _RefreshDataPageState();
11 | }
12 |
13 |
14 |
15 | ///最新消息
16 | const String LAST_NEWS = "https://news-at.zhihu.com/api/4/news/latest";
17 |
18 | ///历史消息
19 | const String HISTORY_NEWS = "https://news-at.zhihu.com/api/4/news/before/";
20 |
21 | class _RefreshDataPageState extends State {
22 |
23 |
24 | ///网络请求
25 | Response response;
26 | Dio dio = new Dio();
27 |
28 | Future getDataFuture;
29 |
30 | bool isShowProgress = false;
31 |
32 | //当前日期
33 | String currentDate = "";
34 |
35 | ScrollController _scrollController = ScrollController();
36 |
37 | List items = new List();
38 |
39 |
40 |
41 |
42 | @override
43 | void initState() {
44 | super.initState();
45 | getDataFuture = getItemNews();
46 | _scrollController.addListener(() {
47 | if (_scrollController.position.pixels ==
48 | _scrollController.position.maxScrollExtent) {
49 | print("get more");
50 | _getMore(currentDate);
51 | }
52 | });
53 |
54 | }
55 | ///获取最新消息
56 | Future > getItemNews() async{
57 | items.clear();
58 |
59 | print("开始获取最新消息.");
60 | response = await dio.get(LAST_NEWS);
61 | currentDate = response.data["date"].toString();
62 |
63 | if(response.data["stories"] != null){
64 | items.addAll(response.data["stories"]);
65 | }
66 |
67 | if(items.length < 6){
68 | _getMore(currentDate);
69 | }
70 |
71 |
72 | return items;
73 | }
74 |
75 |
76 |
77 | _getMore(String date) async{
78 | if(date == "")
79 | return;
80 |
81 | setState(() {
82 | isShowProgress = true;
83 | });
84 |
85 | Map historyMap ;
86 | response = await dio.get(HISTORY_NEWS + date);
87 | historyMap = response.data;
88 |
89 | if(historyMap != null && historyMap.length > 0){
90 | List stories = historyMap["stories"];
91 | if(stories != null && stories.length > 0){
92 | currentDate = historyMap["date"].toString();
93 | }
94 |
95 |
96 | if(response.data["stories"] != null){
97 | items.addAll(response.data["stories"]);
98 | }
99 |
100 |
101 | }
102 |
103 | setState(() {
104 | isShowProgress = false;
105 | });
106 |
107 | }
108 |
109 |
110 | @override
111 | Widget build(BuildContext context) {
112 | return Scaffold(
113 | appBar: AppBar(
114 | title: Text("下拉刷新上滑加载数据"),
115 | ),
116 |
117 | body: RefreshIndicator(
118 | onRefresh: getItemNews,
119 | child: FutureBuilder>(
120 | future: getDataFuture,
121 | builder: (context,AsyncSnapshot> async){
122 | ///正在请求时的视图
123 | if (async.connectionState == ConnectionState.active || async.connectionState == ConnectionState.waiting) {
124 | return Center(
125 | child: Text("loading..."),
126 | );
127 | }
128 | ///发生错误时的视图
129 | if (async.connectionState == ConnectionState.done) {
130 | if (async.hasError) {
131 | return Center(
132 | child: Text("error"),
133 | );
134 | } else if (async.hasData && async.data != null && async.data.length > 0) {
135 |
136 | List resultList = async.data;
137 |
138 | return ListView.builder(
139 | controller: _scrollController,
140 | itemCount: resultList.length + 1,
141 | itemExtent: 100.0,
142 | itemBuilder: (BuildContext context, int index) {
143 | return index < async.data.length ? Container(
144 | child: Card(
145 | child: Row(
146 | children: [
147 | Expanded(
148 | child: Container(
149 | child: Text(resultList[index]["title"].toString(),style: TextStyle(fontSize:20),),
150 | padding: EdgeInsets.symmetric(horizontal: 10),
151 | ),
152 | flex: 2,
153 | ),
154 |
155 | Expanded(
156 | child: Container(
157 | child:Image.network(resultList[index]["images"][0].toString()),
158 | padding: EdgeInsets.all(5),
159 | ),
160 | flex: 1,
161 | ),
162 |
163 | ],
164 | ),
165 | ),
166 | height: 50,
167 | ): Center(
168 | child: isShowProgress? CircularProgressIndicator(
169 | strokeWidth: 2.0,
170 | ):Container(),
171 | );
172 |
173 | }
174 | );
175 |
176 | }else{
177 | return Center(
178 | child: Text("error"),
179 | );
180 | }
181 | }
182 | return Center(
183 | child: Text("error"),
184 | );
185 | },
186 | ),
187 |
188 | ),
189 |
190 | );
191 | }
192 |
193 |
194 | @override
195 | void dispose() {
196 | super.dispose();
197 | _scrollController.dispose();
198 | }
199 |
200 |
201 | }
--------------------------------------------------------------------------------
/lib/scheme/home_index.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | /// 首页
4 | class HomePageIndex extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | // TODO: implement build
8 | return Text('I am home page');
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/lib/scheme/router.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_share/scheme/user_index.dart';
3 | import 'package:flutter_share/scheme/web_view_page.dart';
4 | import 'package:flutter_share/stateManager/screens/cart.dart';
5 | import 'package:flutter_share/stateManager/screens/catalog.dart';
6 |
7 | import 'home_index.dart';
8 |
9 | /// app 协议头
10 | const String appScheme = "tyfapp";
11 |
12 | /// action mapping
13 | const Map> paramsMapping = {
14 | 'homepage' : null,
15 | 'userpage' : ['userId']
16 | };
17 |
18 | /// 处理APP内的跳转
19 | class MyRouter {
20 | /// 根据url处理获得需要跳转的action页面以及需要携带的参数
21 | Widget _getPage(String url, Map urlParseRet) {
22 | if (url.startsWith('https://') || url.startsWith('http://')) {
23 | return CommonWebViewPage(url: url);
24 | } else if(url.startsWith(appScheme)) {
25 | // 判断是否解析出 path action,并且能否在路由配置中找到
26 | String pathAction = urlParseRet['action'].toString();
27 | switch (pathAction) {
28 | case "homepage": {
29 | return _buildPage(HomePageIndex());
30 | }
31 | case "userpage": {
32 | // 必要性检查,如果没有参数则不做任何处理
33 | if(urlParseRet['params']['user_id'].toString() == null) {
34 | return null;
35 | }
36 | return _buildPage(
37 | UserPageIndex(
38 | userId: urlParseRet['params']['user_id'].toString()
39 | )
40 | );
41 | }
42 | default: {
43 | return _buildPage(HomePageIndex());
44 | }
45 | }
46 | }
47 | return null;
48 | }
49 |
50 | /// 执行页面跳转
51 | void push(BuildContext context, String url) {
52 | Map urlParseRet = _parseUrl(url);
53 |
54 | Navigator.pushNamedAndRemoveUntil(
55 | context,
56 | urlParseRet['action'].toString(), (route) {
57 | if(route.settings.name ==
58 | urlParseRet['action'].toString()) {
59 | return false;
60 | }
61 | return true;
62 | }, arguments: urlParseRet['params']);
63 | }
64 |
65 | /// 解析跳转的url,并且分析其内部参数
66 | Map _parseUrl(String url) {
67 | if(url.startsWith(appScheme)) {
68 | url = url.substring(9);
69 | }
70 |
71 | int placeIndex = url.indexOf('?');
72 |
73 | if(url == '' || url == null) {
74 | return {'action': '/', 'params': null};
75 | }
76 | if (placeIndex < 0) {
77 | return {'action': url, 'params': null};
78 | }
79 |
80 | String action = url.substring(0, placeIndex);
81 | String paramStr = url.substring(placeIndex + 1);
82 |
83 | if (paramStr == null) {
84 | return {'action': action, 'params': null};
85 | }
86 |
87 | Map params = {};
88 | List paramsStrArr = paramStr.split('&');
89 | for (String singleParamsStr in paramsStrArr) {
90 | List singleParamsArr = singleParamsStr.split('=');
91 | if(paramsMapping[action].indexOf(singleParamsArr[0]) > -1) {
92 | params[singleParamsArr[0]] = singleParamsArr[1];
93 | }
94 | }
95 | return {'action': action, 'params': params};
96 | }
97 |
98 | /// 增加 scaffold
99 | Widget _buildPage(Widget widgetPage) {
100 | return Scaffold(
101 | appBar: AppBar(
102 | title: Text('Two You'), // 页面名字
103 | ),
104 | body: Center(
105 | child: widgetPage,
106 | )
107 | );
108 | }
109 |
110 | /// 注册路由事件
111 | Map registerRouter () {
112 | return {
113 | 'homepage' : (context) => _buildPage(HomePageIndex()),
114 | 'userpage' : (context) => _buildPage(UserPageIndex()),
115 | '/catalog': (context) => MyCatalog(), ///类别
116 | '/cart': (context) => MyCart(),
117 | };
118 | }
119 |
120 | // /// 设置路由跳转逻辑
121 | // MaterialPageRoute generateRoute(String pathAction, Object params) {
122 | // Map paramsMap = {};
123 | // if(params != null) {
124 | // paramsMap = jsonDecode(JsonCodec().encode(params)) as Map;
125 | // }
126 | // switch (pathAction) {
127 | // case 'userpage' : {
128 | // return MaterialPageRoute(
129 | // builder: (context) => _buildPage(
130 | // UserPageIndex(
131 | // userId: paramsMap['userId'].toString()
132 | // )
133 | // )
134 | // );
135 | // }
136 | // case 'homepage' : {
137 | // return MaterialPageRoute(
138 | // builder: (context) => _buildPage(HomePageIndex())
139 | // );
140 | // }
141 | // default: {
142 | // return MaterialPageRoute(
143 | // builder: (context) => _buildPage(HomePageIndex())
144 | // );
145 | // }
146 | // }
147 | // }
148 | }
--------------------------------------------------------------------------------
/lib/scheme/user_index.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_share/utils/json_config.dart';
3 |
4 | /// 首页
5 | class UserPageIndex extends StatelessWidget {
6 | /// 用户 ID 信息
7 | final String userId;
8 |
9 | /// 构造函数
10 | const UserPageIndex({Key key, this.userId}) : super(key: key);
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 |
15 | //通过这种方式刷新页面
16 | Map dataInfo = JsonConfig.objectToMap(
17 | ModalRoute.of(context).settings.arguments
18 | );
19 |
20 | // TODO: implement build
21 | return Text('I am use page ${dataInfo['userId']}');
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lib/scheme/web_view_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
3 |
4 | /// 通用跳转逻辑
5 | class CommonWebViewPage extends StatelessWidget {
6 | /// url 地址
7 | final String url;
8 |
9 | /// 构造函数
10 | CommonWebViewPage({Key key, this.url}) : super(key: key);
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 |
15 | return WebviewScaffold(
16 | url: url,
17 | appBar: AppBar(
18 | backgroundColor: Colors.blue,
19 | ),
20 | );
21 | }
22 |
23 | }
--------------------------------------------------------------------------------
/lib/stateManager/BasicCounter.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 |
4 | import 'package:flutter/material.dart';
5 |
6 | class BasicCounter with ChangeNotifier {
7 | int _counter;
8 |
9 | BasicCounter(this._counter);
10 |
11 | getCounter() => _counter;
12 | setCounter(int counter) => _counter = counter;
13 |
14 | void increment() {
15 | _counter++;
16 | notifyListeners();
17 | }
18 |
19 | void decrement() {
20 | _counter--;
21 | notifyListeners();
22 | }
23 | }
--------------------------------------------------------------------------------
/lib/stateManager/BasicUse/provider_basic.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:provider/provider.dart';
3 |
4 | void main() {
5 | runApp(
6 | ///使用 ChangeNotifierProvider ,这个 Provider 将数据 model 粘合在一起,数据改变时,保证 MyApp 或者其子 Widget ui 更新。
7 | ChangeNotifierProvider(
8 | // Initialize the model in the builder. That way, Provider
9 | // can own Counter's lifecycle, making sure to call `dispose`
10 | // when not needed anymore.
11 | ///builder 会指定数据 model 并初始化。
12 | builder: (context) => Counter(),
13 | child: MyApp(),
14 | ),
15 | );
16 | }
17 |
18 | /// Simplest possible model, with just one field.
19 | ///
20 | /// [ChangeNotifier] is a class in `flutter:foundation`. [Counter] does
21 | /// _not_ depend on Provider.
22 | ///
23 | ///
24 | class Counter with ChangeNotifier {
25 | ///这个 model 只管理一个变量。
26 | int value = 0;
27 |
28 | ///操作变量
29 | void increment() {
30 | value += 1;
31 | notifyListeners();
32 | }
33 | }
34 |
35 | class MyApp extends StatelessWidget {
36 | @override
37 | Widget build(BuildContext context) {
38 | return MaterialApp(
39 | title: 'Flutter Demo',
40 | theme: ThemeData(
41 | primarySwatch: Colors.blue,
42 | ),
43 | home: MyHomePage(),
44 | );
45 | }
46 | }
47 |
48 | class MyHomePage extends StatelessWidget {
49 |
50 | @override
51 | Widget build(BuildContext context) {
52 | ///通过 Provider.of 方式获取 model
53 | final _counter = Provider.of(context);
54 |
55 | return Scaffold(
56 | appBar: AppBar(
57 | title: Text('Flutter Demo Home Page'),
58 | ),
59 | body: Center(
60 | child: Column(
61 | mainAxisAlignment: MainAxisAlignment.center,
62 | children: [
63 | Text('使用 Consumer 获取 model:'),
64 | // Consumer looks for an ancestor Provider widget
65 | // and retrieves its model (Counter, in this case).
66 | // Then it uses that model to build widgets, and will trigger
67 | // rebuilds if the model is updated.
68 |
69 | ///Consumer 回向上寻找 Provider 类型的父类 Widget,并且取出 Provider 关联的 Model,根据这个 model 来构建 widget
70 | ///并且当 model 数据发生改变时,回触发更新。
71 | ///
72 |
73 | Consumer(
74 | builder: (context, counter, child) => Text(
75 | '${counter.value}',
76 | style: Theme.of(context).textTheme.display1,
77 | ),
78 | ),
79 |
80 | Text('使用 Provider.of 方式 获取 model:'),
81 | Text('${_counter.value}',),
82 | ],
83 | ),
84 | ),
85 | floatingActionButton: FloatingActionButton(
86 | /// listen 为 false 表示不监听状态改变,默认时 true
87 | onPressed: () => Provider.of(context, listen: false).increment(),
88 | tooltip: 'Increment',
89 | child: Icon(Icons.add),
90 | ),
91 |
92 |
93 | ///需要修改 Model 同样可以使用 Consumer 的方式
94 | // floatingActionButton: Consumer(
95 | // builder: (context, Counter counter, child) => FloatingActionButton(
96 | // onPressed: counter.increment,
97 | // child: child,
98 | // ),
99 | // child: Icon(Icons.add),
100 | // ),
101 |
102 |
103 | );
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/lib/stateManager/EventProvider.dart:
--------------------------------------------------------------------------------
1 | // EventProvider (Stream)
2 | import 'package:flutter/material.dart';
3 | import 'package:provider/provider.dart';
4 |
5 | import '../main.dart';
6 |
7 | class EventProvider {
8 |
9 | Stream intStream() {
10 | Duration interval = Duration(seconds: 2);
11 | // ThemeData themeData = _themeData == ThemeData.light()?ThemeData.dark():ThemeData.light()
12 | return Stream.periodic(interval, (int _count) => _count %2 == 0?ThemeData.light():ThemeData.dark() );
13 | //return Stream.periodic(interval, (int _count) => _count %2 == 0? 11: 22 );
14 | // return Stream.periodic(interval, (int _count) => _count++);
15 |
16 | }
17 |
18 |
19 | }
--------------------------------------------------------------------------------
/lib/stateManager/User.dart:
--------------------------------------------------------------------------------
1 |
2 | // User Model
3 | class User {
4 | final String firstName, lastName, website;
5 | const User(this.firstName, this.lastName, this.website);
6 |
7 | User.fromJson(Map json):
8 | this.firstName = json['first_name'],
9 | this.lastName = json['last_name'],
10 | this.website = json['website'];
11 |
12 | Map toJson() => {
13 | "first_name": this.firstName,
14 | "last_name": this.lastName,
15 | "website": this.website
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/lib/stateManager/UserList.dart:
--------------------------------------------------------------------------------
1 | // User List Model
2 | import 'User.dart';
3 |
4 | class UserList {
5 | final List users;
6 | UserList(this.users);
7 |
8 | UserList.fromJson(List usersJson) :
9 | users = usersJson.map((user) => User.fromJson(user)).toList();
10 | }
--------------------------------------------------------------------------------
/lib/stateManager/common/theme.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019 The Flutter team. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | import 'package:flutter/material.dart';
6 |
7 | final appTheme = ThemeData(
8 | primarySwatch: Colors.yellow,
9 | textTheme: TextTheme(
10 | display4: TextStyle(
11 | fontFamily: 'Corben',
12 | fontWeight: FontWeight.w700,
13 | fontSize: 24,
14 | color: Colors.black,
15 | ),
16 | ),
17 | );
18 |
--------------------------------------------------------------------------------
/lib/stateManager/index_main.dart:
--------------------------------------------------------------------------------
1 | import 'dart:developer';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter_share/stateManager/user_provider.dart';
5 | import 'package:provider/provider.dart';
6 |
7 | import 'BasicCounter.dart';
8 | import 'EventProvider.dart';
9 | import 'my_event_page.dart';
10 | import 'my_userpage.dart';
11 |
12 | void main() => runApp(
13 | // MyApp()
14 | MultiProvider(
15 | providers: [
16 | ChangeNotifierProvider(builder: (_) => BasicCounter(0)),
17 | FutureProvider(builder: (_) => UserProvider().loadUserData()),
18 | StreamProvider(builder: (_) => EventProvider().intStream(), initialData:ThemeData.light())
19 | ],
20 | child: MyApp()
21 | )
22 | );
23 |
24 | class MyApp extends StatelessWidget {
25 | @override
26 | Widget build(BuildContext context) {
27 |
28 |
29 |
30 | return MaterialApp(
31 | title: 'Flutter Demo',
32 | // theme: ThemeData.light(),
33 | // theme: themeData,
34 | theme: Provider.of(context),
35 |
36 |
37 | home: DefaultTabController(
38 | length: 3,
39 | child: DefaultTabController(
40 | length: 3,
41 | child: Scaffold(
42 | appBar: AppBar(
43 | title: Text("Provider Demo:" ),
44 | bottom: TabBar(
45 | tabs: [
46 | Tab(icon: Icon(Icons.add)),
47 | Tab(icon: Icon(Icons.person)),
48 | Tab(icon: Icon(Icons.message)),
49 | ],
50 | ),
51 | ),
52 | body: TabBarView(
53 | children: [
54 | HomePage(),
55 | MyUserPage(),
56 | MyEventPage(),
57 | ],
58 | ),
59 | ),
60 | )
61 | )
62 |
63 | );
64 | }
65 | }
66 |
67 |
68 |
69 |
70 | class HomePage extends StatelessWidget {
71 | @override
72 | Widget build(BuildContext context) {
73 | final counter = Provider.of(context);
74 | return Scaffold(
75 | appBar: AppBar(
76 | title: Text("Provider Demo"),
77 | ),
78 | body: Center(
79 | child: Column(
80 | mainAxisAlignment: MainAxisAlignment.center,
81 | children: [
82 | Text(
83 | 'You have pushed the button this many times:',
84 | ),
85 | Text(
86 | '${counter.getCounter()}',
87 | style: Theme.of(context).textTheme.display1,
88 | ),
89 | ],
90 | ),
91 | ),
92 | floatingActionButton: Column(
93 | mainAxisAlignment: MainAxisAlignment.end,
94 | children: [
95 | FloatingActionButton(
96 | onPressed: counter.increment,
97 | tooltip: 'Increment',
98 | child: Icon(Icons.add),
99 | ),
100 | SizedBox(height: 10),
101 | FloatingActionButton(
102 | onPressed: counter.decrement,
103 | tooltip: 'Increment',
104 | child: Icon(Icons.remove),
105 | )
106 | ],
107 | ),
108 | );
109 | }
110 | }
111 |
112 |
113 |
--------------------------------------------------------------------------------
/lib/stateManager/models/cart.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019 The Flutter team. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | import 'package:flutter/foundation.dart';
6 |
7 | import 'catalog.dart';
8 |
9 | class CartModel extends ChangeNotifier {
10 | /// The current catalog. Used to construct items from numeric ids.
11 | final CatalogModel _catalog;
12 |
13 | /// 购物车中存放商品的 list,只存 id 就行
14 | final List _itemIds;
15 |
16 | /// Construct a CartModel instance that is backed by a [CatalogModel] and
17 | /// an optional previous state of the cart.
18 | ///
19 | /// If [previous] is not `null`, it's items are copied to the newly
20 | /// constructed instance.
21 | CartModel(this._catalog, CartModel previous)
22 | : assert(_catalog != null),
23 | _itemIds = previous?._itemIds ?? [];
24 |
25 |
26 |
27 | /// 将存放商品 id 的数组转换为存放商品的数值,函数式编程。
28 | List- get items => _itemIds.map((id) => _catalog.getById(id)).toList();
29 |
30 | /// 获取价格总和,dart 中的 List 中有两个累加的方法 reduce 和 fold,fold 可以提供一个初始值。
31 | int get totalPrice =>
32 | items.fold(0, (total, current) => total + current.price);
33 |
34 | ///添加商品,这个方法时外界可以修改 list 的唯一途径
35 | void add(Item item) {
36 | _itemIds.add(item.id);
37 | // This line tells [Model] that it should rebuild the widgets that
38 | // depend on it.
39 | notifyListeners();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/lib/stateManager/models/catalog.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019 The Flutter team. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | import 'package:flutter/material.dart';
6 |
7 | /// A proxy of the catalog of items the user can buy.
8 | ///
9 | /// In a real app, this might be backed by a backend and cached on device.
10 | /// In this sample app, the catalog is procedurally generated and infinite.
11 | ///
12 | /// For simplicity, the catalog is expected to be immutable (no products are
13 | /// expected to be added, removed or changed during the execution of the app).
14 | class CatalogModel {
15 | static const _itemNames = [
16 | 'Code Smell',
17 | 'Control Flow',
18 | 'Interpreter',
19 | 'Recursion',
20 | 'Sprint',
21 | 'Heisenbug',
22 | 'Spaghetti',
23 | 'Hydra Code',
24 | 'Off-By-One',
25 | 'Scope',
26 | 'Callback',
27 | 'Closure',
28 | 'Automata',
29 | 'Bit Shift',
30 | 'Currying',
31 | ];
32 |
33 | /// Get item by [id].
34 | ///
35 | /// In this sample, the catalog is infinite, looping over [_itemNames].
36 | Item getById(int id) => Item(id, _itemNames[id % _itemNames.length]);
37 |
38 | /// Get item by its position in the catalog.
39 | Item getByPosition(int position) {
40 | // In this simplified case, an item's position in the catalog
41 | // is also its id.
42 | return getById(position);
43 | }
44 | }
45 |
46 | @immutable
47 | class Item {
48 | final int id;
49 | final String name;
50 | final Color color;
51 | final int price = 42;
52 |
53 | Item(this.id, this.name)
54 | // To make the sample app look nicer, each item is given one of the
55 | // Material Design primary colors.
56 | : color = Colors.primaries[id % Colors.primaries.length];
57 |
58 | @override
59 | int get hashCode => id;
60 |
61 | @override
62 | bool operator ==(Object other) => other is Item && other.id == id;
63 | }
64 |
--------------------------------------------------------------------------------
/lib/stateManager/my_event_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:provider/provider.dart';
3 |
4 | class MyEventPage extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | //var _value = Provider.of(context);
8 | var _value =0;
9 | return Container(
10 | child: Center(
11 | child: Column(
12 | mainAxisAlignment: MainAxisAlignment.center,
13 | children: [
14 | Text('StreamProvider Example'),
15 | SizedBox(height: 150),
16 | Text('${_value.toString()}',
17 | style: Theme.of(context).textTheme.display1
18 | )
19 | ],
20 | )
21 | )
22 | );
23 | }
24 | }
--------------------------------------------------------------------------------
/lib/stateManager/my_userpage.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:provider/provider.dart';
4 |
5 | import 'User.dart';
6 |
7 | class MyUserPage extends StatelessWidget {
8 | @override
9 | Widget build(BuildContext context) {
10 | var _users = Provider.of
>(context);
11 | return Column(
12 | children: [
13 | Padding(
14 | padding: EdgeInsets.all(10.0),
15 | child: Text(
16 | 'FutureProvider Example, users loaded from a File'
17 | ),
18 | ),
19 | Expanded(
20 | child: _users == null ? Container(child: CupertinoActivityIndicator(radius: 50.0)) :
21 | ListView.builder(
22 | itemCount: _users.length,
23 | itemBuilder: (context, index){
24 | return Container(
25 | height: 50,
26 | color: Colors.grey[(index*200) % 400],
27 | child: Center(
28 | child: Text(
29 | '${_users[index].firstName} ${_users[index].lastName} | ${_users[index].website}'
30 | )
31 | )
32 | );
33 | }
34 | )
35 | )
36 | ],
37 | );
38 | }
39 | }
--------------------------------------------------------------------------------
/lib/stateManager/screens/cart.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019 The Flutter team. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | import 'package:flutter/material.dart';
6 | import 'package:flutter_share/stateManager/models/cart.dart';
7 | import 'package:provider/provider.dart';
8 |
9 | class MyCart extends StatelessWidget {
10 | @override
11 | Widget build(BuildContext context) {
12 | return Scaffold(
13 | appBar: AppBar(
14 | title: Text('Cart', style: Theme.of(context).textTheme.display4),
15 | backgroundColor: Colors.white,
16 | ),
17 | body: Container(
18 | color: Colors.yellow,
19 | child: Column(
20 | children: [
21 | Expanded(
22 | child: Padding(
23 | padding: const EdgeInsets.all(32),
24 | child: _CartList(),
25 | ),
26 | ),
27 | Divider(height: 4, color: Colors.black),
28 | ///价格
29 | _CartTotal()
30 | ],
31 | ),
32 | ),
33 | );
34 | }
35 | }
36 |
37 | class _CartList extends StatelessWidget {
38 | @override
39 | Widget build(BuildContext context) {
40 | var itemNameStyle = Theme.of(context).textTheme.title;
41 |
42 | ///使用 Provider.of 方式获取 CartModel
43 | var cart = Provider.of(context);
44 |
45 | return ListView.builder(
46 | itemCount: cart.items.length,
47 | itemBuilder: (context, index) => ListTile(
48 | leading: Icon(Icons.done),
49 | title: Text(
50 | cart.items[index].name,
51 | style: itemNameStyle,
52 | ),
53 | ),
54 | );
55 | }
56 | }
57 |
58 | class _CartTotal extends StatelessWidget {
59 | @override
60 | Widget build(BuildContext context) {
61 | var hugeStyle = Theme.of(context).textTheme.display4.copyWith(fontSize: 48);
62 |
63 | return SizedBox(
64 | height: 200,
65 | child: Center(
66 | child: Row(
67 | mainAxisAlignment: MainAxisAlignment.center,
68 | children: [
69 | ///使用 Consumer 方式使用 CartModel
70 | Consumer(
71 | builder: (context, cart, child) =>
72 | Text('\$${cart.totalPrice}', style: hugeStyle)),
73 | SizedBox(width: 24),
74 | FlatButton(
75 | onPressed: () {
76 | Scaffold.of(context).showSnackBar(
77 | SnackBar(content: Text('Buying not supported yet.')));
78 | },
79 | color: Colors.white,
80 | child: Text('BUY'),
81 | ),
82 | ],
83 | ),
84 | ),
85 | );
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/lib/stateManager/screens/catalog.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019 The Flutter team. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | import 'package:flutter/material.dart';
6 | import 'package:flutter_share/stateManager/models/cart.dart';
7 | import 'package:flutter_share/stateManager/models/catalog.dart';
8 | import 'package:provider/provider.dart';
9 |
10 |
11 | class MyCatalog extends StatelessWidget {
12 | @override
13 | Widget build(BuildContext context) {
14 | return Scaffold(
15 | body: CustomScrollView(
16 | slivers: [
17 | _MyAppBar(),
18 | ///上间距
19 | SliverToBoxAdapter(child: SizedBox(height: 12)),
20 | SliverList(
21 | delegate: SliverChildBuilderDelegate(
22 | (context, index) => _MyListItem(index)
23 | ,
24 | childCount: 25 ///本来时无限加载的,这里加上数量限制。
25 | ),
26 | ),
27 | ],
28 | ),
29 | );
30 | }
31 | }
32 |
33 | class _AddButton extends StatelessWidget {
34 | final Item item;
35 |
36 | const _AddButton({Key key, @required this.item}) : super(key: key);
37 |
38 | @override
39 | Widget build(BuildContext context) {
40 |
41 | ///通过 Provider.of 方式使用 CartModel
42 | var cart = Provider.of(context);
43 |
44 | return FlatButton(
45 | ///判断是否为空,不为空 list 中添加 item
46 | onPressed: cart.items.contains(item) ? null : () => cart.add(item),
47 | splashColor: Theme.of(context).primaryColor,
48 | child: cart.items.contains(item)
49 | ? Icon(Icons.check, semanticLabel: 'ADDED')
50 | : Text('ADD'),
51 | );
52 | }
53 | }
54 |
55 | class _MyAppBar extends StatelessWidget {
56 | @override
57 | Widget build(BuildContext context) {
58 | return SliverAppBar(
59 | title: Text('Catalog', style: Theme.of(context).textTheme.display4),
60 | floating: true,
61 | actions: [
62 | IconButton(
63 | icon: Icon(Icons.shopping_cart),
64 | onPressed: () => Navigator.pushNamed(context, '/cart'),
65 | ),
66 | ],
67 | );
68 | }
69 | }
70 |
71 | class _MyListItem extends StatelessWidget {
72 | final int index;
73 |
74 | _MyListItem(this.index, {Key key}) : super(key: key);
75 |
76 | @override
77 | Widget build(BuildContext context) {
78 |
79 | ///Provider.of 方式获取 model
80 | var catalog = Provider.of(context);
81 | var item = catalog.getByPosition(index);
82 | var textTheme = Theme.of(context).textTheme.title;
83 |
84 | return Padding(
85 | padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
86 | child: LimitedBox(
87 | maxHeight: 48,
88 | child: Row(
89 | children: [
90 | AspectRatio(
91 | aspectRatio: 1,
92 | child: Container(
93 | color: item.color,
94 | ),
95 | ),
96 | SizedBox(width: 24),
97 | Expanded(
98 | child: Text(item.name, style: textTheme),
99 | ),
100 | SizedBox(width: 24),
101 | _AddButton(item: item),
102 | ],
103 | ),
104 | ),
105 | );
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/lib/stateManager/user_provider.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:flutter/services.dart';
4 |
5 | import 'User.dart';
6 | import 'UserList.dart';
7 |
8 | class UserProvider {
9 | final String _dataPath = "assets/data/users.json";
10 | List users;
11 |
12 | Future> loadUserData( ) async {
13 | var dataString = await loadAsset();
14 | Map jsonUserData = jsonDecode(dataString);
15 | users = UserList.fromJson(jsonUserData['users']).users;
16 | print('done loading user!' + jsonEncode(users));
17 | return users;
18 | }
19 |
20 | Future loadAsset() async {
21 | return await Future.delayed(Duration(seconds: 10), () async {
22 | return await rootBundle.loadString('assets/data/users.json');
23 | });
24 | }
25 | }
--------------------------------------------------------------------------------
/lib/utils/json_config.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:flutter/services.dart' show rootBundle;
4 |
5 | /// 缓存配置信息,避免多次读取文件
6 | const Map cache = {};
7 |
8 | /// 获取 json 配置文件
9 | ///
10 | /// 在使用该方法前,需要在 pubspec.yaml 中增加 assets 的配置引入
11 | class JsonConfig {
12 | /// 读取 json 配置文件,并解析返回
13 | static Future getConfig(String fileName) async {
14 | if(cache[fileName] != null){
15 | return cache[fileName];
16 | }
17 | final jsonString = await rootBundle.loadString('assets/json/${fileName}.dart');
18 | try {
19 | var jsonRet = json.decode(jsonString);
20 | cache[fileName] = jsonRet;
21 | return jsonRet;
22 | } catch (err){
23 | // @todo add report log
24 | return false;
25 | }
26 | }
27 |
28 | /// object convert to map data
29 | static Map objectToMap(Object data) {
30 | return jsonDecode(JsonCodec().encode(data)) as Map;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | async:
5 | dependency: "direct main"
6 | description:
7 | name: async
8 | url: "https://pub.flutter-io.cn"
9 | source: hosted
10 | version: "2.5.0-nullsafety.1"
11 | boolean_selector:
12 | dependency: transitive
13 | description:
14 | name: boolean_selector
15 | url: "https://pub.flutter-io.cn"
16 | source: hosted
17 | version: "2.1.0-nullsafety.1"
18 | characters:
19 | dependency: transitive
20 | description:
21 | name: characters
22 | url: "https://pub.flutter-io.cn"
23 | source: hosted
24 | version: "1.1.0-nullsafety.3"
25 | charcode:
26 | dependency: transitive
27 | description:
28 | name: charcode
29 | url: "https://pub.flutter-io.cn"
30 | source: hosted
31 | version: "1.2.0-nullsafety.1"
32 | charts_common:
33 | dependency: transitive
34 | description:
35 | name: charts_common
36 | url: "https://pub.flutter-io.cn"
37 | source: hosted
38 | version: "0.9.0"
39 | charts_flutter:
40 | dependency: "direct main"
41 | description:
42 | name: charts_flutter
43 | url: "https://pub.flutter-io.cn"
44 | source: hosted
45 | version: "0.9.0"
46 | clock:
47 | dependency: transitive
48 | description:
49 | name: clock
50 | url: "https://pub.flutter-io.cn"
51 | source: hosted
52 | version: "1.1.0-nullsafety.1"
53 | collection:
54 | dependency: transitive
55 | description:
56 | name: collection
57 | url: "https://pub.flutter-io.cn"
58 | source: hosted
59 | version: "1.15.0-nullsafety.3"
60 | cupertino_icons:
61 | dependency: "direct main"
62 | description:
63 | name: cupertino_icons
64 | url: "https://pub.flutter-io.cn"
65 | source: hosted
66 | version: "0.1.2"
67 | dio:
68 | dependency: "direct main"
69 | description:
70 | name: dio
71 | url: "https://pub.flutter-io.cn"
72 | source: hosted
73 | version: "3.0.9"
74 | fake_async:
75 | dependency: transitive
76 | description:
77 | name: fake_async
78 | url: "https://pub.flutter-io.cn"
79 | source: hosted
80 | version: "1.2.0-nullsafety.1"
81 | file_utils:
82 | dependency: "direct main"
83 | description:
84 | name: file_utils
85 | url: "https://pub.flutter-io.cn"
86 | source: hosted
87 | version: "0.1.4"
88 | flutter:
89 | dependency: "direct main"
90 | description: flutter
91 | source: sdk
92 | version: "0.0.0"
93 | flutter_test:
94 | dependency: "direct dev"
95 | description: flutter
96 | source: sdk
97 | version: "0.0.0"
98 | flutter_webview_plugin:
99 | dependency: "direct main"
100 | description:
101 | name: flutter_webview_plugin
102 | url: "https://pub.flutter-io.cn"
103 | source: hosted
104 | version: "0.3.0+2"
105 | globbing:
106 | dependency: transitive
107 | description:
108 | name: globbing
109 | url: "https://pub.flutter-io.cn"
110 | source: hosted
111 | version: "0.3.1"
112 | http_parser:
113 | dependency: transitive
114 | description:
115 | name: http_parser
116 | url: "https://pub.flutter-io.cn"
117 | source: hosted
118 | version: "3.1.4"
119 | intl:
120 | dependency: transitive
121 | description:
122 | name: intl
123 | url: "https://pub.flutter-io.cn"
124 | source: hosted
125 | version: "0.16.1"
126 | logging:
127 | dependency: transitive
128 | description:
129 | name: logging
130 | url: "https://pub.flutter-io.cn"
131 | source: hosted
132 | version: "0.11.4"
133 | matcher:
134 | dependency: transitive
135 | description:
136 | name: matcher
137 | url: "https://pub.flutter-io.cn"
138 | source: hosted
139 | version: "0.12.10-nullsafety.1"
140 | meta:
141 | dependency: transitive
142 | description:
143 | name: meta
144 | url: "https://pub.flutter-io.cn"
145 | source: hosted
146 | version: "1.3.0-nullsafety.3"
147 | path:
148 | dependency: transitive
149 | description:
150 | name: path
151 | url: "https://pub.flutter-io.cn"
152 | source: hosted
153 | version: "1.8.0-nullsafety.1"
154 | path_provider:
155 | dependency: "direct main"
156 | description:
157 | name: path_provider
158 | url: "https://pub.flutter-io.cn"
159 | source: hosted
160 | version: "1.6.9"
161 | path_provider_macos:
162 | dependency: transitive
163 | description:
164 | name: path_provider_macos
165 | url: "https://pub.flutter-io.cn"
166 | source: hosted
167 | version: "0.0.4+3"
168 | path_provider_platform_interface:
169 | dependency: transitive
170 | description:
171 | name: path_provider_platform_interface
172 | url: "https://pub.flutter-io.cn"
173 | source: hosted
174 | version: "1.0.2"
175 | platform:
176 | dependency: transitive
177 | description:
178 | name: platform
179 | url: "https://pub.flutter-io.cn"
180 | source: hosted
181 | version: "2.2.1"
182 | plugin_platform_interface:
183 | dependency: transitive
184 | description:
185 | name: plugin_platform_interface
186 | url: "https://pub.flutter-io.cn"
187 | source: hosted
188 | version: "1.0.2"
189 | provider:
190 | dependency: "direct main"
191 | description:
192 | name: provider
193 | url: "https://pub.flutter-io.cn"
194 | source: hosted
195 | version: "3.1.0"
196 | simple_permissions:
197 | dependency: "direct main"
198 | description:
199 | name: simple_permissions
200 | url: "https://pub.flutter-io.cn"
201 | source: hosted
202 | version: "0.1.9"
203 | sky_engine:
204 | dependency: transitive
205 | description: flutter
206 | source: sdk
207 | version: "0.0.99"
208 | source_span:
209 | dependency: transitive
210 | description:
211 | name: source_span
212 | url: "https://pub.flutter-io.cn"
213 | source: hosted
214 | version: "1.8.0-nullsafety.2"
215 | stack_trace:
216 | dependency: transitive
217 | description:
218 | name: stack_trace
219 | url: "https://pub.flutter-io.cn"
220 | source: hosted
221 | version: "1.10.0-nullsafety.1"
222 | stream_channel:
223 | dependency: transitive
224 | description:
225 | name: stream_channel
226 | url: "https://pub.flutter-io.cn"
227 | source: hosted
228 | version: "2.1.0-nullsafety.1"
229 | string_scanner:
230 | dependency: transitive
231 | description:
232 | name: string_scanner
233 | url: "https://pub.flutter-io.cn"
234 | source: hosted
235 | version: "1.1.0-nullsafety.1"
236 | term_glyph:
237 | dependency: transitive
238 | description:
239 | name: term_glyph
240 | url: "https://pub.flutter-io.cn"
241 | source: hosted
242 | version: "1.2.0-nullsafety.1"
243 | test_api:
244 | dependency: transitive
245 | description:
246 | name: test_api
247 | url: "https://pub.flutter-io.cn"
248 | source: hosted
249 | version: "0.2.19-nullsafety.2"
250 | typed_data:
251 | dependency: transitive
252 | description:
253 | name: typed_data
254 | url: "https://pub.flutter-io.cn"
255 | source: hosted
256 | version: "1.3.0-nullsafety.3"
257 | uni_links:
258 | dependency: "direct main"
259 | description:
260 | name: uni_links
261 | url: "https://pub.flutter-io.cn"
262 | source: hosted
263 | version: "0.4.0"
264 | vector_math:
265 | dependency: transitive
266 | description:
267 | name: vector_math
268 | url: "https://pub.flutter-io.cn"
269 | source: hosted
270 | version: "2.1.0-nullsafety.3"
271 | sdks:
272 | dart: ">=2.10.0-110 <2.11.0"
273 | flutter: ">=1.12.13+hotfix.5 <2.0.0"
274 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: flutter_share
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 | # In Android, build-name is used as versionName while build-number used as versionCode.
10 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
11 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
12 | # Read more about iOS versioning at
13 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
14 | version: 1.0.0+1
15 |
16 | environment:
17 | sdk: ">=2.1.0 <3.0.0"
18 |
19 | dependencies:
20 | flutter:
21 | sdk: flutter
22 |
23 | # The following adds the Cupertino Icons font to your application.
24 | # Use with the CupertinoIcons class for iOS style icons.
25 | cupertino_icons: ^0.1.2
26 |
27 | #网络请求
28 | dio: ^3.0.9
29 |
30 | #provider 全局状态管理
31 | provider: ^3.0.1
32 |
33 | #图形图表绘制
34 | charts_flutter: ^0.9.0
35 |
36 | #异步依赖
37 | async: ^2.3.0
38 |
39 | #文件路径管理
40 | path_provider: ^1.6.9
41 |
42 | #权限检查
43 | simple_permissions: ^0.1.9
44 |
45 | #文件管理
46 | file_utils: ^0.1.3
47 |
48 |
49 | #scheme 实用
50 | flutter_webview_plugin: 0.3.0+2
51 | uni_links: ^0.4.0
52 |
53 |
54 |
55 |
56 | dev_dependencies:
57 | flutter_test:
58 | sdk: flutter
59 |
60 |
61 | # For information on the generic Dart part of this file, see the
62 | # following page: https://dart.dev/tools/pub/pubspec
63 |
64 | # The following section is specific to Flutter.
65 | flutter:
66 |
67 | # The following line ensures that the Material Icons font is
68 | # included with your application, so that you can use the icons in
69 | # the material Icons class.
70 | uses-material-design: true
71 |
72 | assets:
73 | - images/bg.jpg
74 | - assets/data/users.json
75 | - images/
76 |
77 |
78 | # To add assets to your application, add an assets section, like this:
79 | # assets:
80 | # - images/a_dot_burr.jpeg
81 | # - images/a_dot_ham.jpeg
82 |
83 | # An image asset can refer to one or more resolution-specific "variants", see
84 | # https://flutter.dev/assets-and-images/#resolution-aware.
85 |
86 | # For details regarding adding assets from package dependencies, see
87 | # https://flutter.dev/assets-and-images/#from-packages
88 |
89 | # To add custom fonts to your application, add a fonts section here,
90 | # in this "flutter" section. Each entry in this list should have a
91 | # "family" key with the font family name, and a "fonts" key with a
92 | # list giving the asset and other descriptors for the font. For
93 | # example:
94 | # fonts:
95 | # - family: Schyler
96 | # fonts:
97 | # - asset: fonts/Schyler-Regular.ttf
98 | # - asset: fonts/Schyler-Italic.ttf
99 | # style: italic
100 | # - family: Trajan Pro
101 | # fonts:
102 | # - asset: fonts/TrajanPro.ttf
103 | # - asset: fonts/TrajanPro_Bold.ttf
104 | # weight: 700
105 | #
106 | # For details regarding fonts from package dependencies,
107 | # see https://flutter.dev/custom-fonts/#from-packages
108 |
--------------------------------------------------------------------------------
/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | //
3 | // To perform an interaction with a widget in your test, use the WidgetTester
4 | // utility that Flutter provides. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter/material.dart';
9 | import 'package:flutter_test/flutter_test.dart';
10 |
11 | import 'package:flutter_share/main.dart';
12 |
13 | void main() {
14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 | // Build our app and trigger a frame.
16 | await tester.pumpWidget(MyApp());
17 |
18 | // Verify that our counter starts at 0.
19 | expect(find.text('0'), findsOneWidget);
20 | expect(find.text('1'), findsNothing);
21 |
22 | // Tap the '+' icon and trigger a frame.
23 | await tester.tap(find.byIcon(Icons.add));
24 | await tester.pump();
25 |
26 | // Verify that our counter has incremented.
27 | expect(find.text('0'), findsNothing);
28 | expect(find.text('1'), findsOneWidget);
29 | });
30 | }
31 |
--------------------------------------------------------------------------------