├── .gitignore
├── .metadata
├── 112110502929_0IMG_0219.png
├── 112110542562_0IMG_0199.png
├── 1574306235.png
├── README.md
├── android
├── app
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── flutterapp
│ │ │ └── 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
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── assets
└── images
│ ├── 2.0x
│ ├── flutter.jpeg
│ ├── flutter2.jpeg
│ └── heart.png
│ ├── 2018.jpg
│ ├── 3.0x
│ ├── flutter.jpeg
│ ├── flutter2.jpeg
│ └── heart.png
│ ├── flutter.jpeg
│ ├── flutter2.jpeg
│ ├── food01.jpeg
│ ├── food02.jpeg
│ ├── food03.jpeg
│ ├── food04.jpeg
│ ├── food05.jpeg
│ ├── food06.jpeg
│ ├── footer.jpeg
│ ├── girl01.png
│ ├── girl02.png
│ ├── girl03.png
│ ├── heart.png
│ └── shop.jpeg
├── images
├── 2018.jpg
├── flutter.jpeg
├── flutter2.jpeg
├── food01.jpeg
├── food02.jpeg
├── food03.jpeg
├── food04.jpeg
├── food05.jpeg
├── food06.jpeg
├── footer.jpeg
├── girl01.png
├── girl02.png
├── girl03.png
├── heart.png
└── shop.jpeg
├── ios
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
└── 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
│ └── zh.lproj
│ ├── LaunchScreen.strings
│ └── Main.strings
├── lib
├── FlutterApp.dart
├── main.dart
├── projectDemo
│ ├── DouBanDemo.dart
│ └── pages
│ │ ├── GroupPage.dart
│ │ ├── MoviePage.dart
│ │ ├── PersonPage.dart
│ │ └── ShopPage.dart
├── router
│ ├── FlutterHero.dart
│ ├── FlutterRouterNewScreen.dart
│ ├── NamedRouter.dart
│ └── SendDataNewScreen.dart
├── sharedelement
│ ├── README.md
│ ├── custom_flow_delegate.dart
│ ├── product_detail.dart
│ ├── product_list.dart
│ ├── shared_element_shop.dart
│ └── shared_element_transition.dart
├── test
│ └── ContainerTestWidget.dart
└── widgets
│ ├── FlutterAlign.dart
│ ├── FlutterBottomNavigationBar.dart
│ ├── FlutterButtonBar.dart
│ ├── FlutterCardWidget.dart
│ ├── FlutterContainer.dart
│ ├── FlutterDemoTest.dart
│ ├── FlutterDropdownButton.dart
│ ├── FlutterFlatButton.dart
│ ├── FlutterFloatingActionButton.dart
│ ├── FlutterGridView.dart
│ ├── FlutterIcon.dart
│ ├── FlutterIconButton.dart
│ ├── FlutterImage.dart
│ ├── FlutterListView.dart
│ ├── FlutterPopupMenuButton.dart
│ ├── FlutterRaisedButton.dart
│ ├── FlutterRow.dart
│ ├── FlutterSliverAppBar.dart
│ ├── FlutterStack.dart
│ ├── FlutterTabBar.dart
│ ├── FlutterTabBarView.dart
│ ├── FlutterTextWidget.dart
│ ├── bottom_drag_widget.dart
│ ├── scrollView
│ ├── FlutterCustomScrollView.dart
│ ├── FlutterNestedScrollView.dart
│ └── FlutterSliverToBoxAdapter.dart
│ └── sliver
│ ├── README.md
│ ├── sliver_box.dart
│ ├── sliver_expanded_appbar.dart
│ ├── sliver_grid.dart
│ ├── sliver_header.dart
│ ├── sliver_list.dart
│ └── sliver_menu.dart
├── pubspec.yaml
├── quaful-release.apk
└── test
└── widget_test.dart
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.lock
4 | *.log
5 | *.pyc
6 | *.swp
7 | .DS_Store
8 | .atom/
9 | .buildlog/
10 | .history
11 | .svn/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # Visual Studio Code related
20 | .vscode/
21 |
22 | # Flutter/Dart/Pub related
23 | **/doc/api/
24 | .dart_tool/
25 | .flutter-plugins
26 | .packages
27 | .pub-cache/
28 | .pub/
29 | build/
30 |
31 | # Android related
32 | **/android/**/gradle-wrapper.jar
33 | **/android/.gradle
34 | **/android/captures/
35 | **/android/gradlew
36 | **/android/gradlew.bat
37 | **/android/local.properties
38 | **/android/**/GeneratedPluginRegistrant.java
39 |
40 | # iOS/XCode related
41 | **/ios/**/*.mode1v3
42 | **/ios/**/*.mode2v3
43 | **/ios/**/*.moved-aside
44 | **/ios/**/*.pbxuser
45 | **/ios/**/*.perspectivev3
46 | **/ios/**/*sync/
47 | **/ios/**/.sconsign.dblite
48 | **/ios/**/.tags*
49 | **/ios/**/.vagrant/
50 | **/ios/**/DerivedData/
51 | **/ios/**/Icon?
52 | **/ios/**/Pods/
53 | **/ios/**/.symlinks/
54 | **/ios/**/profile
55 | **/ios/**/xcuserdata
56 | **/ios/.generated/
57 | **/ios/Flutter/App.framework
58 | **/ios/Flutter/Flutter.framework
59 | **/ios/Flutter/Generated.xcconfig
60 | **/ios/Flutter/app.flx
61 | **/ios/Flutter/app.zip
62 | **/ios/Flutter/flutter_assets/
63 | **/ios/ServiceDefinitions.json
64 | **/ios/Runner/GeneratedPluginRegistrant.*
65 |
66 | # Exceptions to above rules.
67 | !**/ios/**/default.mode1v3
68 | !**/ios/**/default.mode2v3
69 | !**/ios/**/default.pbxuser
70 | !**/ios/**/default.perspectivev3
71 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
72 |
--------------------------------------------------------------------------------
/.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: 72bf075e8d6961d2ca6df462b2228954f8d0e73a
8 | channel: dev
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/112110502929_0IMG_0219.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/112110502929_0IMG_0219.png
--------------------------------------------------------------------------------
/112110542562_0IMG_0199.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/112110542562_0IMG_0199.png
--------------------------------------------------------------------------------
/1574306235.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/1574306235.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # flutter_widget_demo
2 |
3 | 包含了Flutter的大部分Widget的使用demo,
4 | 感谢您的Star!
5 |
6 | ## Getting Started
7 |
8 | For help getting started with Flutter, view our online
9 | [documentation](https://flutter.io/).
10 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
26 |
27 | android {
28 | compileSdkVersion 27
29 |
30 | lintOptions {
31 | disable 'InvalidPackage'
32 | }
33 |
34 | defaultConfig {
35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
36 | applicationId "com.example.flutterapp"
37 | minSdkVersion 16
38 | targetSdkVersion 27
39 | versionCode flutterVersionCode.toInteger()
40 | versionName flutterVersionName
41 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
42 | }
43 |
44 | buildTypes {
45 | release {
46 | // TODO: Add your own signing config for the release build.
47 | // Signing with the debug keys for now, so `flutter run --release` works.
48 | signingConfig signingConfigs.debug
49 | }
50 | }
51 | }
52 |
53 | flutter {
54 | source '../..'
55 | }
56 |
57 | dependencies {
58 | testImplementation 'junit:junit:4.12'
59 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
60 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
61 | }
62 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
10 |
11 |
12 |
17 |
21 |
28 |
32 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/example/flutterapp/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.flutterapp;
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/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | jcenter()
5 | }
6 |
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:3.2.1'
9 | }
10 | }
11 |
12 | allprojects {
13 | repositories {
14 | google()
15 | jcenter()
16 | }
17 | }
18 |
19 | rootProject.buildDir = '../build'
20 | subprojects {
21 | project.buildDir = "${rootProject.buildDir}/${project.name}"
22 | }
23 | subprojects {
24 | project.evaluationDependsOn(':app')
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/assets/images/2.0x/flutter.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/2.0x/flutter.jpeg
--------------------------------------------------------------------------------
/assets/images/2.0x/flutter2.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/2.0x/flutter2.jpeg
--------------------------------------------------------------------------------
/assets/images/2.0x/heart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/2.0x/heart.png
--------------------------------------------------------------------------------
/assets/images/2018.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/2018.jpg
--------------------------------------------------------------------------------
/assets/images/3.0x/flutter.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/3.0x/flutter.jpeg
--------------------------------------------------------------------------------
/assets/images/3.0x/flutter2.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/3.0x/flutter2.jpeg
--------------------------------------------------------------------------------
/assets/images/3.0x/heart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/3.0x/heart.png
--------------------------------------------------------------------------------
/assets/images/flutter.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/flutter.jpeg
--------------------------------------------------------------------------------
/assets/images/flutter2.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/flutter2.jpeg
--------------------------------------------------------------------------------
/assets/images/food01.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/food01.jpeg
--------------------------------------------------------------------------------
/assets/images/food02.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/food02.jpeg
--------------------------------------------------------------------------------
/assets/images/food03.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/food03.jpeg
--------------------------------------------------------------------------------
/assets/images/food04.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/food04.jpeg
--------------------------------------------------------------------------------
/assets/images/food05.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/food05.jpeg
--------------------------------------------------------------------------------
/assets/images/food06.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/food06.jpeg
--------------------------------------------------------------------------------
/assets/images/footer.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/footer.jpeg
--------------------------------------------------------------------------------
/assets/images/girl01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/girl01.png
--------------------------------------------------------------------------------
/assets/images/girl02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/girl02.png
--------------------------------------------------------------------------------
/assets/images/girl03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/girl03.png
--------------------------------------------------------------------------------
/assets/images/heart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/heart.png
--------------------------------------------------------------------------------
/assets/images/shop.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/assets/images/shop.jpeg
--------------------------------------------------------------------------------
/images/2018.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/images/2018.jpg
--------------------------------------------------------------------------------
/images/flutter.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/images/flutter.jpeg
--------------------------------------------------------------------------------
/images/flutter2.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/images/flutter2.jpeg
--------------------------------------------------------------------------------
/images/food01.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/images/food01.jpeg
--------------------------------------------------------------------------------
/images/food02.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/images/food02.jpeg
--------------------------------------------------------------------------------
/images/food03.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/images/food03.jpeg
--------------------------------------------------------------------------------
/images/food04.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/images/food04.jpeg
--------------------------------------------------------------------------------
/images/food05.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/images/food05.jpeg
--------------------------------------------------------------------------------
/images/food06.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/images/food06.jpeg
--------------------------------------------------------------------------------
/images/footer.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/images/footer.jpeg
--------------------------------------------------------------------------------
/images/girl01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/images/girl01.png
--------------------------------------------------------------------------------
/images/girl02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/images/girl02.png
--------------------------------------------------------------------------------
/images/girl03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/images/girl03.png
--------------------------------------------------------------------------------
/images/heart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/images/heart.png
--------------------------------------------------------------------------------
/images/shop.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/images/shop.jpeg
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11 | 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; };
12 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
13 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
14 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
15 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
16 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
17 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
18 | 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
19 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
20 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
21 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
22 | /* End PBXBuildFile section */
23 |
24 | /* Begin PBXCopyFilesBuildPhase section */
25 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
26 | isa = PBXCopyFilesBuildPhase;
27 | buildActionMask = 2147483647;
28 | dstPath = "";
29 | dstSubfolderSpec = 10;
30 | files = (
31 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
32 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
33 | );
34 | name = "Embed Frameworks";
35 | runOnlyForDeploymentPostprocessing = 0;
36 | };
37 | /* End PBXCopyFilesBuildPhase section */
38 |
39 | /* Begin PBXFileReference section */
40 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
41 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
42 | 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; };
43 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
44 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; };
45 | 4BC6E22E21B8DEC7002DF9F4 /* zh */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = zh; path = zh.lproj/Main.strings; sourceTree = ""; };
46 | 4BC6E22F21B8DEC7002DF9F4 /* zh */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = zh; path = zh.lproj/LaunchScreen.strings; sourceTree = ""; };
47 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
48 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
49 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
50 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
51 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
52 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; };
53 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
54 | 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
55 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
56 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
57 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
58 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
59 | /* End PBXFileReference section */
60 |
61 | /* Begin PBXFrameworksBuildPhase section */
62 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
63 | isa = PBXFrameworksBuildPhase;
64 | buildActionMask = 2147483647;
65 | files = (
66 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
67 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
68 | );
69 | runOnlyForDeploymentPostprocessing = 0;
70 | };
71 | /* End PBXFrameworksBuildPhase section */
72 |
73 | /* Begin PBXGroup section */
74 | 9740EEB11CF90186004384FC /* Flutter */ = {
75 | isa = PBXGroup;
76 | children = (
77 | 2D5378251FAA1A9400D5DBA9 /* flutter_assets */,
78 | 3B80C3931E831B6300D905FE /* App.framework */,
79 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
80 | 9740EEBA1CF902C7004384FC /* Flutter.framework */,
81 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
82 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
83 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
84 | );
85 | name = Flutter;
86 | sourceTree = "";
87 | };
88 | 97C146E51CF9000F007C117D = {
89 | isa = PBXGroup;
90 | children = (
91 | 9740EEB11CF90186004384FC /* Flutter */,
92 | 97C146F01CF9000F007C117D /* Runner */,
93 | 97C146EF1CF9000F007C117D /* Products */,
94 | );
95 | sourceTree = "";
96 | };
97 | 97C146EF1CF9000F007C117D /* Products */ = {
98 | isa = PBXGroup;
99 | children = (
100 | 97C146EE1CF9000F007C117D /* Runner.app */,
101 | );
102 | name = Products;
103 | sourceTree = "";
104 | };
105 | 97C146F01CF9000F007C117D /* Runner */ = {
106 | isa = PBXGroup;
107 | children = (
108 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
109 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
110 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
111 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
112 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
113 | 97C147021CF9000F007C117D /* Info.plist */,
114 | 97C146F11CF9000F007C117D /* Supporting Files */,
115 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
116 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
117 | );
118 | path = Runner;
119 | sourceTree = "";
120 | };
121 | 97C146F11CF9000F007C117D /* Supporting Files */ = {
122 | isa = PBXGroup;
123 | children = (
124 | 97C146F21CF9000F007C117D /* main.m */,
125 | );
126 | name = "Supporting Files";
127 | sourceTree = "";
128 | };
129 | /* End PBXGroup section */
130 |
131 | /* Begin PBXNativeTarget section */
132 | 97C146ED1CF9000F007C117D /* Runner */ = {
133 | isa = PBXNativeTarget;
134 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
135 | buildPhases = (
136 | 9740EEB61CF901F6004384FC /* Run Script */,
137 | 97C146EA1CF9000F007C117D /* Sources */,
138 | 97C146EB1CF9000F007C117D /* Frameworks */,
139 | 97C146EC1CF9000F007C117D /* Resources */,
140 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
141 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
142 | );
143 | buildRules = (
144 | );
145 | dependencies = (
146 | );
147 | name = Runner;
148 | productName = Runner;
149 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
150 | productType = "com.apple.product-type.application";
151 | };
152 | /* End PBXNativeTarget section */
153 |
154 | /* Begin PBXProject section */
155 | 97C146E61CF9000F007C117D /* Project object */ = {
156 | isa = PBXProject;
157 | attributes = {
158 | LastUpgradeCheck = 1010;
159 | ORGANIZATIONNAME = "The Chromium Authors";
160 | TargetAttributes = {
161 | 97C146ED1CF9000F007C117D = {
162 | CreatedOnToolsVersion = 7.3.1;
163 | DevelopmentTeam = HGUXFJ2W6S;
164 | };
165 | };
166 | };
167 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
168 | compatibilityVersion = "Xcode 3.2";
169 | developmentRegion = English;
170 | hasScannedForEncodings = 0;
171 | knownRegions = (
172 | en,
173 | Base,
174 | );
175 | mainGroup = 97C146E51CF9000F007C117D;
176 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
177 | projectDirPath = "";
178 | projectRoot = "";
179 | targets = (
180 | 97C146ED1CF9000F007C117D /* Runner */,
181 | );
182 | };
183 | /* End PBXProject section */
184 |
185 | /* Begin PBXResourcesBuildPhase section */
186 | 97C146EC1CF9000F007C117D /* Resources */ = {
187 | isa = PBXResourcesBuildPhase;
188 | buildActionMask = 2147483647;
189 | files = (
190 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
191 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
192 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
193 | 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */,
194 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
195 | );
196 | runOnlyForDeploymentPostprocessing = 0;
197 | };
198 | /* End PBXResourcesBuildPhase section */
199 |
200 | /* Begin PBXShellScriptBuildPhase section */
201 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
202 | isa = PBXShellScriptBuildPhase;
203 | buildActionMask = 2147483647;
204 | files = (
205 | );
206 | inputPaths = (
207 | );
208 | name = "Thin Binary";
209 | outputPaths = (
210 | );
211 | runOnlyForDeploymentPostprocessing = 0;
212 | shellPath = /bin/sh;
213 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
214 | };
215 | 9740EEB61CF901F6004384FC /* Run Script */ = {
216 | isa = PBXShellScriptBuildPhase;
217 | buildActionMask = 2147483647;
218 | files = (
219 | );
220 | inputPaths = (
221 | );
222 | name = "Run Script";
223 | outputPaths = (
224 | );
225 | runOnlyForDeploymentPostprocessing = 0;
226 | shellPath = /bin/sh;
227 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
228 | };
229 | /* End PBXShellScriptBuildPhase section */
230 |
231 | /* Begin PBXSourcesBuildPhase section */
232 | 97C146EA1CF9000F007C117D /* Sources */ = {
233 | isa = PBXSourcesBuildPhase;
234 | buildActionMask = 2147483647;
235 | files = (
236 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
237 | 97C146F31CF9000F007C117D /* main.m in Sources */,
238 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
239 | );
240 | runOnlyForDeploymentPostprocessing = 0;
241 | };
242 | /* End PBXSourcesBuildPhase section */
243 |
244 | /* Begin PBXVariantGroup section */
245 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
246 | isa = PBXVariantGroup;
247 | children = (
248 | 97C146FB1CF9000F007C117D /* Base */,
249 | 4BC6E22E21B8DEC7002DF9F4 /* zh */,
250 | );
251 | name = Main.storyboard;
252 | sourceTree = "";
253 | };
254 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
255 | isa = PBXVariantGroup;
256 | children = (
257 | 97C147001CF9000F007C117D /* Base */,
258 | 4BC6E22F21B8DEC7002DF9F4 /* zh */,
259 | );
260 | name = LaunchScreen.storyboard;
261 | sourceTree = "";
262 | };
263 | /* End PBXVariantGroup section */
264 |
265 | /* Begin XCBuildConfiguration section */
266 | 249021D3217E4FDB00AE95B9 /* Profile */ = {
267 | isa = XCBuildConfiguration;
268 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
269 | buildSettings = {
270 | ALWAYS_SEARCH_USER_PATHS = NO;
271 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
272 | CLANG_ANALYZER_NONNULL = YES;
273 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
274 | CLANG_CXX_LIBRARY = "libc++";
275 | CLANG_ENABLE_MODULES = YES;
276 | CLANG_ENABLE_OBJC_ARC = YES;
277 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
278 | CLANG_WARN_BOOL_CONVERSION = YES;
279 | CLANG_WARN_COMMA = YES;
280 | CLANG_WARN_CONSTANT_CONVERSION = YES;
281 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
282 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
283 | CLANG_WARN_EMPTY_BODY = YES;
284 | CLANG_WARN_ENUM_CONVERSION = YES;
285 | CLANG_WARN_INFINITE_RECURSION = YES;
286 | CLANG_WARN_INT_CONVERSION = YES;
287 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
288 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
289 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
290 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
291 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
292 | CLANG_WARN_STRICT_PROTOTYPES = YES;
293 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
294 | CLANG_WARN_UNREACHABLE_CODE = YES;
295 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
296 | CODE_SIGN_IDENTITY = "iPhone Developer";
297 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
298 | COPY_PHASE_STRIP = NO;
299 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
300 | ENABLE_NS_ASSERTIONS = NO;
301 | ENABLE_STRICT_OBJC_MSGSEND = YES;
302 | GCC_C_LANGUAGE_STANDARD = gnu99;
303 | GCC_NO_COMMON_BLOCKS = YES;
304 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
305 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
306 | GCC_WARN_UNDECLARED_SELECTOR = YES;
307 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
308 | GCC_WARN_UNUSED_FUNCTION = YES;
309 | GCC_WARN_UNUSED_VARIABLE = YES;
310 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
311 | MTL_ENABLE_DEBUG_INFO = NO;
312 | SDKROOT = iphoneos;
313 | TARGETED_DEVICE_FAMILY = "1,2";
314 | VALIDATE_PRODUCT = YES;
315 | };
316 | name = Profile;
317 | };
318 | 249021D4217E4FDB00AE95B9 /* Profile */ = {
319 | isa = XCBuildConfiguration;
320 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
321 | buildSettings = {
322 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
323 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
324 | DEVELOPMENT_TEAM = HGUXFJ2W6S;
325 | ENABLE_BITCODE = NO;
326 | FRAMEWORK_SEARCH_PATHS = (
327 | "$(inherited)",
328 | "$(PROJECT_DIR)/Flutter",
329 | );
330 | INFOPLIST_FILE = Runner/Info.plist;
331 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
332 | LIBRARY_SEARCH_PATHS = (
333 | "$(inherited)",
334 | "$(PROJECT_DIR)/Flutter",
335 | );
336 | PRODUCT_BUNDLE_IDENTIFIER = com.examplefew;
337 | PRODUCT_NAME = "$(TARGET_NAME)";
338 | VERSIONING_SYSTEM = "apple-generic";
339 | };
340 | name = Profile;
341 | };
342 | 97C147031CF9000F007C117D /* Debug */ = {
343 | isa = XCBuildConfiguration;
344 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
345 | buildSettings = {
346 | ALWAYS_SEARCH_USER_PATHS = NO;
347 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
348 | CLANG_ANALYZER_NONNULL = YES;
349 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
350 | CLANG_CXX_LIBRARY = "libc++";
351 | CLANG_ENABLE_MODULES = YES;
352 | CLANG_ENABLE_OBJC_ARC = YES;
353 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
354 | CLANG_WARN_BOOL_CONVERSION = YES;
355 | CLANG_WARN_COMMA = YES;
356 | CLANG_WARN_CONSTANT_CONVERSION = YES;
357 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
358 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
359 | CLANG_WARN_EMPTY_BODY = YES;
360 | CLANG_WARN_ENUM_CONVERSION = YES;
361 | CLANG_WARN_INFINITE_RECURSION = YES;
362 | CLANG_WARN_INT_CONVERSION = YES;
363 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
364 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
365 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
366 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
367 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
368 | CLANG_WARN_STRICT_PROTOTYPES = YES;
369 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
370 | CLANG_WARN_UNREACHABLE_CODE = YES;
371 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
372 | "CODE_SIGN_ENTITLEMENTS[sdk=*]" = "";
373 | CODE_SIGN_IDENTITY = "iPhone Developer";
374 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
375 | COPY_PHASE_STRIP = NO;
376 | DEBUG_INFORMATION_FORMAT = dwarf;
377 | "DEVELOPMENT_TEAM[sdk=*]" = "";
378 | ENABLE_STRICT_OBJC_MSGSEND = YES;
379 | ENABLE_TESTABILITY = YES;
380 | GCC_C_LANGUAGE_STANDARD = gnu99;
381 | GCC_DYNAMIC_NO_PIC = NO;
382 | GCC_NO_COMMON_BLOCKS = YES;
383 | GCC_OPTIMIZATION_LEVEL = 0;
384 | GCC_PREPROCESSOR_DEFINITIONS = (
385 | "DEBUG=1",
386 | "$(inherited)",
387 | );
388 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
389 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
390 | GCC_WARN_UNDECLARED_SELECTOR = YES;
391 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
392 | GCC_WARN_UNUSED_FUNCTION = YES;
393 | GCC_WARN_UNUSED_VARIABLE = YES;
394 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
395 | MTL_ENABLE_DEBUG_INFO = YES;
396 | ONLY_ACTIVE_ARCH = YES;
397 | SDKROOT = iphoneos;
398 | TARGETED_DEVICE_FAMILY = "1,2";
399 | };
400 | name = Debug;
401 | };
402 | 97C147041CF9000F007C117D /* Release */ = {
403 | isa = XCBuildConfiguration;
404 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
405 | buildSettings = {
406 | ALWAYS_SEARCH_USER_PATHS = NO;
407 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
408 | CLANG_ANALYZER_NONNULL = YES;
409 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
410 | CLANG_CXX_LIBRARY = "libc++";
411 | CLANG_ENABLE_MODULES = YES;
412 | CLANG_ENABLE_OBJC_ARC = YES;
413 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
414 | CLANG_WARN_BOOL_CONVERSION = YES;
415 | CLANG_WARN_COMMA = YES;
416 | CLANG_WARN_CONSTANT_CONVERSION = YES;
417 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
418 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
419 | CLANG_WARN_EMPTY_BODY = YES;
420 | CLANG_WARN_ENUM_CONVERSION = YES;
421 | CLANG_WARN_INFINITE_RECURSION = YES;
422 | CLANG_WARN_INT_CONVERSION = YES;
423 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
424 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
425 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
426 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
427 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
428 | CLANG_WARN_STRICT_PROTOTYPES = YES;
429 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
430 | CLANG_WARN_UNREACHABLE_CODE = YES;
431 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
432 | CODE_SIGN_IDENTITY = "iPhone Developer";
433 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
434 | COPY_PHASE_STRIP = NO;
435 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
436 | ENABLE_NS_ASSERTIONS = NO;
437 | ENABLE_STRICT_OBJC_MSGSEND = YES;
438 | GCC_C_LANGUAGE_STANDARD = gnu99;
439 | GCC_NO_COMMON_BLOCKS = YES;
440 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
441 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
442 | GCC_WARN_UNDECLARED_SELECTOR = YES;
443 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
444 | GCC_WARN_UNUSED_FUNCTION = YES;
445 | GCC_WARN_UNUSED_VARIABLE = YES;
446 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
447 | MTL_ENABLE_DEBUG_INFO = NO;
448 | SDKROOT = iphoneos;
449 | TARGETED_DEVICE_FAMILY = "1,2";
450 | VALIDATE_PRODUCT = YES;
451 | };
452 | name = Release;
453 | };
454 | 97C147061CF9000F007C117D /* Debug */ = {
455 | isa = XCBuildConfiguration;
456 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
457 | buildSettings = {
458 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
459 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
460 | DEVELOPMENT_TEAM = HGUXFJ2W6S;
461 | ENABLE_BITCODE = NO;
462 | FRAMEWORK_SEARCH_PATHS = (
463 | "$(inherited)",
464 | "$(PROJECT_DIR)/Flutter",
465 | );
466 | INFOPLIST_FILE = Runner/Info.plist;
467 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
468 | LIBRARY_SEARCH_PATHS = (
469 | "$(inherited)",
470 | "$(PROJECT_DIR)/Flutter",
471 | );
472 | PRODUCT_BUNDLE_IDENTIFIER = com.examplefew;
473 | PRODUCT_NAME = "$(TARGET_NAME)";
474 | VERSIONING_SYSTEM = "apple-generic";
475 | };
476 | name = Debug;
477 | };
478 | 97C147071CF9000F007C117D /* Release */ = {
479 | isa = XCBuildConfiguration;
480 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
481 | buildSettings = {
482 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
483 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
484 | DEVELOPMENT_TEAM = HGUXFJ2W6S;
485 | ENABLE_BITCODE = NO;
486 | FRAMEWORK_SEARCH_PATHS = (
487 | "$(inherited)",
488 | "$(PROJECT_DIR)/Flutter",
489 | );
490 | INFOPLIST_FILE = Runner/Info.plist;
491 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
492 | LIBRARY_SEARCH_PATHS = (
493 | "$(inherited)",
494 | "$(PROJECT_DIR)/Flutter",
495 | );
496 | PRODUCT_BUNDLE_IDENTIFIER = com.examplefew;
497 | PRODUCT_NAME = "$(TARGET_NAME)";
498 | VERSIONING_SYSTEM = "apple-generic";
499 | };
500 | name = Release;
501 | };
502 | /* End XCBuildConfiguration section */
503 |
504 | /* Begin XCConfigurationList section */
505 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
506 | isa = XCConfigurationList;
507 | buildConfigurations = (
508 | 97C147031CF9000F007C117D /* Debug */,
509 | 97C147041CF9000F007C117D /* Release */,
510 | 249021D3217E4FDB00AE95B9 /* Profile */,
511 | );
512 | defaultConfigurationIsVisible = 0;
513 | defaultConfigurationName = Debug;
514 | };
515 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
516 | isa = XCConfigurationList;
517 | buildConfigurations = (
518 | 97C147061CF9000F007C117D /* Debug */,
519 | 97C147071CF9000F007C117D /* Release */,
520 | 249021D4217E4FDB00AE95B9 /* Profile */,
521 | );
522 | defaultConfigurationIsVisible = 0;
523 | defaultConfigurationName = Debug;
524 | };
525 | /* End XCConfigurationList section */
526 | };
527 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
528 | }
529 |
--------------------------------------------------------------------------------
/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.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildSystemType
6 | Original
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/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/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/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/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/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/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/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/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/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/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/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/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/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/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/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/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/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/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/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/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/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/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/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/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/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/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/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/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/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/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/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/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 | en
7 | CFBundleDisplayName
8 | flutter
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | flutter_app
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(FLUTTER_BUILD_NUMBER)
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 | UIViewControllerBasedStatusBarAppearance
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/ios/Runner/zh.lproj/LaunchScreen.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/ios/Runner/zh.lproj/Main.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/lib/FlutterApp.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/widgets/FlutterTextWidget.dart';
3 | import 'package:flutter_app/widgets/FlutterContainer.dart';
4 | import 'package:flutter_app/widgets/FlutterAlign.dart';
5 | import 'package:flutter_app/widgets/FlutterRow.dart';
6 | import 'package:flutter_app/widgets/FlutterImage.dart';
7 | import 'package:flutter_app/widgets/FlutterRaisedButton.dart';
8 | import 'package:flutter_app/widgets/FlutterFloatingActionButton.dart';
9 | import 'package:flutter_app/widgets/FlutterFlatButton.dart';
10 | import 'package:flutter_app/widgets/FlutterIconButton.dart';
11 | import 'package:flutter_app/widgets/FlutterDropdownButton.dart';
12 | import 'package:flutter_app/widgets/FlutterPopupMenuButton.dart';
13 | import 'package:flutter_app/widgets/FlutterButtonBar.dart';
14 | import 'package:flutter_app/widgets/FlutterListView.dart';
15 | import 'package:flutter_app/widgets/FlutterGridView.dart';
16 | import 'package:flutter_app/projectDemo/DouBanDemo.dart';
17 | import 'package:flutter_app/test/ContainerTestWidget.dart';
18 | import 'package:flutter_app/widgets/FlutterCardWidget.dart';
19 | import 'package:flutter_app/router/FlutterRouterNewScreen.dart';
20 | class FlutterApp extends StatelessWidget {
21 | @override
22 | Widget build(BuildContext context) {
23 | return MaterialApp(
24 | title: "Flutter",
25 | theme: ThemeData(
26 | primarySwatch: Colors.blue,
27 | ),
28 | home: Scaffold(
29 | appBar: AppBar(
30 | title: Text('Flutter'),
31 | ),
32 | body: SafeArea(
33 | child: Container(
34 | child: DouBanListView(),
35 | alignment: Alignment.center,
36 | )),
37 | ),
38 | );
39 | }
40 | }
41 |
42 | class FlutterHomeApp extends StatelessWidget {
43 | @override
44 | Widget build(BuildContext context) {
45 | return Text(
46 | "Hello",
47 | textAlign: TextAlign.center,
48 | overflow: TextOverflow.ellipsis,
49 | style: TextStyle(fontWeight: FontWeight.bold),
50 | );
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/FlutterApp.dart';
3 | import 'package:flutter_app/widgets/FlutterPopupMenuButton.dart';
4 | import 'package:flutter_app/router/FlutterRouterNewScreen.dart';
5 | import 'package:flutter_app/router/FlutterHero.dart';
6 | import 'package:flutter_app/widgets/FlutterBottomNavigationBar.dart';
7 | import 'package:flutter_app/widgets/FlutterTabBar.dart';
8 | import 'package:flutter_app/widgets/FlutterStack.dart';
9 | import 'package:flutter_app/router/NamedRouter.dart';
10 | import 'package:flutter_app/widgets/scrollView/FlutterSliverToBoxAdapter.dart';
11 | import 'package:flutter_app/widgets/scrollView/FlutterCustomScrollView.dart';
12 | import 'package:flutter_app/widgets/scrollView/FlutterNestedScrollView.dart';
13 | import 'package:flutter_app/widgets/FlutterSliverAppBar.dart';
14 | import 'package:flutter_app/widgets/sliver/sliver_expanded_appbar.dart';
15 | import 'package:flutter_app/widgets/sliver/sliver_box.dart';
16 | import 'package:flutter_app/widgets/sliver/sliver_grid.dart';
17 | import 'package:flutter_app/widgets/sliver/sliver_header.dart';
18 | import 'package:flutter_app/widgets/sliver/sliver_list.dart';
19 | import 'package:flutter_app/widgets/sliver/sliver_menu.dart';
20 | import 'package:flutter_app/widgets/bottom_drag_widget.dart';
21 |
22 | void main() => runApp(MyApp());
23 | List urls = [
24 | 'http://img1.doubanio.com/view/photo/s_ratio_poster/public/p480747492.webp',
25 | 'http://img1.doubanio.com/view/photo/s_ratio_poster/public/p1910813120.webp',
26 | 'http://img1.doubanio.com/view/photo/s_ratio_poster/public/p511118051.webp',
27 | ];
28 |
29 | class MyApp extends StatelessWidget {
30 | // This widget is the root of your application.
31 | @override
32 | Widget build(BuildContext context) {
33 | return MaterialApp(
34 | title: 'Flutter Demo',
35 | // home: FlutterStack(urls: urls, w: 140.0,),
36 | home: Scaffold(body: Demo(),),
37 | );
38 | }
39 | }
40 |
41 |
42 | /// DragController controller = DragController();
43 | class Demo extends StatefulWidget {
44 | @override
45 | _DemoState createState() => _DemoState();
46 | }
47 |
48 | class _DemoState extends State {
49 | @override
50 | Widget build(BuildContext context) {
51 | return BottomDragWidget(
52 | body: Container(
53 | color: Colors.brown,
54 | child: ListView.builder(itemBuilder: (BuildContext context, int index){
55 | return Text('我是listview下面一层的东东,index=$index');
56 | }, itemCount: 100,),
57 | ),
58 | dragContainer: DragContainer(
59 | drawer: getListView(),
60 | defaultShowHeight: 150.0,
61 | height: 700.0,
62 | ));
63 | }
64 |
65 | Widget getListView() {
66 | return Container(
67 | height:600.0,
68 |
69 | ///总高度
70 | color: Colors.amberAccent,
71 | child: Column(
72 | children: [
73 | Container(
74 | color: Colors.deepOrangeAccent,
75 | height: 10.0,
76 | ),
77 | Expanded(child: newListView())
78 | ],
79 | ),
80 | );
81 | }
82 |
83 | Widget newListView() {
84 | return OverscrollNotificationWidget(
85 | child: ListView.builder(
86 | itemBuilder: (BuildContext context, int index) {
87 | return Text('data=$index');
88 | },
89 | itemCount: 100,
90 | ///这个属性是用来断定滚动的部件的物理特性,例如:
91 | ///scrollStart
92 | ///ScrollUpdate
93 | ///Overscroll
94 | ///ScrollEnd
95 | ///在Android和ios等平台,其默认值是不同的。我们可以在scroll_configuration.dart中看到如下配置
96 |
97 | ///下面代码是我在翻源码找到的解决方案
98 | /// The scroll physics to use for the platform given by [getPlatform].
99 | ///
100 | /// Defaults to [BouncingScrollPhysics] on iOS and [ClampingScrollPhysics] on
101 | /// Android.
102 | // ScrollPhysics getScrollPhysics(BuildContext context) {
103 | // switch (getPlatform(context)) {
104 | // case TargetPlatform.iOS:/*/
105 | // return const BouncingScrollPhysics();
106 | // case TargetPlatform.android:
107 | // case TargetPlatform.fuchsia:
108 | // return const ClampingScrollPhysics();
109 | // }
110 | // return null;
111 | // }
112 | ///在ios中,默认返回BouncingScrollPhysics,对于[BouncingScrollPhysics]而言,
113 | ///由于 double applyBoundaryConditions(ScrollMetrics position, double value) => 0.0;
114 | ///会导致:当listview的第一条目显示时,继续下拉时,不会调用上面提到的Overscroll监听。
115 | ///故这里,设定为[ClampingScrollPhysics]
116 | physics: const ClampingScrollPhysics(),
117 | ),
118 | );
119 | }
120 |
121 | }
122 |
123 | class MyHomePage extends StatefulWidget {
124 | MyHomePage({Key key, this.title}) : super(key: key);
125 | final String title;
126 |
127 | @override
128 | _MyHomePageState createState() => _MyHomePageState();
129 | }
130 |
131 | class _MyHomePageState extends State {
132 | int _counter = 0;
133 |
134 | void _incrementCounter() {
135 | setState(() {
136 | _counter++;
137 | });
138 | }
139 |
140 | @override
141 | Widget build(BuildContext context) {
142 | return Scaffold(
143 | appBar: AppBar(
144 | title: Text(widget.title),
145 | ),
146 | body: Center(
147 | child: Column(
148 | mainAxisAlignment: MainAxisAlignment.center,
149 | children: [
150 | Text(
151 | ' Hello You have pushed the button this many times:',
152 | ),
153 | Text(
154 | '$_counter',
155 | style: Theme.of(context).textTheme.display1,
156 | ),
157 | ],
158 | ),
159 | ),
160 | floatingActionButton: FloatingActionButton(
161 | onPressed: _incrementCounter,
162 | tooltip: 'Increment',
163 | child: Icon(Icons.add),
164 | ), // This trailing comma makes auto-formatting nicer for build methods.
165 | );
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/lib/projectDemo/DouBanDemo.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert' as Convert;
2 | import 'dart:io';
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter/cupertino.dart';
5 | import 'package:flutter_app/router/SendDataNewScreen.dart';
6 |
7 | class DouBanListView extends StatefulWidget {
8 | @override
9 | State createState() {
10 | return DouBanState();
11 | }
12 | }
13 |
14 | class DouBanState extends State with AutomaticKeepAliveClientMixin{
15 | var subjects = [];
16 |
17 | var itemHeight = 150.0;
18 |
19 | requestMovieTop() async {
20 | var httpClient = new HttpClient();
21 | //http://api.douban.com/v2/movie/top250?start=25&count=10
22 | var uri = new Uri.http(
23 | 'api.douban.com', '/v2/movie/top250', {'start': '0', 'count': '150'});
24 | var request = await httpClient.getUrl(uri);
25 | var response = await request.close();
26 | var responseBody = await response.transform(Convert.utf8.decoder).join();
27 | Map data = Convert.jsonDecode(responseBody);
28 | setState(() {
29 | subjects = data['subjects'];
30 | });
31 | }
32 |
33 | @override
34 | void initState() {
35 | super.initState();
36 | requestMovieTop();
37 | }
38 |
39 | @override
40 | Widget build(BuildContext context) {
41 | return Container(
42 | child: getListViewContainer(),
43 | );
44 | }
45 |
46 | getListViewContainer() {
47 | if (subjects.length == 0) {
48 | //loading
49 | return CupertinoActivityIndicator();
50 | }
51 | return ListView.builder(
52 | //item 的数量
53 | itemCount: subjects.length,
54 | itemBuilder: (BuildContext context, int index) {
55 | return GestureDetector(
56 | //Flutter 手势处理
57 | child: Container(
58 | color: Colors.transparent,
59 | child: Column(
60 | crossAxisAlignment: CrossAxisAlignment.start,
61 | children: [
62 | numberWidget(index + 1),
63 | getItemContainerView(subjects[index]),
64 | //下面的灰色分割线
65 | Container(
66 | height: 10,
67 | color: Color.fromARGB(255, 234, 233, 234),
68 | )
69 | ],
70 | ),
71 | ),
72 | onTap: () {
73 | //监听点击事件
74 | print("click item index=$index");
75 | //跳转到详情页面
76 | Navigator.push(
77 | context,
78 | MaterialPageRoute(
79 | builder: (context) => DouBanDetailScreen(
80 | subject: subjects[index],
81 | )));
82 | },
83 | );
84 | });
85 | }
86 |
87 | //肖申克的救赎(1993) View
88 | getTitleView(subject) {
89 | var title = subject['title'];
90 | var year = subject['year'];
91 | return Container(
92 | child: Row(
93 | children: [
94 | Icon(
95 | Icons.play_circle_outline,
96 | color: Colors.redAccent,
97 | ),
98 | Text(
99 | title,
100 | style: TextStyle(
101 | fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black),
102 | ),
103 | Text('($year)',
104 | style: TextStyle(
105 | fontSize: 16,
106 | fontWeight: FontWeight.bold,
107 | color: Colors.grey))
108 | ],
109 | ),
110 | );
111 | }
112 |
113 | getItemContainerView(var subject) {
114 | var imgUrl = subject['images']['medium'];
115 | return Container(
116 | width: double.infinity,
117 | padding: EdgeInsets.all(5.0),
118 | child: Row(
119 | children: [
120 | getImage(imgUrl),
121 | Expanded(
122 | child: getMovieInfoView(subject),
123 | flex: 1,
124 | )
125 | ],
126 | ),
127 | );
128 | }
129 |
130 | //圆角图片
131 | getImage(var imgUrl) {
132 | return Container(
133 | decoration: BoxDecoration(
134 | image:
135 | DecorationImage(image: NetworkImage(imgUrl), fit: BoxFit.cover),
136 | borderRadius: BorderRadius.all(Radius.circular(5.0))),
137 | margin: EdgeInsets.only(left: 8, top: 3, right: 8, bottom: 3),
138 | height: itemHeight,
139 | width: 100.0,
140 | );
141 | }
142 |
143 | getStaring(var stars) {
144 | return Row(
145 | children: [RatingBar(stars), Text('$stars')],
146 | );
147 | }
148 |
149 | //电影标题,星标评分,演员简介Container
150 | getMovieInfoView(var subject) {
151 | var start = subject['rating']['average'];
152 | return Container(
153 | height: itemHeight,
154 | alignment: Alignment.topLeft,
155 | child: Column(
156 | children: [
157 | getTitleView(subject),
158 | RatingBar(start),
159 | DescWidget(subject)
160 | ],
161 | ),
162 | );
163 | }
164 |
165 | //NO.1 图标
166 | numberWidget(var no) {
167 | return Container(
168 | child: Text(
169 | 'No.$no',
170 | style: TextStyle(color: Color.fromARGB(255, 133, 66, 0)),
171 | ),
172 | decoration: BoxDecoration(
173 | color: Color.fromARGB(255, 255, 201, 129),
174 | borderRadius: BorderRadius.all(Radius.circular(5.0))),
175 | padding: EdgeInsets.fromLTRB(8, 4, 8, 4),
176 | margin: EdgeInsets.only(left: 12, top: 10),
177 | );
178 | }
179 |
180 | //
181 | // Flutter中为了节约内存不会保存widget的状态,widget都是临时变量。当我们使用TabBar,TabBarView是我们就会发现,切换tab后再重新切换回上一页面,这时候tab会重新加载重新创建,体验很不友好。Flutter出于自己的设计考虑并没有延续android的ViewPager这样的缓存页面设计,毕竟控件两端都要开发,目前还在beta版本有很多设计还不够完善,但是设计的拓展性没得说,flutter还是为我们提供了解决办法。我们可以强制widget不显示情况下保留状态,下回再加载时就不用重新创建了。
182 | //
183 | // AutomaticKeepAliveClientMixin
184 | // AutomaticKeepAliveClientMixin 是一个抽象状态,使用也很简单,我们只需要用我们自己的状态继承这个抽象状态,并实现 wantKeepAlive 方法即可。
185 | //
186 | // 继承这个状态后,widget在不显示之后也不会被销毁仍然保存在内存中,所以慎重使用这个方法。
187 | // ---------------------
188 | // 作者:唯夜
189 | // 来源:CSDN
190 | // 原文:https://blog.csdn.net/tgbus18990140382/article/details/81181879
191 | // 版权声明:本文为博主原创文章,转载请附上博文链接!
192 |
193 |
194 | @override
195 | bool get wantKeepAlive => true;
196 | }
197 |
198 | //类别、演员介绍
199 | class DescWidget extends StatelessWidget {
200 | var subject;
201 |
202 | DescWidget(this.subject);
203 |
204 | @override
205 | Widget build(BuildContext context) {
206 | var casts = subject['casts'];
207 | var sb = StringBuffer();
208 | var genres = subject['genres'];
209 | for (var i = 0; i < genres.length; i++) {
210 | sb.write('${genres[i]} ');
211 | }
212 | sb.write("/ ");
213 | List list = List.generate(
214 | casts.length, (int index) => casts[index]['name'].toString());
215 |
216 | for (var i = 0; i < list.length; i++) {
217 | sb.write('${list[i]} ');
218 | }
219 | return Container(
220 | alignment: Alignment.topLeft,
221 | child: Text(
222 | sb.toString(),
223 | softWrap: true,
224 | textDirection: TextDirection.ltr,
225 | style:
226 | TextStyle(fontSize: 16, color: Color.fromARGB(255, 118, 117, 118)),
227 | ),
228 | );
229 | }
230 | }
231 |
232 | class RatingBar extends StatelessWidget {
233 | double stars;
234 |
235 | RatingBar(this.stars);
236 |
237 | @override
238 | Widget build(BuildContext context) {
239 | List startList = [];
240 | //实心星星
241 | var startNumber = stars ~/ 2;
242 | //半实心星星
243 | var startHalf = 0;
244 | if (stars.toString().contains('.')) {
245 | int tmp = int.parse((stars.toString().split('.')[1]));
246 | if (tmp >= 5) {
247 | startHalf = 1;
248 | }
249 | }
250 | //空心星星
251 | var startEmpty = 5 - startNumber - startHalf;
252 |
253 | for (var i = 0; i < startNumber; i++) {
254 | startList.add(Icon(
255 | Icons.star,
256 | color: Colors.amberAccent,
257 | size: 18,
258 | ));
259 | }
260 | if (startHalf > 0) {
261 | startList.add(Icon(
262 | Icons.star_half,
263 | color: Colors.amberAccent,
264 | size: 18,
265 | ));
266 | }
267 | for (var i = 0; i < startEmpty; i++) {
268 | startList.add(Icon(
269 | Icons.star_border,
270 | color: Colors.grey,
271 | size: 18,
272 | ));
273 | }
274 | startList.add(Text(
275 | '$stars',
276 | style: TextStyle(
277 | color: Colors.grey,
278 | ),
279 | ));
280 | return Container(
281 | alignment: Alignment.topLeft,
282 | padding: const EdgeInsets.only(left: 0, top: 8, right: 0, bottom: 5),
283 | child: Row(
284 | children: startList,
285 | ),
286 | );
287 | }
288 | }
289 |
--------------------------------------------------------------------------------
/lib/projectDemo/pages/GroupPage.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class GroupPage extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) {
6 | return Text('GroupPage');
7 | }
8 | }
--------------------------------------------------------------------------------
/lib/projectDemo/pages/MoviePage.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class MoviePage extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) {
6 | return Text('MoviePage');
7 | }
8 | }
--------------------------------------------------------------------------------
/lib/projectDemo/pages/PersonPage.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class PersonPage extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) {
6 | return Text('PersonPage');
7 | }
8 | }
--------------------------------------------------------------------------------
/lib/projectDemo/pages/ShopPage.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class ShopPage extends StatelessWidget {
4 |
5 | @override
6 | Widget build(BuildContext context) {
7 | return Text('ShopPage');
8 | }
9 |
10 | }
--------------------------------------------------------------------------------
/lib/router/FlutterHero.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 |
4 | class HeroApp extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return MaterialApp(
8 | title: 'Transition Demo',
9 | home: MainScreen(),
10 | );
11 | }
12 | }
13 |
14 | class MainScreen extends StatelessWidget {
15 | @override
16 | Widget build(BuildContext context) {
17 | return Scaffold(
18 | appBar: AppBar(
19 | title: Text('Main Screen'),
20 | ),
21 | body: GestureDetector(
22 | child: Hero(
23 | tag: 'imageHero',
24 | child: Image.network(
25 | 'https://picsum.photos/250?image=9',
26 | ),
27 | ),
28 | onTap: () {
29 | Navigator.push(context, MaterialPageRoute(builder: (_) {
30 | return DetailScreen();
31 | }));
32 | },
33 | ),
34 | );
35 | }
36 | }
37 |
38 | class DetailScreen extends StatelessWidget {
39 | @override
40 | Widget build(BuildContext context) {
41 | return Scaffold(
42 | body: GestureDetector(
43 | child: Center(
44 | child: Hero(
45 | tag: 'imageHero',
46 | child: Image.network(
47 | 'https://picsum.photos/250?image=9',
48 | ),
49 | ),
50 | ),
51 | onTap: () {
52 | Navigator.pop(context);
53 | },
54 | ),
55 | );
56 | }
57 | }
--------------------------------------------------------------------------------
/lib/router/FlutterRouterNewScreen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/cupertino.dart';
3 |
4 | class FirstPage extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return Scaffold(
8 | appBar: AppBar(
9 | title: Text('FirstPage'),
10 | ),
11 | body: SafeArea(
12 | child: RaisedButton(
13 | child: Text("Navigator.push SecondPage"),
14 | onPressed: () {
15 | _navigateSecondPage(context);
16 | })),
17 | );
18 | }
19 |
20 | // void _navigateSecondPage(BuildContext context) {
21 | // //MaterialPageRoute({
22 | // // @required this.builder,
23 | // // RouteSettings settings,
24 | // // this.maintainState = true,
25 | // // bool fullscreenDialog = false,
26 | // // })
27 | // Navigator.push(context, MaterialPageRoute(builder: (context) {
28 | // return SecondPage(value: '我是FirstPage带来的数据');
29 | // }));
30 | // }
31 |
32 | /// async关键字声明该函数内部有代码需要延迟执行
33 | /// 使用await会把延迟运算放入到延迟运算的队列(await)中。
34 | void _navigateSecondPage(BuildContext context) async {
35 | print('执行了_navigateSecondPage');
36 | final result =
37 | await Navigator.push(context, MaterialPageRoute(builder: (context) {
38 | return SecondPage();
39 | }));
40 | print('FirstPage收到数据:$result');
41 | }
42 | }
43 |
44 | class SecondPage extends StatelessWidget {
45 |
46 |
47 | @override
48 | Widget build(BuildContext context) {
49 | return Scaffold(
50 | appBar: AppBar(
51 | title: Text('SecondPage'),
52 | ),
53 | body: SafeArea(
54 | child: RaisedButton(
55 | child: Text("返回数据到FirstPage"),
56 | onPressed: () {
57 | _backCurrentPage(context);
58 | })),
59 | );
60 | }
61 | }
62 |
63 | ///退出当前页面,返回到上一级页面
64 | void _backCurrentPage(BuildContext context) {
65 | print('执行了_backCurrentPage');
66 | ///只有执行了这个方法,上级页面才会收到返回的数据
67 | Navigator.pop(context, '我是来自SecondPage的数据');
68 | }
69 |
70 |
--------------------------------------------------------------------------------
/lib/router/NamedRouter.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class NamedRouter {
4 | static Map routes;
5 |
6 | static Widget initApp() {
7 | return MaterialApp(
8 | initialRoute: '/',
9 | title: 'Named-Router',
10 | routes: NamedRouter.initRoutes(),
11 | );
12 | }
13 |
14 | static initRoutes() {
15 | routes = {
16 | '/': (context) => FirstScreen(),
17 | '/second': (context) => SecondScreen()
18 | };
19 | return routes;
20 | }
21 |
22 |
23 | }
24 |
25 | class FirstScreen extends StatelessWidget {
26 | @override
27 | Widget build(BuildContext context) {
28 | return Scaffold(
29 | appBar: AppBar(
30 | title: Text('First Screen'),
31 | ),
32 | body: Center(
33 | child: RaisedButton(
34 | child: Text('Launch screen'),
35 | onPressed: () {
36 | // Navigate to the second screen using a named route
37 | Navigator.pushNamed(context, '/second');
38 | },
39 | ),
40 | ),
41 | );
42 | }
43 | }
44 |
45 | class SecondScreen extends StatelessWidget {
46 | @override
47 | Widget build(BuildContext context) {
48 | return Scaffold(
49 | appBar: AppBar(
50 | title: Text("Second Screen"),
51 | ),
52 | body: Center(
53 | child: RaisedButton(
54 | onPressed: () {
55 | // Navigate back to the first screen by popping the current route
56 | // off the stack
57 | Navigator.pop(context);
58 | },
59 | child: Text('Go back!'),
60 | ),
61 | ),
62 | );
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/lib/router/SendDataNewScreen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'package:flutter_app/projectDemo/DouBanDemo.dart';
4 |
5 | class DouBanDetailScreen extends StatelessWidget {
6 | var subject;
7 |
8 | DouBanDetailScreen({Key key, @required this.subject}) : super(key: key);
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return getItemContainerView(subject);
13 | }
14 |
15 | getItemContainerView(var subject) {
16 | var imgUrl = subject['images']['large'];
17 | return Container(
18 | color: Color.fromARGB(245, 255, 255, 255),
19 | alignment: Alignment.center,
20 | padding: EdgeInsets.all(10),
21 | child: Card(
22 | elevation: 10.0,
23 | child: Column(
24 | //横向包裹
25 | mainAxisSize: MainAxisSize.min,
26 | children: [
27 | Container(
28 | child: Image.network(imgUrl),
29 | padding: EdgeInsets.only(
30 | top: 10,
31 | bottom: 10,
32 | ),
33 | ),
34 | Container(
35 | padding: EdgeInsets.only(bottom: 10, left: 10, right: 10),
36 | child: DescWidget(subject),
37 | )
38 | ],
39 | ),
40 | ),
41 | );
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/sharedelement/README.md:
--------------------------------------------------------------------------------
1 | # flutter_shared_element
2 |
3 | #### Hero
4 |
5 | 教程:[谈一谈Flutter中的共享元素动画Hero](https://www.jianshu.com/p/ddb484789883)
6 |
7 | 效果图:
8 |
9 | 
--------------------------------------------------------------------------------
/lib/sharedelement/custom_flow_delegate.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class CustomFlowDelegate extends FlowDelegate {
4 | EdgeInsets margin = EdgeInsets.zero;
5 |
6 | CustomFlowDelegate({this.margin});
7 | @override
8 | void paintChildren(FlowPaintingContext context) {
9 | var x = margin.left;
10 | var y = margin.top;
11 | for (int i = 0; i < context.childCount; i++) {
12 | var w = context.getChildSize(i).width + x + margin.right;
13 | if (w < context.size.width) {
14 | context.paintChild(i,
15 | transform: new Matrix4.translationValues(
16 | x, y, 0.0));
17 | x = w + margin.left;
18 | } else {
19 | x = margin.left;
20 | y += context.getChildSize(i).height + margin.top + margin.bottom;
21 | context.paintChild(i,
22 | transform: new Matrix4.translationValues(
23 | x, y, 0.0));
24 | x += context.getChildSize(i).width + margin.left + margin.right;
25 | }
26 | }
27 | }
28 |
29 | @override
30 | bool shouldRepaint(FlowDelegate oldDelegate) {
31 | return oldDelegate != this;
32 | }
33 | }
--------------------------------------------------------------------------------
/lib/sharedelement/product_detail.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/sharedelement/product_list.dart';
3 |
4 | class ProductDetailPage extends StatefulWidget {
5 | final ProductItem product;
6 |
7 | const ProductDetailPage({Key key, this.product}) : super(key: key);
8 |
9 | @override
10 | State createState() => _ProductDetailState();
11 | }
12 |
13 | class _ProductDetailState extends State {
14 | @override
15 | Widget build(BuildContext context) {
16 | return Scaffold(
17 | appBar: AppBar(
18 | title: Text(widget.product.name),
19 | ),
20 | body: Column(children: [
21 | _buildProduct(),
22 | ]),
23 | );
24 | }
25 |
26 | Widget _buildProduct() {
27 | return Hero(
28 | tag: widget.product.tag,
29 | child: Container(
30 | padding: EdgeInsets.only(left: 15.0, right: 15.0),
31 | height: 120.0,
32 | child: Row(
33 | children: [
34 | Card(
35 | child: ClipRRect(
36 | child: SizedBox(
37 | width: 60.0,
38 | height: 60.0,
39 | child: Image.asset(
40 | widget.product.asset,
41 | fit: BoxFit.cover,
42 | ),
43 | ),
44 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
45 | ),
46 | ),
47 | Expanded(
48 | child: Column(
49 | mainAxisAlignment: MainAxisAlignment.center,
50 | crossAxisAlignment: CrossAxisAlignment.start,
51 | children: [
52 | Text(
53 | widget.product.name,
54 | style: Theme.of(context).textTheme.title,
55 | ),
56 | Row(
57 | children: [
58 | Expanded(child: Text(
59 | '4 items',
60 | style: Theme.of(context).textTheme.body1.copyWith(
61 | color: Colors.black26,
62 | ),
63 | )),
64 | Text(
65 | '\$${widget.product.price}',
66 | style: Theme.of(context).textTheme.title,
67 | )
68 | ],
69 | ),
70 | ],
71 | ))
72 | ],
73 | )),
74 | );
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/lib/sharedelement/product_list.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/sharedelement/product_detail.dart';
3 |
4 | class ProductItem {
5 | final String name;
6 | final String tag;
7 | final String asset;
8 | final int stock;
9 | final double price;
10 |
11 | ProductItem({
12 | this.name,
13 | this.tag,
14 | this.asset,
15 | this.stock,
16 | this.price,
17 | });
18 | }
19 |
20 | final List products = [
21 | ProductItem(
22 | name: 'Bueno Chocolate',
23 | tag: '1',
24 | asset: 'assets/images/food01.jpeg',
25 | stock: 1,
26 | price: 71.0),
27 | ProductItem(
28 | name: 'Chocolate with berries',
29 | tag: '2',
30 | asset: 'assets/images/food02.jpeg',
31 | stock: 1,
32 | price: 71.0),
33 | ProductItem(
34 | name: 'Trumoo Candies',
35 | tag: '3',
36 | asset: 'assets/images/food03.jpeg',
37 | stock: 1,
38 | price: 71.0),
39 | ProductItem(
40 | name: 'Choco-coko',
41 | tag: '4',
42 | asset: 'assets/images/food04.jpeg',
43 | stock: 1,
44 | price: 71.0),
45 | ProductItem(
46 | name: 'Chocolate tree',
47 | tag: '5',
48 | asset: 'assets/images/food05.jpeg',
49 | stock: 1,
50 | price: 71.0),
51 | ProductItem(
52 | name: 'Chocolate',
53 | tag: '6',
54 | asset: 'assets/images/food06.jpeg',
55 | stock: 1,
56 | price: 71.0),
57 | ProductItem(
58 | name: 'Chocolate with berries',
59 | tag: '2',
60 | asset: 'assets/images/food02.jpeg',
61 | stock: 1,
62 | price: 71.0),
63 | ProductItem(
64 | name: 'Trumoo Candies',
65 | tag: '3',
66 | asset: 'assets/images/food03.jpeg',
67 | stock: 1,
68 | price: 71.0),
69 | ProductItem(
70 | name: 'Choco-coko',
71 | tag: '4',
72 | asset: 'assets/images/food04.jpeg',
73 | stock: 1,
74 | price: 71.0),
75 | ProductItem(
76 | name: 'Chocolate tree',
77 | tag: '5',
78 | asset: 'assets/images/food05.jpeg',
79 | stock: 1,
80 | price: 71.0),
81 | ProductItem(
82 | name: 'Chocolate',
83 | tag: '6',
84 | asset: 'assets/images/food06.jpeg',
85 | stock: 1,
86 | price: 71.0),
87 | ];
88 |
89 | class ProductListPage extends StatefulWidget {
90 | final String title;
91 |
92 | const ProductListPage({Key key, this.title}) : super(key: key);
93 |
94 | @override
95 | State createState() => _ProductListState();
96 | }
97 |
98 | class _ProductListState extends State {
99 | Widget _buildSearch() {
100 | return Hero(
101 | tag: 'search',
102 | child: Card(
103 | margin: EdgeInsets.fromLTRB(15.0, 10.0, 15.0, 10.0),
104 | elevation: 8.0,
105 | shape: RoundedRectangleBorder(
106 | borderRadius: BorderRadius.all(Radius.circular(50.0)),
107 | ),
108 | child: Container(
109 | padding: EdgeInsets.only(left: 25.0, right: 25.0),
110 | height: 45.0,
111 | child: Center(
112 | child: Row(
113 | children: [
114 | Padding(
115 | padding: EdgeInsets.only(right: 8.0),
116 | child: Icon(
117 | Icons.search,
118 | color: Colors.black26,
119 | size: 20.0,
120 | ),
121 | ),
122 | Expanded(
123 | child: TextField(
124 | keyboardType: TextInputType.text,
125 | decoration: InputDecoration(
126 | border: InputBorder.none,
127 | hintText: 'Search category',
128 | hintStyle: TextStyle(color: Colors.black26)),
129 | cursorColor: Theme.of(this.context).accentColor,
130 | ))
131 | ],
132 | ),
133 | ),
134 | ),
135 | ));
136 | }
137 |
138 | Widget _buildProduct(ProductItem product) {
139 | var width = MediaQuery.of(context).size.width;
140 | return Hero(
141 | tag: product.tag,
142 | child: Container(
143 | height: 120.0,
144 | margin: EdgeInsets.fromLTRB(15.0, 5.0, 15.0, 5.0),
145 | child: Stack(
146 | alignment: AlignmentDirectional.centerStart,
147 | children: [
148 | Positioned(
149 | left: 20.0,
150 | child: Card(
151 | child: Container(
152 | width: width - 15.0 * 2 - 20.0 - 50.0,
153 | margin: EdgeInsets.only(left: 50.0),
154 | child: Row(
155 | children: [
156 | Expanded(
157 | child: Column(
158 | crossAxisAlignment: CrossAxisAlignment.start,
159 | children: [
160 | Text(
161 | product.name,
162 | style: Theme.of(context).textTheme.title,
163 | ),
164 | Padding(
165 | padding: EdgeInsets.only(top: 8.0),
166 | child: Text(
167 | '${product.stock} Unit',
168 | style: TextStyle(color: Colors.black26),
169 | ),
170 | ),
171 | ],
172 | ),
173 | ),
174 | Container(
175 | height: 60.0,
176 | width: 1.0,
177 | color: Colors.black12,
178 | ),
179 | Expanded(
180 | child: Column(
181 | children: [
182 | Padding(
183 | padding: EdgeInsets.only(top: 8.0),
184 | child: Text(
185 | '\$${product.price}',
186 | style: TextStyle(fontSize: 25.0),
187 | ),
188 | ),
189 | Padding(
190 | padding: EdgeInsets.only(top: 8.0),
191 | child: Text(
192 | 'PRICE',
193 | style: TextStyle(color: Colors.black26),
194 | ),
195 | ),
196 | MaterialButton(
197 | height: 30.0,
198 | child: Text('BUY'),
199 | onPressed: () {
200 | Navigator.of(context).push(
201 | PageRouteBuilder(
202 | pageBuilder: (context, _, __) {
203 | return ProductDetailPage(
204 | product: product,
205 | );
206 | },
207 | transitionDuration:
208 | const Duration(milliseconds: 500),
209 | transitionsBuilder:
210 | (_, animation, __, child) {
211 | return FadeTransition(
212 | opacity: animation,
213 | child: FadeTransition(
214 | opacity:
215 | Tween(begin: 0.5, end: 1.0)
216 | .animate(animation),
217 | child: child,
218 | ),
219 | );
220 | }),
221 | );
222 | },
223 | color: Colors.deepPurpleAccent,
224 | textColor: Colors.white,
225 | )
226 | ],
227 | ),
228 | ),
229 | ],
230 | ),
231 | ),
232 | )),
233 | ClipRRect(
234 | child: SizedBox(
235 | width: 70.0,
236 | height: 70.0,
237 | child: Image.asset(
238 | product.asset,
239 | fit: BoxFit.cover,
240 | ),
241 | ),
242 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
243 | ),
244 | ],
245 | ),
246 | ),
247 | );
248 | }
249 |
250 | @override
251 | Widget build(BuildContext context) {
252 | return Scaffold(
253 | appBar: AppBar(
254 | title: Text(widget.title),
255 | ),
256 | body: Column(
257 | children: [
258 | _buildSearch(),
259 | Expanded(
260 | child: ListView.builder(
261 | itemCount: products.length,
262 | itemBuilder: (BuildContext context, int index) {
263 | return _buildProduct(products[index]);
264 | }),
265 | )
266 | ],
267 | ),
268 | );
269 | }
270 | }
271 |
--------------------------------------------------------------------------------
/lib/sharedelement/shared_element_shop.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/sharedelement/product_list.dart';
3 |
4 | class _CategoryItem {
5 | final String category;
6 | final String tag;
7 | final String asset;
8 |
9 | _CategoryItem({this.category, this.tag, this.asset});
10 | }
11 |
12 | final List<_CategoryItem> categories = [
13 | _CategoryItem(category: 'Pasta', tag: 'pasta', asset: 'images/food01.jpeg'),
14 | _CategoryItem(category: 'Fruits', tag: 'fruits', asset: 'images/food02.jpeg'),
15 | _CategoryItem(category: 'Sweets', tag: 'sweets', asset: 'images/food03.jpeg'),
16 | _CategoryItem(
17 | category: 'Seafood', tag: 'seafood', asset: 'images/food04.jpeg'),
18 | _CategoryItem(category: 'Nuts', tag: 'nuts', asset: 'images/food05.jpeg'),
19 | _CategoryItem(
20 | category: 'Vegetables', tag: 'vegetables', asset: 'images/food06.jpeg'),
21 | ];
22 |
23 | class ShopPage extends StatefulWidget {
24 | @override
25 | State createState() => _ShopState();
26 | }
27 |
28 | class _ShopState extends State {
29 | List<_CategoryItem> showCategories = categories;
30 |
31 | @override
32 | Widget build(BuildContext context) {
33 | return Scaffold(
34 | appBar: AppBar(
35 | title: Text('SharedElementTransition'),
36 | ),
37 | body: CustomScrollView(
38 | physics: ScrollPhysics(),
39 | slivers: [
40 | SliverToBoxAdapter(
41 | child: Column(
42 | children: [
43 | _buildHeader(),
44 | _buildSearch(),
45 | _buildCategoryTitle(),
46 | ],
47 | ),
48 | ),
49 | _buildCategory(),
50 | ],
51 | ),
52 | );
53 | }
54 |
55 | Widget _buildCategory() {
56 | return SliverGrid.count(
57 | crossAxisCount: 2,
58 | mainAxisSpacing: 4.0,
59 | crossAxisSpacing: 4.0,
60 | childAspectRatio: 1.0,
61 | children: showCategories.map((category) {
62 | return GestureDetector(
63 | behavior: HitTestBehavior.translucent,
64 | onTap: () {
65 | Navigator.of(context).push(
66 | PageRouteBuilder(
67 | pageBuilder: (context, _, __) {
68 | return ProductListPage(
69 | title: category.category,
70 | );
71 | },
72 | transitionDuration: const Duration(milliseconds: 500),
73 | transitionsBuilder: (_, animation, __, child) {
74 | return FadeTransition(
75 | opacity: animation,
76 | child: FadeTransition(
77 | opacity: Tween(begin: 0.5, end: 1.0).animate(animation),
78 | child: child,
79 | ),
80 | );
81 | }),
82 | );
83 | },
84 | child: Card(
85 | child: Container(
86 | height: 120.0,
87 | padding: EdgeInsets.all(10.0),
88 | child: Column(
89 | mainAxisAlignment: MainAxisAlignment.center,
90 | children: [
91 | ClipRRect(
92 | child: SizedBox(
93 | width: 100.0,
94 | height: 100.0,
95 | child: Image.asset(
96 | category.asset,
97 | fit: BoxFit.cover,
98 | ),
99 | ),
100 | borderRadius: BorderRadius.all(Radius.circular(10.0)),
101 | ),
102 | Padding(
103 | padding: EdgeInsets.only(top: 8.0),
104 | child: Text(category.category),
105 | ),
106 | ],
107 | ),
108 | ),
109 | ),
110 | );
111 | }).toList(),
112 | );
113 | }
114 |
115 | void _doSearch(String search) {
116 | showCategories = categories
117 | .where((_CategoryItem category) =>
118 | category.category.toLowerCase().contains(search.toLowerCase()))
119 | .toList();
120 | setState(() {});
121 | }
122 |
123 | Widget _buildCategoryTitle() {
124 | return Padding(
125 | padding: EdgeInsets.all(15.0),
126 | child: Row(
127 | children: [
128 | Expanded(
129 | child: Text(
130 | 'Categories',
131 | style: Theme.of(context).textTheme.title,
132 | )),
133 | Text('${categories.length}'),
134 | ],
135 | ),
136 | );
137 | }
138 |
139 | Widget _buildSearch() {
140 | return Hero(
141 | tag: 'search',
142 | child: Card(
143 | margin: EdgeInsets.fromLTRB(15.0, 10.0, 15.0, 10.0),
144 | elevation: 8.0,
145 | shape: RoundedRectangleBorder(
146 | borderRadius: BorderRadius.all(Radius.circular(50.0)),
147 | ),
148 | child: Container(
149 | padding: EdgeInsets.only(left: 25.0, right: 25.0),
150 | height: 45.0,
151 | child: Center(
152 | child: Row(
153 | children: [
154 | Padding(
155 | padding: EdgeInsets.only(right: 8.0),
156 | child: Icon(
157 | Icons.search,
158 | color: Colors.black26,
159 | size: 20.0,
160 | ),
161 | ),
162 | Expanded(
163 | child: TextField(
164 | keyboardType: TextInputType.text,
165 | decoration: InputDecoration(
166 | border: InputBorder.none,
167 | hintText: 'Search category',
168 | hintStyle: TextStyle(color: Colors.black26)),
169 | cursorColor: Theme.of(this.context).accentColor,
170 | onChanged: (value) {
171 | _doSearch(value);
172 | },
173 | ))
174 | ],
175 | ),
176 | ),
177 | ),
178 | ));
179 | }
180 |
181 | Widget _buildHeader() {
182 | return Container(
183 | padding: EdgeInsets.all(15.0),
184 | height: 100.0,
185 | child: Row(
186 | children: [
187 | Expanded(
188 | child: Column(
189 | mainAxisAlignment: MainAxisAlignment.center,
190 | crossAxisAlignment: CrossAxisAlignment.start,
191 | children: [
192 | Text(
193 | 'Yumi Store',
194 | style: Theme.of(this.context).textTheme.title,
195 | ),
196 | Padding(
197 | padding: EdgeInsets.only(top: 6.0),
198 | child: Row(
199 | children: [
200 | Icon(
201 | Icons.favorite_border,
202 | color: Colors.black26,
203 | size: 12.0,
204 | ),
205 | Padding(
206 | padding: EdgeInsets.only(left: 4.0),
207 | child: Text(
208 | '0 items',
209 | style: TextStyle(color: Colors.black26),
210 | ),
211 | )
212 | ],
213 | ),
214 | ),
215 | ],
216 | ),
217 | ),
218 | ClipRRect(
219 | child: SizedBox(
220 | width: 60.0,
221 | height: 60.0,
222 | child: Image.asset(
223 | 'images/shop.jpeg',
224 | fit: BoxFit.cover,
225 | ),
226 | ),
227 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
228 | )
229 | ],
230 | ),
231 | );
232 | }
233 | }
234 |
--------------------------------------------------------------------------------
/lib/sharedelement/shared_element_transition.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'dart:math' as math;
3 |
4 | import 'package:flutter_app/sharedelement/custom_flow_delegate.dart';
5 |
6 | class _MenuData {
7 | const _MenuData({
8 | this.width,
9 | this.height,
10 | this.title,
11 | this.icon,
12 | this.flutterLogo,
13 | });
14 |
15 | final double width;
16 | final double height;
17 | final String title;
18 | final IconData icon;
19 | final FlutterLogo flutterLogo;
20 | }
21 |
22 | final List<_MenuData> menus = [
23 | const _MenuData(
24 | width: 100.0,
25 | height: 100.0,
26 | title: 'Music',
27 | icon: Icons.audiotrack,
28 | ),
29 | const _MenuData(
30 | width: 120.0,
31 | height: 150.0,
32 | title: 'Transition',
33 | icon: Icons.transform,
34 | flutterLogo: FlutterLogo(
35 | colors: Colors.cyan,
36 | size: 60.0,
37 | ),
38 | ),
39 | const _MenuData(
40 | width: 120.0,
41 | height: 150.0,
42 | title: 'Photo',
43 | icon: Icons.photo,
44 | flutterLogo: FlutterLogo(
45 | colors: Colors.orange,
46 | size: 60.0,
47 | ),
48 | ),
49 | const _MenuData(
50 | width: 100.0,
51 | height: 100.0,
52 | title: 'Alarm',
53 | icon: Icons.access_alarm,
54 | ),
55 | const _MenuData(
56 | width: 100.0,
57 | height: 100.0,
58 | title: 'Access',
59 | icon: Icons.beach_access,
60 | ),
61 | const _MenuData(
62 | width: 120.0,
63 | height: 150.0,
64 | title: 'Call',
65 | icon: Icons.call,
66 | flutterLogo: FlutterLogo(
67 | colors: Colors.lightGreen,
68 | size: 60.0,
69 | ),
70 | ),
71 | ];
72 |
73 | class _MenuDataItem extends StatelessWidget {
74 | const _MenuDataItem(this.data);
75 |
76 | final _MenuData data;
77 |
78 | @override
79 | Widget build(BuildContext context) {
80 | print('width:${data.width}');
81 | return GestureDetector(
82 | behavior: HitTestBehavior.translucent,
83 | onTap: () {
84 | Navigator.of(context).push(MaterialPageRoute(builder: (_) {
85 | return ElementDetailPage(
86 | data: data,
87 | );
88 | }));
89 | },
90 | child: Container(
91 | width: data.width,
92 | height: data.height,
93 | margin: EdgeInsets.fromLTRB(10.0, 4.0, 10.0, 4.0),
94 | child: Card(
95 | child: Padding(
96 | padding: const EdgeInsets.all(16.0),
97 | child: Column(
98 | crossAxisAlignment: CrossAxisAlignment.stretch,
99 | mainAxisAlignment: MainAxisAlignment.center,
100 | children: [
101 | Hero(
102 | createRectTween: (Rect begin, Rect end) {
103 | return RectTween(
104 | begin: Rect.fromLTRB(
105 | begin.left, begin.top, begin.right, begin.bottom),
106 | end: Rect.fromLTRB(end.left, end.top, end.right, end.bottom),
107 | );
108 | },
109 | tag: data.title,
110 | child: Padding(
111 | padding: EdgeInsets.only(right: 10.0),
112 | child: data.flutterLogo == null
113 | ? Icon(
114 | data.icon,
115 | color: Theme.of(context).accentColor,
116 | )
117 | : data.flutterLogo,
118 | )),
119 | Expanded(
120 | child: Padding(
121 | padding: EdgeInsets.only(top: 10.0),
122 | child: Text(
123 | data.title,
124 | style: Theme.of(context).textTheme.body1,
125 | ),
126 | ),
127 | ),
128 | ],
129 | ),
130 | ),
131 | ),
132 | ),
133 | );
134 | }
135 | }
136 |
137 | class ElementDetailPage extends StatelessWidget {
138 |
139 | final _MenuData data;
140 |
141 | ElementDetailPage({Key key, this.data}) : super(key: key);
142 |
143 | @override
144 | Widget build(BuildContext context) {
145 | return Material(
146 | child: Column(
147 | children: [
148 | Expanded(
149 | child: Hero(
150 | createRectTween: (Rect begin, Rect end) {
151 | return RectTween(
152 | begin: Rect.fromLTRB(
153 | begin.left, begin.top, begin.right, begin.bottom),
154 | end: Rect.fromLTRB(end.left, end.top, end.right, end.bottom),
155 | );
156 | },
157 | tag: data.title,
158 | child: data.flutterLogo == null
159 | ? Icon(
160 | data.icon,
161 | color: Theme.of(context).accentColor,
162 | size: 100.0,
163 | )
164 | : FlutterLogo(
165 | size: 200.0,
166 | colors: data.flutterLogo.colors,
167 | ),
168 | )),
169 | Padding(
170 | padding: EdgeInsets.only(bottom: 40.0),
171 | child: Text(
172 | 'This is icon ${data.title}',
173 | style: Theme.of(context).textTheme.title,
174 | ),
175 | ),
176 | ],
177 | ),
178 | );
179 | }
180 | }
181 |
182 | class SharedElementPage extends StatelessWidget {
183 | @override
184 | Widget build(BuildContext context) {
185 | return Scaffold(
186 | appBar: AppBar(
187 | title: Text('SharedElementTransition'),
188 | ),
189 | body: Flow(
190 | delegate: CustomFlowDelegate(
191 | margin: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 10.0)),
192 | children: menus.map((menu) {
193 | return _MenuDataItem(menu);
194 | }).toList(),
195 | ),
196 | );
197 | }
198 | }
199 |
--------------------------------------------------------------------------------
/lib/test/ContainerTestWidget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class ContainerTestWidget extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) {
6 | return Container(
7 | color: Colors.deepPurple,
8 | height: 500,
9 | child: Column(
10 | mainAxisAlignment: MainAxisAlignment.center,
11 | children: [
12 | Text("test"),
13 | Container(
14 | color: Colors.cyan,
15 | height: 200,
16 | child: Text('fjewiofj'),
17 | )
18 | ],
19 | ),
20 | );
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterAlign.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class FlutterAlign extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) {
6 | return Align(
7 | alignment: Alignment(-1, 1),
8 | child: Container(
9 | child: Text(
10 | "Hello",
11 | ),
12 | ),
13 | );
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterBottomNavigationBar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/widgets/FlutterTabBar.dart';
3 | import 'package:flutter_app/projectDemo/pages/GroupPage.dart';
4 | import 'package:flutter_app/projectDemo/pages/MoviePage.dart';
5 | import 'package:flutter_app/projectDemo/pages/PersonPage.dart';
6 | import 'package:flutter_app/projectDemo/pages/ShopPage.dart';
7 |
8 | class FlutterBottomNavigationBar extends StatefulWidget {
9 | FlutterBottomNavigationBar({Key key}) : super(key: key);
10 |
11 | @override
12 | State createState() {
13 | return _FlutterBottomNavigationBar();
14 | }
15 | }
16 |
17 | class _FlutterBottomNavigationBar extends State {
18 | final List pages = [
19 | HomePage(),
20 | MoviePage(),
21 | GroupPage(),
22 | ShopPage(),
23 | PersonPage()
24 | ];
25 |
26 | int _selectIndex = 0;
27 | //Stack(层叠布局)+Offstage组合,解决状态被重置的问题
28 | Widget getWidget(int index) {
29 | return Offstage(
30 | offstage: _selectIndex != index,
31 | child: TickerMode(
32 | enabled: _selectIndex == index,
33 | child: pages[index],
34 | ),
35 | );
36 | }
37 |
38 | @override
39 | Widget build(BuildContext context) {
40 | // Key key,
41 | // this.appBar,
42 | // this.body,
43 | // this.floatingActionButton,
44 | // this.floatingActionButtonLocation,
45 | // this.floatingActionButtonAnimator,
46 | // this.persistentFooterButtons,
47 | // this.drawer,
48 | // this.endDrawer,
49 | // this.bottomNavigationBar,
50 | // this.bottomSheet,
51 | // this.backgroundColor,
52 | // this.resizeToAvoidBottomPadding = true,
53 | // this.primary = true,
54 | return Scaffold(
55 | body: new Stack(
56 | children: [
57 | getWidget(0),
58 | getWidget(1),
59 | getWidget(2),
60 | getWidget(3),
61 | getWidget(4),
62 | ],
63 | ),
64 | // List
65 | // @required this.icon,
66 | // this.title,
67 | // Widget activeIcon,
68 | // this.backgroundColor,
69 | backgroundColor: Color.fromARGB(255, 248, 248, 248),
70 | bottomNavigationBar: BottomNavigationBar(
71 | items: [
72 | // BottomNavigationBarItem({
73 | //默认图标样式
74 | // @required this.icon,
75 | // this.title,
76 | //选中的图标样式
77 | // Widget activeIcon,
78 | //背景色
79 | // this.backgroundColor,
80 | // })
81 | BottomNavigationBarItem(
82 | icon: Icon(
83 | Icons.home,
84 | color: Color.fromARGB(255, 125, 125, 125),
85 | ),
86 | title: Text('首页'),
87 | activeIcon: Icon(
88 | Icons.home,
89 | )),
90 | BottomNavigationBarItem(
91 | icon: Icon(
92 | Icons.movie,
93 | color: Color.fromARGB(255, 125, 125, 125),
94 | ),
95 | title: Text('书影音'),
96 | activeIcon: Icon(
97 | Icons.movie,
98 | )),
99 | BottomNavigationBarItem(
100 | icon: Icon(
101 | Icons.group,
102 | color: Color.fromARGB(255, 125, 125, 125),
103 | ),
104 | title: Text('小组'),
105 | activeIcon: Icon(
106 | Icons.group,
107 | )),
108 | BottomNavigationBarItem(
109 | icon: Icon(
110 | Icons.receipt,
111 | color: Color.fromARGB(255, 125, 125, 125),
112 | ),
113 | title: Text('市集'),
114 | activeIcon: Icon(
115 | Icons.receipt,
116 | )),
117 | BottomNavigationBarItem(
118 | icon: Icon(
119 | Icons.person,
120 | color: Color.fromARGB(255, 125, 125, 125),
121 | ),
122 | title: Text('我的'),
123 | activeIcon: Icon(
124 | Icons.person,
125 | )),
126 | ],
127 | onTap: (int index) {
128 | setState(() {
129 | _selectIndex = index;
130 | });
131 | },
132 | //图标大小
133 | iconSize: 24,
134 | //当前选中的索引
135 | currentIndex: _selectIndex,
136 | //选中后,底部BottomNavigationBar内容的颜色(选中时,默认为主题色)(仅当type: BottomNavigationBarType.fixed,时生效)
137 | fixedColor: Color.fromARGB(255, 0, 188, 96),
138 | type: BottomNavigationBarType.fixed,
139 | ),
140 | );
141 | }
142 | }
143 |
144 | class Page1 extends StatelessWidget {
145 | @override
146 | Widget build(BuildContext context) {
147 | return Center(
148 | child: Text('Page1'),
149 | );
150 | }
151 | }
152 |
153 | class Page2 extends StatelessWidget {
154 | @override
155 | Widget build(BuildContext context) {
156 | return Center(
157 | child: Text('Page2'),
158 | );
159 | }
160 | }
161 |
162 | class Page3 extends StatelessWidget {
163 | @override
164 | Widget build(BuildContext context) {
165 | return Center(
166 | child: Text('Page3'),
167 | );
168 | }
169 | }
170 |
171 | class Page4 extends StatelessWidget {
172 | @override
173 | Widget build(BuildContext context) {
174 | return Center(
175 | child: Text('Page4'),
176 | );
177 | }
178 | }
179 |
180 | class Page5 extends StatelessWidget {
181 | @override
182 | Widget build(BuildContext context) {
183 | return Center(
184 | child: Text('Page5'),
185 | );
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterButtonBar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class FlutterButtonBar extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) {
6 | return ButtonBar(children: [
7 | Text("ButtonBar0"),
8 | Icon(Icons.ac_unit),
9 | Text("ButtonBar1")
10 | ], );
11 | }
12 | }
13 | //
14 | //const ButtonBar({
15 | //Key key,
16 | //ButtonBar的child之间的排序方式
17 | //this.alignment = MainAxisAlignment.end,
18 | //this.mainAxisSize = MainAxisSize.max,
19 | //Button的children
20 | //this.children = const [],
21 | //})
22 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterCardWidget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class FlutterCardWidget extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) {
6 | return Card(
7 | color: Colors.blueAccent,
8 | //z轴的高度,设置card的阴影
9 | elevation: 20.0,
10 | //设置shape,也就是R角
11 | shape: RoundedRectangleBorder(
12 | borderRadius: BorderRadius.only(
13 | topLeft: Radius.circular(20.0),
14 | topRight: Radius.zero,
15 | bottomLeft: Radius.zero,
16 | bottomRight: Radius.circular(20.0)),
17 | ),
18 | //对Widget截取的行为,比如这里 Clip.antiAlias 指抗锯齿
19 | clipBehavior: Clip.antiAlias,
20 | semanticContainer: false,
21 | child: getChild(),
22 | );
23 | }
24 |
25 | getChild() {
26 | return Container(
27 | color: Colors.deepPurpleAccent,
28 | width: 200,
29 | height: 150,
30 | alignment: Alignment.center,
31 | child: Text(
32 | "Card",
33 | style: TextStyle(fontSize: 28, color: Colors.white),
34 | ),
35 | );
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterContainer.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/widgets/FlutterTextWidget.dart';
3 |
4 | ///painting: transform->decoration->paints the child -> paints the foregroundDecoration
5 | /// Container 布局中会包含其他很多Widgets,所以该widget的layout behavior 比较复杂
6 |
7 | class FlutterContainer extends StatelessWidget {
8 | @override
9 | Widget build(BuildContext context) {
10 | return Center(
11 | child: Container(
12 | constraints: BoxConstraints.expand(width: 300, height: 100),
13 | child: Container(
14 | margin: EdgeInsets.all(20.5),
15 | padding: EdgeInsets.fromLTRB(30.4, 0, 0, 80),
16 | color: Colors.brown,
17 | child: Text("HELLO"),
18 | alignment: Alignment.center,
19 | ),
20 | ),
21 | );
22 | }
23 | }
24 | ///minHeight: 100, minWidth: 200, maxWidth: 400, maxHeight: 200
--------------------------------------------------------------------------------
/lib/widgets/FlutterDemoTest.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class FlutterDemoTestStatefulWidget extends StatefulWidget {
4 | @override
5 | State createState() => _FlutterDemoTestState();
6 | }
7 |
8 | class _FlutterDemoTestState extends State {
9 | var selectValue;
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | return DropdownButton(
14 | items: _getItems(),
15 | hint: Text("请选择城市"),
16 | value: selectValue,
17 | onChanged: (value) {
18 | print("value=$value");
19 | selectValue = value;
20 | setState(() {});
21 | });
22 | }
23 | }
24 |
25 | List _getItems() {
26 | List list = List();
27 | list.add(DropdownMenuItem(
28 | child: Text("北京"),
29 | value: "BJ",
30 | ));
31 | list.add(DropdownMenuItem(
32 | child: Text("上海"),
33 | value: "SH",
34 | ));
35 | list.add(DropdownMenuItem(
36 | child: Text("深圳"),
37 | value: "SZ",
38 | ));
39 | list.add(DropdownMenuItem(
40 | child: Text("广州"),
41 | value: "GZ",
42 | ));
43 | return list;
44 | }
45 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterDropdownButton.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class FlutterDropdownButtonStatefulWidget extends StatefulWidget {
4 | @override
5 | State createState() {
6 | return _DropdownState();
7 | }
8 | }
9 | //返回城市列表,写法一
10 | List _getItems() {
11 | List items = new List();
12 | //value 表示DropdownButton.onChanged的返回值
13 | items.add(DropdownMenuItem(child: Text("北京"), value: "BJ"));
14 | items.add(DropdownMenuItem(child: Text("上海"), value: "SH"));
15 | items.add(DropdownMenuItem(child: Text("广州"), value: "GZ"));
16 | items.add(DropdownMenuItem(child: Text("深圳"), value: "SZ"));
17 | return items;
18 | }
19 | //返回城市列表,写法二
20 | List> _getCityList() {
21 | var list = ["北京", "上海", "广州", "深圳"];
22 | return list.map((item) => DropdownMenuItem(
23 | value: item,
24 | child: Text(item),
25 | )).toList();
26 | }
27 |
28 | //下划线开头表示私有
29 | class _DropdownState extends State {
30 | // 下拉菜单选中的值(注意:在初始化时,要么为null,这时显示默认hint的值;
31 | // 如果自己设定值,则值必须为列表中的一个值,如果不在列表中,会抛出异常)
32 | String selectValue;
33 |
34 | @override
35 | Widget build(BuildContext context) {
36 | return DropdownButton(
37 | //要显示的条目
38 | items: _getItems(),
39 | //默认显示的值
40 | hint: Text("请选择城市"),
41 | //下拉菜单选中的值(注意:在初始化时,要么为null,这时显示默认hint的值;
42 | // 如果自己设定值,则值必须为列表中的一个值,如果不在列表中,会抛出异常)
43 | value: selectValue,
44 | onChanged: (itemValue) {//itemValue为选中的值
45 | print("itemValue=$itemValue");
46 | _onChanged(itemValue);
47 | },
48 | );
49 | }
50 | _onChanged(String value) {
51 | //更新对象的状态
52 | setState(() {
53 | selectValue = value;
54 | });
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterFlatButton.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class FlutterFlatButton extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) {
6 | return FlatButton(
7 | onPressed: () {},
8 | child: Text(
9 | "FlatBtn",
10 | style: TextStyle(fontSize: 20, color: Colors.deepPurple),
11 | ));
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterFloatingActionButton.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class FlutterFloatingActionButton extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) {
6 | return FloatingActionButton(
7 | child: Icon(Icons.access_alarm),
8 | tooltip: "ToolTip",
9 | foregroundColor: Colors.white,
10 | backgroundColor: Colors.deepPurple,
11 | shape: const Border(),
12 | onPressed: () {
13 | //click callback
14 | },
15 | );
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterGridView.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class FlutterGridView extends StatelessWidget {
4 |
5 |
6 | // //GridView写法四
7 | // @override
8 | // Widget build(BuildContext context) {
9 | // List datas = getDataList();
10 | // return GridView.custom(
11 | // gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
12 | // crossAxisCount: 3, mainAxisSpacing: 10.0, crossAxisSpacing: 20.0, ),
13 | // childrenDelegate: SliverChildBuilderDelegate((context, position) {
14 | // return getItemContainer(datas[position]);
15 | // }, childCount: datas.length));
16 | // }
17 |
18 | //GridView写法三
19 |
20 | // @override
21 | // Widget build(BuildContext context) {
22 | // List datas = getDataList();
23 | // return GridView.builder(
24 | // itemCount: datas.length,
25 | // itemBuilder: (BuildContext context, int index) {
26 | // return getItemContainer(datas[index]);
27 | // },
28 | // gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
29 | // //单个子Widget的水平最大宽度
30 | // maxCrossAxisExtent: 100,
31 | // //垂直单个子Widget之间间距
32 | // mainAxisSpacing: 20.0,
33 | // //水平单个子Widget之间间距
34 | // crossAxisSpacing: 0.0
35 | // ),
36 | // );
37 | // }
38 |
39 | //GridView写法二
40 |
41 | // @override
42 | // Widget build(BuildContext context) {
43 | // List datas = getDataList();
44 | // return GridView.builder(
45 | // itemCount: datas.length,
46 | // //SliverGridDelegateWithFixedCrossAxisCount 构建一个横轴固定数量Widget
47 | // gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
48 | // //横轴元素个数
49 | // crossAxisCount: 3,
50 | // //纵轴间距
51 | // mainAxisSpacing: 20.0,
52 | // //横轴间距
53 | // crossAxisSpacing: 10.0,
54 | // //子组件宽高长度比例
55 | // childAspectRatio: 2.0),
56 | // itemBuilder: (BuildContext context, int index) {
57 | // //Widget Function(BuildContext context, int index)
58 | // return getItemContainer(datas[index]);
59 | // });
60 | // }
61 |
62 | //GridView写法一
63 |
64 | @override
65 | Widget build(BuildContext context) {
66 | return GridView.count(
67 | //水平子Widget之间间距
68 | crossAxisSpacing: 10.0,
69 | //垂直子Widget之间间距
70 | mainAxisSpacing: 10.0,
71 | //GridView内边距
72 | padding: EdgeInsets.all(10.0),
73 | //一行的Widget数量
74 | crossAxisCount: 3,
75 | //子Widget宽高比例
76 | childAspectRatio: 1.0,
77 | //子Widget列表
78 | children: getWidgetList(),
79 | );
80 | }
81 |
82 | List getDataList() {
83 | List list = [];
84 | for (int i = 0; i < 100; i++) {
85 | list.add(i.toString());
86 | }
87 | return list;
88 | }
89 |
90 | List getWidgetList() {
91 | return getDataList().map((item) => getItemContainer(item)).toList();
92 | }
93 |
94 | Widget getItemContainer(String item) {
95 |
96 | return Card(
97 | elevation: 20,
98 | child: Container(
99 | width: 5.0,
100 | height: 5.0,
101 | alignment: Alignment.center,
102 | child: Text(
103 | item,
104 | style: TextStyle(color: Colors.white, fontSize: 20),
105 | ),
106 | color: Colors.blue,
107 | )
108 | );
109 |
110 |
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterIcon.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | double _volume = 0.0;
4 |
5 | class MyStatefulWidget extends StatefulWidget {
6 | MyStatefulWidget({Key key}) : super(key: key);
7 |
8 | @override
9 | _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
10 | }
11 |
12 | class _MyStatefulWidgetState extends State {
13 | Widget build(BuildContext) {
14 | return Container(
15 | child: IconButton(
16 | icon: Icon(Icons.volume_up),
17 | tooltip: 'Increase volume by 10%',
18 | onPressed: () {
19 | setState(() {
20 | _volume *= 1.1;
21 | });
22 | },
23 | ),
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterIconButton.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class FlutterIconButton extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) {
6 | return IconButton(
7 | color: Colors.deepOrangeAccent,
8 | splashColor: Colors.purple,
9 | icon: Icon(
10 | Icons.android,
11 | color: Colors.deepPurpleAccent,
12 | ),
13 | onPressed: () {});
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterImage.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'dart:io';
3 | //博客地址:flutterall.com
4 | class FlutterImage extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | var img = Image.network(
8 | "https://upload.jianshu.io/users/upload_avatars/3884536/d847a50f1da0.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240",
9 | repeat: ImageRepeat.repeatY,
10 | );
11 | return Scaffold(
12 | body: Container(
13 | child: img,
14 | constraints: BoxConstraints.expand(//对Image的约束
15 | width: MediaQuery.of(context).size.width,
16 | height: MediaQuery.of(context).size.height),
17 | ),
18 | );
19 | }
20 | }
21 |
22 | //显示网络图片:Image.network("https://upload.jianshu.io/users/upload_avatars/3884536/d847a50f1da0.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240"),
23 | //加载File图片: Image.file(File("/sdcard/flutter.jpeg")), 注意在AndroidManifest.xml中配置读写文件权限。
24 |
25 | //centerSlice//////////////
26 | //Image.network("
27 | //https://upload.jianshu.io/users/upload_avatars/3884536/d847a50f1da0.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240
28 | //"
29 | //,
30 | //width: 400
31 | //,
32 | //height: 400
33 | //,
34 | //fit: BoxFit.contain,centerSlice: Rect.fromLTWH(10, 10, 10, 10),
35 | //)
36 |
37 | //matchTextDirection/////////////
38 |
39 | //var img = Image.network(
40 | // "https://upload-images.jianshu.io/upload_images/3884536-0a4766ccd55f287a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240",
41 | // matchTextDirection: true,
42 | //);
43 | //
44 | //var center = Center(
45 | // child: ListView(
46 | // children: [
47 | // Directionality(
48 | // textDirection: TextDirection.ltr,
49 | // child: img,
50 | // ),
51 | // Directionality(
52 | // textDirection: TextDirection.rtl,
53 | // child: img,
54 | // )
55 | // ],
56 | // ));
57 | //
58 | //return Scaffold(
59 | //body: center,
60 | //);
61 |
62 |
63 | //repeat
64 | //var img = Image.network(
65 | // "https://upload.jianshu.io/users/upload_avatars/3884536/d847a50f1da0.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240",
66 | // width: 50,
67 | // height: 50,
68 | // fit: BoxFit.scaleDown,
69 | // repeat: ImageRepeat.repeat,
70 | //);
71 | //return Scaffold(
72 | //body: Container(
73 | //child: img,
74 | //constraints: BoxConstraints.expand(//对Image的约束
75 | //width: MediaQuery.of(context).size.width,
76 | //height: MediaQuery.of(context).size.height),
77 | //),
78 | //);
--------------------------------------------------------------------------------
/lib/widgets/FlutterListView.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'dart:math';
3 |
4 | class FlutterListView extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return ListView(
8 | scrollDirection: Axis.horizontal,
9 | children: getListWidgets());
10 | }
11 | }
12 |
13 | //生成listview children Widgets
14 | List getListWidgets() {
15 | List list = List();
16 | Random random = Random();
17 | for (int i = 0; i < 100; i++) {
18 | int r = random.nextInt(255);
19 | int g = random.nextInt(255);
20 | int b = random.nextInt(255);
21 | list.add(ItemData(Color.fromARGB(255, r, g, b), i.toString()));
22 | }
23 | return list.map((item) => ListViewItem(item)).toList();
24 | }
25 |
26 | class ListViewItem extends StatelessWidget {
27 | final ItemData itemData;
28 |
29 | ListViewItem(this.itemData);
30 |
31 | @override
32 | Widget build(BuildContext context) {
33 | return Container(
34 | width: 150,
35 | height: 70,
36 | //ListTile可以作为listView的一种子组件类型,支持配置点击事件,一个拥有固定样式的Widget
37 | child: ListTile(
38 | leading: CircleAvatar(
39 | backgroundColor: itemData.color,
40 | child: Text(
41 | itemData.text,
42 | style: TextStyle(color: Colors.white),
43 | ),
44 | ),
45 | title: Text(itemData.text),
46 | ),
47 | );
48 | }
49 | }
50 |
51 | class ItemData {
52 | final Color color;
53 | final String text;
54 |
55 | ItemData(this.color, this.text);
56 | }
57 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterPopupMenuButton.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class FlutterPopupMenuButton extends StatefulWidget {
4 | @override
5 | State createState() => _PopupMenuState();
6 | }
7 |
8 | const List models = const ['白天模式', '护眼模式', '黑夜模式'];
9 |
10 | class _PopupMenuState extends State {
11 | String title = models[0];
12 |
13 | List> _getItemBuilder() {
14 | return models
15 | .map((item) => PopupMenuItem(
16 | child: Text(item),
17 | value: item,//value一定不能少
18 | ))
19 | .toList();
20 | }
21 |
22 | void _select(String value) {
23 | setState(() {
24 | title = value;
25 | });
26 | }
27 |
28 | @override
29 | Widget build(BuildContext context) {
30 | return MaterialApp(
31 | home: Scaffold(
32 | appBar: AppBar(
33 | title: Text(title),
34 | actions: [
35 | PopupMenuButton(
36 | onSelected: _select,
37 | itemBuilder: (BuildContext context) {
38 | return _getItemBuilder();
39 | },
40 | )
41 | ],
42 | ),
43 | ),
44 | );
45 | }
46 |
47 | // List _getItemBuilder() {
48 | // List list = List();
49 | // list.add(PopupMenuItem(
50 | // child: Text("白天模式"),
51 | // value: "Day",
52 | // ));
53 | // list.add(PopupMenuItem(
54 | // child: Text("黑夜模式"),
55 | // value: "Night",
56 | // ));
57 | // return list;
58 | // }
59 |
60 | }
61 |
62 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterRaisedButton.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/cupertino.dart';
3 |
4 | class FlutterRaisedButton extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return Scaffold(
8 | body: SafeArea(
9 | child: Container(
10 | alignment: Alignment.center,
11 | child: RaisedButton(
12 | textTheme: ButtonTextTheme.accent,
13 | color: Colors.teal,
14 | highlightColor: Colors.deepPurpleAccent,
15 | splashColor: Colors.deepOrangeAccent,
16 | colorBrightness: Brightness.dark,
17 | elevation: 50.0,
18 | highlightElevation: 100.0,
19 | disabledElevation: 20.0,
20 | onPressed: () {
21 | //TODO
22 | },
23 | child: Text(
24 | 'RaisedButton',
25 | style: TextStyle(color: Colors.white, fontSize: 40),
26 | ),
27 | ),
28 | ),
29 | ),
30 | );
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterRow.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class FlutterRow extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) {
6 | return SafeArea(
7 | child: Row(
8 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
9 | children: [Text("One"), Text("Two"), Text("Three")],
10 | ),
11 | );
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterSliverAppBar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class FlutterSliverAppBar extends StatelessWidget {
4 | /// 如果没有leading,automaticallyImplyLeading为true,就会默认返回箭头
5 | /// 如果 没有leading 且为false,空间留给title
6 | /// 如果有leading,这个参数就无效了
7 | // automaticallyImplyLeading: true,
8 | // // title: Text('大标题'), //标题
9 | // centerTitle: true, //标题是否居中
10 | // actions: [Icon(Icons.archive)], //右侧的内容和点击事件啥的
11 | // elevation: 4, //阴影的高度
12 | // forceElevated: false, //是否显示阴影
13 | // backgroundColor: Colors.green, //背景颜色
14 | // brightness: Brightness.dark, //黑底白字,lignt 白底黑字
15 | // iconTheme: IconThemeData(
16 | // color: Colors.red,
17 | // size: 30,
18 | // opacity: 1), //所有的icon的样式,不仅仅是左侧的,右侧的也会改变
19 | // textTheme: TextTheme(), //字体样式
20 | // primary: true, // appbar是否显示在屏幕的最上面,为false是显示在最上面,为true就显示在状态栏的下面
21 | // titleSpacing: 16, //标题两边的空白区域
22 | // expandedHeight: 200.0, //默认高度是状态栏和导航栏的高度,如果有滚动视差的话,要大于前两者的高度
23 | // floating: false, //滑动到最上面,再滑动是否隐藏导航栏的文字和标题等的具体内容,为true是隐藏,为false是不隐藏
24 | // pinned: true, //是否固定导航栏,为true是固定,为false是不固定,往上滑,导航栏可以隐藏
25 | // snap:
26 | // false, //只跟floating相对应,如果为true,floating必须为true,也就是向下滑动一点儿,整个大背景就会动画显示全部,向上滑动整个导航栏的内容就会消失
27 |
28 | @override
29 | Widget build(BuildContext context) {
30 | var url =
31 | "https://upload-images.jianshu.io/upload_images/3884536-0a4766ccd55f287a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000/format/webp";
32 | var children = [
33 | ListView.builder(
34 | itemBuilder: (BuildContext context, int index) {
35 | return Text("$index");
36 | },
37 | itemCount: 100,
38 | )
39 | ];
40 |
41 | return Scaffold(
42 | body: SafeArea(
43 | child: CustomScrollView(
44 | slivers: [
45 | SliverAppBar(
46 | title: Text('SliverAppBar text'),
47 | expandedHeight: 200.0,
48 | actions: [Text("actions"), Text("actions2")],
49 | pinned: true,
50 | backgroundColor: Colors.indigo,
51 | flexibleSpace: FlexibleSpaceBar(
52 | background: Container(
53 | color: Colors.black26,
54 | width: double.infinity,
55 | height: 60.0,
56 | ),
57 | ),
58 | ),
59 | Container(
60 | color: Colors.blue,
61 | width: double.infinity,
62 | height: 1000.0,
63 | )
64 | ],
65 | )),
66 | );
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterStack.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class FlutterStack extends StatelessWidget {
4 | final w = 140.0;
5 | final urls;
6 |
7 | FlutterStack({Key key, @required this.urls, double w}) : super(key: key);
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | double h = w * 1.5;
12 | double dif = w * 0.14;
13 | return Scaffold(
14 | body: SafeArea(
15 | child: Container(
16 | height: h,
17 | child: Stack(
18 | alignment: Alignment.bottomLeft,
19 | children: [
20 | Positioned(
21 | left: w * 0.78,
22 | child: ClipRRect(
23 | borderRadius: BorderRadius.circular(6.0),
24 | child: Image.network(
25 | urls[2],
26 | width: w,
27 | height: h - dif - dif / 2,
28 | fit: BoxFit.cover,
29 | color: Color.fromARGB(100, 246, 246, 246),
30 | colorBlendMode: BlendMode.screen,
31 | ),
32 | ),
33 | ),
34 | Positioned(
35 | left: w * 0.42,
36 | child: ClipRRect(
37 | borderRadius: BorderRadius.circular(6.0),
38 | child: Image.network(
39 | urls[1],
40 | width: w,
41 | height: h - dif,
42 | fit: BoxFit.cover,
43 | color: Color.fromARGB(100, 246, 246, 246),
44 | colorBlendMode: BlendMode.screen,
45 | ),
46 | ),
47 | ),
48 | Positioned(
49 | left: 0,
50 | child: ClipRRect(
51 | borderRadius: BorderRadius.circular(6.0),
52 | child: Image.network(
53 | urls[0],
54 | width: w,
55 | height: h,
56 | fit: BoxFit.cover,
57 | ),
58 | ),
59 | ),
60 | ],
61 | ),
62 | )),
63 | );
64 | }
65 |
66 | //圆角图片
67 | getImage(var imgUrl, var w, var h) {
68 | // this.color,
69 | // this.elevation = 1.0,
70 | // this.shape,
71 | // this.margin = const EdgeInsets.all(4.0),
72 | // this.clipBehavior = Clip.none,
73 | // this.child,
74 | // this.semanticContainer = true,
75 | return Card(
76 | child: Image.network(
77 | imgUrl,
78 | width: w,
79 | height: h,
80 | fit: BoxFit.cover,
81 | ),
82 | );
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterTabBar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/widgets/FlutterTabBarView.dart';
3 |
4 | var titleList = ['电影', '电视', '综艺', '读书', '音乐', '同城'];
5 |
6 | List tabList;
7 |
8 |
9 | class HomePage extends StatefulWidget {
10 |
11 | @override
12 | State createState() {
13 | return _HomePageState();
14 | }
15 |
16 | }
17 |
18 | TabController _tabController;
19 |
20 |
21 | class _HomePageState extends State with SingleTickerProviderStateMixin{
22 |
23 | var tabBar;
24 |
25 | @override
26 | void initState() {
27 | super.initState();
28 | tabBar = FlutterTabBar();
29 | tabList = getTabList();
30 | _tabController = TabController(vsync: this, length: tabList.length);
31 | }
32 |
33 |
34 | List getTabList() {
35 | return titleList
36 | .map((item) => Text(
37 | '$item',
38 | style: TextStyle(fontSize: 18),
39 | ))
40 | .toList();
41 | }
42 |
43 | @override
44 | Widget build(BuildContext context) {
45 | return Container(
46 | child: SafeArea(
47 | child: DefaultTabController(
48 | length: titleList.length,
49 | child: Column(
50 | children: [
51 | tabBar,
52 | Expanded(
53 | child: Container(
54 | color: Colors.white70,
55 | width: double.infinity,
56 | alignment: Alignment.center,
57 | // child: Text('$selectType', style: TextStyle(fontSize: 26),),
58 | child: FlutterTabBarView(tabController: _tabController,),
59 | ),
60 | )
61 | ],
62 | ))),
63 | );
64 |
65 | // @override
66 | // Widget build(BuildContext context) {
67 | // return MaterialApp(
68 | // home: Scaffold(
69 | // body: Container(
70 | // child: SafeArea(
71 | // child: DefaultTabController(
72 | // length: titleList.length,
73 | // child: Column(
74 | // children: [
75 | // tabBar,
76 | // Expanded(
77 | // child: Container(
78 | // color: Colors.blue,
79 | // width: double.infinity,
80 | // alignment: Alignment.center,
81 | //// child: Text('$selectType', style: TextStyle(fontSize: 26),),
82 | // child: FlutterTabBarView(tabController: _tabController,),
83 | // ),
84 | // )
85 | // ],
86 | // ))),
87 | // ),
88 | // ),
89 | // );
90 |
91 | }
92 |
93 |
94 | }
95 |
96 |
97 | class FlutterTabBar extends StatefulWidget {
98 |
99 |
100 | FlutterTabBar({Key key}) : super(key: key);
101 |
102 | @override
103 | State createState() {
104 | return _FlutterTabBarState();
105 | }
106 | }
107 |
108 |
109 |
110 |
111 | class _FlutterTabBarState extends State {
112 | Color selectColor, unselectedColor;
113 | TextStyle selectStyle, unselectedStyle;
114 |
115 | @override
116 | void initState() {
117 | super.initState();
118 | selectColor = Color.fromARGB(255, 45, 45, 45);
119 | unselectedColor = Color.fromARGB(255, 117, 117, 117);
120 | selectStyle = TextStyle(fontSize: 18, color: selectColor);
121 | unselectedStyle = TextStyle(fontSize: 18, color: selectColor);
122 | }
123 |
124 | @override
125 | void dispose() {
126 | _tabController.dispose();
127 | super.dispose();
128 | }
129 |
130 | @override
131 | Widget build(BuildContext context) {
132 | //Tab小部件列表
133 | // List @required this.tabs,
134 | //组件选中以及动画的状态
135 | // TabController this.controller,
136 | //Tab是否可滑动
137 | // bool this.isScrollable = false,
138 | //选项卡下方的导航条的颜色
139 | // Color this.indicatorColor,
140 | //选项卡下方的导航条的线条粗细
141 | // double this.indicatorWeight = 2.0,
142 | // EdgeInsetsGeometry this.indicatorPadding = EdgeInsets.zero,
143 | // Decoration this.indicator,
144 | // TabBarIndicatorSize this.indicatorSize,导航条的长度,(tab:默认等分;label:跟标签长度一致)
145 | // Color this.labelColor,所选标签标签的颜色
146 | // TextStyle this.labelStyle,所选标签标签的文本样式
147 | // EdgeInsetsGeometry this.labelPadding,,所选标签标签的内边距
148 | // Color this.unselectedLabelColor,未选定标签标签的颜色
149 | // TextStyle this.unselectedLabelStyle,未选中标签标签的文字样式
150 | // void Function(T value) this.onTap,按下时的响应事件
151 |
152 | return TabBar(
153 | tabs: tabList,
154 | isScrollable: true,
155 | controller: _tabController,
156 | indicatorColor: selectColor,
157 | labelColor: selectColor,
158 | labelStyle: selectStyle,
159 | unselectedLabelColor: unselectedColor,
160 | unselectedLabelStyle: unselectedStyle,
161 | indicatorSize: TabBarIndicatorSize.label,
162 | );
163 | }
164 |
165 | }
166 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterTabBarView.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/projectDemo/DouBanDemo.dart';
3 |
4 | class FlutterTabBarView extends StatefulWidget {
5 | final TabController tabController;
6 |
7 | FlutterTabBarView({Key key, @required this.tabController}) : super(key: key);
8 |
9 | @override
10 | State createState() {
11 | return _FlutterTabBarViewState(tabController: tabController);
12 | }
13 | }
14 |
15 | var viewList;
16 |
17 | class _FlutterTabBarViewState extends State {
18 | final TabController tabController;
19 |
20 | _FlutterTabBarViewState({@required this.tabController});
21 |
22 | @override
23 | void initState() {
24 | super.initState();
25 | viewList = [
26 | Page1(),
27 | Page2(),
28 | DouBanListView(),
29 | Page4(),
30 | Page5(),
31 | Page1(),
32 | ];
33 | }
34 |
35 | @override
36 | Widget build(BuildContext context) {
37 | // TabBarView({
38 | // Key key,
39 | // @required this.children,
40 | // this.controller,
41 | // this.physics,
42 | // })
43 | print('build FlutterTabBarView');
44 | return TabBarView(
45 | children: viewList,
46 | controller: tabController,
47 | );
48 | }
49 | }
50 |
51 | class Page1 extends StatelessWidget {
52 | @override
53 | Widget build(BuildContext context) {
54 | print('build Page1');
55 |
56 | return Center(
57 | child: Text('Page1'),
58 | );
59 | }
60 | }
61 |
62 | class Page2 extends StatelessWidget {
63 | @override
64 | Widget build(BuildContext context) {
65 | print('build Page2');
66 | return Center(
67 | child: Text('Page2'),
68 | );
69 | }
70 | }
71 |
72 | class Page3 extends StatelessWidget {
73 |
74 | @override
75 | Widget build(BuildContext context) {
76 | print('build Page3');
77 | return Center(
78 | child: Text('Page3'),
79 | );
80 | }
81 | }
82 |
83 | class Page4 extends StatelessWidget {
84 | @override
85 | Widget build(BuildContext context) {
86 | print('build Page4');
87 | return Center(
88 | child: Text('Page4'),
89 | );
90 | }
91 | }
92 |
93 | class Page5 extends StatelessWidget {
94 | @override
95 | Widget build(BuildContext context) {
96 | print('build Page5');
97 | return Center(
98 | child: Text('Page5'),
99 | );
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/lib/widgets/FlutterTextWidget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class MyTextWidget extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) {
6 | return Scaffold(
7 | body: SafeArea(child: txt2),
8 | );
9 | }
10 |
11 | //TextStyle->decoration: TextDecoration.none 去掉Text默认的下划线
12 | //decoration 装饰属性
13 | var txt1 = Text("hello",
14 | textAlign: TextAlign.center,
15 | style: TextStyle(
16 | fontWeight: FontWeight.bold, decoration: TextDecoration.none));
17 |
18 | var txt2 = Text.rich(TextSpan(
19 | text: "text.rich",
20 | style: TextStyle(decoration: TextDecoration.none),
21 | children: [
22 | TextSpan(
23 | text: " the ",
24 | style: TextStyle(
25 | fontSize: 18,
26 | fontWeight: FontWeight.bold,
27 | decoration: TextDecoration.none)),
28 | TextSpan(
29 | text: "world",
30 | style: TextStyle(fontSize: 20, decoration: TextDecoration.none))
31 | ]));
32 | }
33 |
--------------------------------------------------------------------------------
/lib/widgets/bottom_drag_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/gestures.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | ///上拉抽屉
5 | class BottomDragWidget extends StatelessWidget {
6 | final Widget body;
7 | final DragContainer dragContainer;
8 |
9 | BottomDragWidget({Key key, @required this.body, @required this.dragContainer})
10 | : assert(body != null),
11 | assert(dragContainer != null),
12 | super(key: key);
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | return Stack(
17 | children: [
18 | body,
19 | Align(
20 | alignment: Alignment.bottomCenter,
21 | child: dragContainer,
22 | )
23 | ],
24 | );
25 | }
26 | }
27 |
28 | typedef DragListener = void Function(
29 | double dragDistance, ScrollNotificationListener isDragEnd);
30 |
31 | class DragController {
32 | DragListener _dragListener;
33 |
34 | setDrag(DragListener l) {
35 | _dragListener = l;
36 | }
37 |
38 | void updateDragDistance(
39 | double dragDistance, ScrollNotificationListener isDragEnd) {
40 | if (_dragListener != null) {
41 | _dragListener(dragDistance, isDragEnd);
42 | }
43 | }
44 | }
45 |
46 | class DragContainer extends StatefulWidget {
47 | final Widget drawer;
48 | final double defaultShowHeight;
49 | final double height;
50 |
51 | DragContainer(
52 | {Key key,
53 | @required this.drawer,
54 | @required this.defaultShowHeight,
55 | @required this.height})
56 | : assert(drawer != null),
57 | assert(defaultShowHeight != null),
58 | assert(height != null),
59 | super(key: key){
60 | _controller = DragController();
61 | }
62 |
63 | @override
64 | _DragContainerState createState() => _DragContainerState();
65 | }
66 |
67 | class _DragContainerState extends State
68 | with TickerProviderStateMixin {
69 | AnimationController animalController;
70 |
71 | ///滑动位置超过这个位置,会滚到顶部;小于,会滚动底部。
72 | double maxOffsetDistance;
73 | bool onResetControllerValue = false;
74 | double offsetDistance;
75 | Animation animation;
76 | bool offstage = false;
77 | bool _isFling = false;
78 |
79 | double get defaultOffsetDistance => widget.height - widget.defaultShowHeight;
80 |
81 | @override
82 | void initState() {
83 | animalController = AnimationController(
84 | vsync: this, duration: const Duration(milliseconds: 250));
85 | maxOffsetDistance = (widget.height + widget.defaultShowHeight) * 0.5;
86 |
87 | // if (controller != null) {
88 | _controller
89 | .setDrag((double value, ScrollNotificationListener notification) {
90 | if (notification != ScrollNotificationListener.edge) {
91 | _handleDragEnd(null);
92 | } else {
93 | setState(() {
94 | offsetDistance = offsetDistance + value;
95 | });
96 | }
97 | });
98 | // }
99 | super.initState();
100 | }
101 |
102 | GestureRecognizerFactoryWithHandlers
103 | getRecognizer() {
104 | return GestureRecognizerFactoryWithHandlers<
105 | MyVerticalDragGestureRecognizer>(
106 | () => MyVerticalDragGestureRecognizer(flingListener: (bool isFling) {
107 | _isFling = isFling;
108 | }), //constructor
109 | (MyVerticalDragGestureRecognizer instance) {
110 | //initializer
111 | instance
112 | ..onStart = _handleDragStart
113 | ..onUpdate = _handleDragUpdate
114 | ..onEnd = _handleDragEnd;
115 | },
116 | );
117 | }
118 |
119 | @override
120 | void dispose() {
121 | animalController.dispose();
122 | super.dispose();
123 | }
124 |
125 | @override
126 | Widget build(BuildContext context) {
127 | if (offsetDistance == null || onResetControllerValue) {
128 | ///说明是第一次加载,由于BottomDragWidget中 alignment: Alignment.bottomCenter,故直接设置
129 | offsetDistance = defaultOffsetDistance;
130 | }
131 |
132 | ///偏移值在这个范围内
133 | offsetDistance = offsetDistance.clamp(0.0, defaultOffsetDistance);
134 | offstage = offsetDistance < maxOffsetDistance;
135 | return Transform.translate(
136 | offset: Offset(0.0, offsetDistance),
137 | child: RawGestureDetector(
138 | gestures: {MyVerticalDragGestureRecognizer: getRecognizer()},
139 | child: Stack(
140 | children: [
141 | Container(
142 | child: widget.drawer,
143 | height: widget.height,
144 | ),
145 | Offstage(
146 | child: Container(
147 | ///使用图层来解决当抽屉露出头时,上拉抽屉上移。解决的方案最佳
148 | color: Colors.transparent,
149 | height: widget.height,
150 | ),
151 | offstage: offstage,
152 | )
153 | ],
154 | ),
155 | ),
156 | );
157 | }
158 |
159 | double get screenH => MediaQuery.of(context).size.height;
160 |
161 | ///当拖拽结束时调用
162 | void _handleDragEnd(DragEndDetails details) {
163 | onResetControllerValue = true;
164 |
165 | ///很重要!!!动画完毕后,controller.value = 1.0, 这里要将value的值重置为0.0,才会再次运行动画
166 | ///重置value的值时,会刷新UI,故这里使用[onResetControllerValue]来进行过滤。
167 | animalController.value = 0.0;
168 | onResetControllerValue = false;
169 | double start;
170 | double end;
171 | if (offsetDistance <= maxOffsetDistance) {
172 | ///这个判断通过,说明已经child位置超过警戒线了,需要滚动到顶部了
173 | start = offsetDistance;
174 | end = 0.0;
175 | } else {
176 | start = offsetDistance;
177 | end = defaultOffsetDistance;
178 | }
179 |
180 | if (_isFling &&
181 | details != null &&
182 | details.velocity != null &&
183 | details.velocity.pixelsPerSecond != null &&
184 | details.velocity.pixelsPerSecond.dy < 0) {
185 | ///这个判断通过,说明是快速向上滑动,此时需要滚动到顶部了
186 | start = offsetDistance;
187 | end = 0.0;
188 | }
189 |
190 | ///easeOut 先快后慢
191 | final CurvedAnimation curve =
192 | new CurvedAnimation(parent: animalController, curve: Curves.easeOut);
193 | animation = Tween(begin: start, end: end).animate(curve)
194 | ..addListener(() {
195 | if (!onResetControllerValue) {
196 | offsetDistance = animation.value;
197 | setState(() {});
198 | }
199 | });
200 | ///自己滚动
201 | animalController.forward();
202 | }
203 |
204 | void _handleDragUpdate(DragUpdateDetails details) {
205 | offsetDistance = offsetDistance + details.delta.dy;
206 | setState(() {});
207 | }
208 |
209 | void _handleDragStart(DragStartDetails details) {
210 | _isFling = false;
211 | }
212 | }
213 |
214 | typedef FlingListener = void Function(bool isFling);
215 |
216 | ///MyVerticalDragGestureRecognizer 负责任务
217 | ///1.监听child的位置更新
218 | ///2.判断child在手松的那一刻是否是出于fling状态
219 | class MyVerticalDragGestureRecognizer extends VerticalDragGestureRecognizer {
220 | final FlingListener flingListener;
221 |
222 | /// Create a gesture recognizer for interactions in the vertical axis.
223 | MyVerticalDragGestureRecognizer({Object debugOwner, this.flingListener})
224 | : super(debugOwner: debugOwner);
225 |
226 | final Map _velocityTrackers = {};
227 |
228 | @override
229 | void handleEvent(PointerEvent event) {
230 | super.handleEvent(event);
231 | if (!event.synthesized &&
232 | (event is PointerDownEvent || event is PointerMoveEvent)) {
233 | final VelocityTracker tracker = _velocityTrackers[event.pointer];
234 | assert(tracker != null);
235 | tracker.addPosition(event.timeStamp, event.position);
236 | }
237 | }
238 |
239 | @override
240 | void addPointer(PointerEvent event) {
241 | super.addPointer(event);
242 | _velocityTrackers[event.pointer] = VelocityTracker();
243 | }
244 |
245 | ///来检测是否是fling
246 | @override
247 | void didStopTrackingLastPointer(int pointer) {
248 | final double minVelocity = minFlingVelocity ?? kMinFlingVelocity;
249 | final double minDistance = minFlingDistance ?? kTouchSlop;
250 | final VelocityTracker tracker = _velocityTrackers[pointer];
251 |
252 | ///VelocityEstimate 计算二维速度的
253 | final VelocityEstimate estimate = tracker.getVelocityEstimate();
254 | bool isFling = false;
255 | if (estimate != null && estimate.pixelsPerSecond != null) {
256 | isFling = estimate.pixelsPerSecond.dy.abs() > minVelocity &&
257 | estimate.offset.dy.abs() > minDistance;
258 | }
259 | _velocityTrackers.clear();
260 | if (flingListener != null) {
261 | flingListener(isFling);
262 | }
263 |
264 | ///super.didStopTrackingLastPointer(pointer) 会调用[_handleDragEnd]
265 | ///所以将[lingListener(isFling);]放在前一步调用
266 | super.didStopTrackingLastPointer(pointer);
267 | }
268 |
269 | @override
270 | void dispose() {
271 | _velocityTrackers.clear();
272 | super.dispose();
273 | }
274 | }
275 |
276 | typedef ScrollListener = void Function(
277 | double dragDistance, ScrollNotificationListener notification);
278 |
279 | DragController _controller;
280 |
281 | ///监听手指在child处于边缘时的滑动
282 | ///例如:当child滚动到顶部时,此时下拉,会回调[ScrollNotificationListener.edge],
283 | ///或者child滚动到底部时,此时下拉,会回调[ScrollNotificationListener.edge],
284 | ///当child为[ScrollView]的子类时,例如:[ListView] / [GridView] 等,时,需要将其`physics`属性设置为[ClampingScrollPhysics]
285 | ///想看原因的,可以看下:
286 | /// ///这个属性是用来断定滚动的部件的物理特性,例如:
287 | // ///scrollStart
288 | // ///ScrollUpdate
289 | // ///Overscroll
290 | // ///ScrollEnd
291 | // ///在Android和ios等平台,其默认值是不同的。我们可以在scroll_configuration.dart中看到如下配置
292 | //
293 | // /// The scroll physics to use for the platform given by [getPlatform].
294 | // ///
295 | // /// Defaults to [BouncingScrollPhysics] on iOS and [ClampingScrollPhysics] on
296 | // /// Android.
297 | //// ScrollPhysics getScrollPhysics(BuildContext context) {
298 | //// switch (getPlatform(context)) {
299 | //// case TargetPlatform.iOS:/*/
300 | //// return const BouncingScrollPhysics();
301 | //// case TargetPlatform.android:
302 | //// case TargetPlatform.fuchsia:
303 | //// return const ClampingScrollPhysics();
304 | //// }
305 | //// return null;
306 | //// }
307 | ///在ios中,默认返回BouncingScrollPhysics,对于[BouncingScrollPhysics]而言,
308 | ///由于 double applyBoundaryConditions(ScrollMetrics position, double value) => 0.0;
309 | ///会导致:当listview的第一条目显示时,继续下拉时,不会调用上面提到的Overscroll监听。
310 | ///故这里,设定为[ClampingScrollPhysics]
311 | class OverscrollNotificationWidget extends StatefulWidget {
312 | const OverscrollNotificationWidget({
313 | Key key,
314 | @required this.child,
315 | // this.scrollListener,
316 | }) : assert(child != null),
317 | super(key: key);
318 |
319 | final Widget child;
320 | // final ScrollListener scrollListener;
321 |
322 | @override
323 | OverscrollNotificationWidgetState createState() =>
324 | OverscrollNotificationWidgetState();
325 | }
326 |
327 | /// Contains the state for a [OverscrollNotificationWidget]. This class can be used to
328 | /// programmatically show the refresh indicator, see the [show] method.
329 | class OverscrollNotificationWidgetState
330 | extends State
331 | with TickerProviderStateMixin {
332 | final GlobalKey _key = GlobalKey();
333 |
334 | ///[ScrollStartNotification] 部件开始滑动
335 | ///[ScrollUpdateNotification] 部件位置发生改变
336 | ///[OverscrollNotification] 表示窗口小部件未更改它的滚动位置,因为更改会导致滚动位置超出其滚动范围
337 | ///[ScrollEndNotification] 部件停止滚动
338 | ///之所以不能使用这个来build或者layout,是因为这个通知的回调是会有延迟的。
339 | ///Any attempt to adjust the build or layout based on a scroll notification would
340 | ///result in a layout that lagged one frame behind, which is a poor user experience.
341 |
342 | @override
343 | Widget build(BuildContext context) {
344 | print('NotificationListener build');
345 | final Widget child = NotificationListener(
346 | key: _key,
347 | child: NotificationListener(
348 | child: NotificationListener(
349 | child: NotificationListener(
350 | child: widget.child,
351 | onNotification: (ScrollEndNotification notification) {
352 | _controller.updateDragDistance(
353 | 0.0, ScrollNotificationListener.end);
354 | return false;
355 | },
356 | ),
357 | onNotification: (OverscrollNotification notification) {
358 | if (notification.dragDetails != null &&
359 | notification.dragDetails.delta != null) {
360 | _controller.updateDragDistance(notification.dragDetails.delta.dy,
361 | ScrollNotificationListener.edge);
362 | }
363 | return false;
364 | },
365 | ),
366 | onNotification: (ScrollUpdateNotification notification) {
367 | return false;
368 | },
369 | ),
370 | onNotification: (ScrollStartNotification scrollUpdateNotification) {
371 | _controller.updateDragDistance(0.0, ScrollNotificationListener.start);
372 | return false;
373 | },
374 | );
375 |
376 | return child;
377 | }
378 | }
379 |
380 | enum ScrollNotificationListener {
381 | ///滑动开始
382 | start,
383 |
384 | ///滑动结束
385 | end,
386 |
387 | ///滑动时,控件在边缘(最上面显示或者最下面显示)位置
388 | edge
389 | }
390 |
391 | /// -----------------------DEMO-----------------------
392 | ///
393 | ///
394 | ///
395 | /// DragController controller = DragController();
396 | //class Demo extends StatefulWidget {
397 | // @override
398 | // _DemoState createState() => _DemoState();
399 | //}
400 | //
401 | //class _DemoState extends State {
402 | // @override
403 | // Widget build(BuildContext context) {
404 | // return BottomDragWidget(
405 | // body: Container(
406 | // color: Colors.brown,
407 | // child: ListView.builder(itemBuilder: (BuildContext context, int index){
408 | // return Text('我是listview下面一层的东东,index=$index');
409 | // }, itemCount: 100,),
410 | // ),
411 | // dragContainer: DragContainer(
412 | // controller: controller,
413 | // drawer: getListView(),
414 | // defaultShowHeight: 150.0,
415 | // height: 700.0,
416 | // ));
417 | // }
418 | //
419 | // Widget getListView() {
420 | // return Container(
421 | // height:600.0,
422 | //
423 | // ///总高度
424 | // color: Colors.amberAccent,
425 | // child: Column(
426 | // children: [
427 | // Container(
428 | // color: Colors.deepOrangeAccent,
429 | // height: 10.0,
430 | // ),
431 | // Expanded(child: newListView())
432 | // ],
433 | // ),
434 | // );
435 | // }
436 | //
437 | // Widget newListView() {
438 | // return OverscrollNotificationWidget(
439 | // child: ListView.builder(
440 | // itemBuilder: (BuildContext context, int index) {
441 | // return Text('data=$index');
442 | // },
443 | // itemCount: 100,
444 | // ///这个属性是用来断定滚动的部件的物理特性,例如:
445 | // ///scrollStart
446 | // ///ScrollUpdate
447 | // ///Overscroll
448 | // ///ScrollEnd
449 | // ///在Android和ios等平台,其默认值是不同的。我们可以在scroll_configuration.dart中看到如下配置
450 | //
451 | /////下面代码是我在翻源码找到的解决方案
452 | ///// The scroll physics to use for the platform given by [getPlatform].
453 | // ///
454 | // /// Defaults to [BouncingScrollPhysics] on iOS and [ClampingScrollPhysics] on
455 | // /// Android.
456 | //// ScrollPhysics getScrollPhysics(BuildContext context) {
457 | //// switch (getPlatform(context)) {
458 | //// case TargetPlatform.iOS:/*/
459 | //// return const BouncingScrollPhysics();
460 | //// case TargetPlatform.android:
461 | //// case TargetPlatform.fuchsia:
462 | //// return const ClampingScrollPhysics();
463 | //// }
464 | //// return null;
465 | //// }
466 | // ///在ios中,默认返回BouncingScrollPhysics,对于[BouncingScrollPhysics]而言,
467 | // ///由于 double applyBoundaryConditions(ScrollMetrics position, double value) => 0.0;
468 | // ///会导致:当listview的第一条目显示时,继续下拉时,不会调用上面提到的Overscroll监听。
469 | // ///故这里,设定为[ClampingScrollPhysics]
470 | // physics: const ClampingScrollPhysics(),
471 | // ),
472 | // scrollListener: _scrollListener,
473 | // );
474 | // }
475 | //
476 | // void _scrollListener(
477 | // double dragDistance, ScrollNotificationListener isDragEnd) {
478 | // controller.updateDragDistance(dragDistance, isDragEnd);
479 | // }
480 | //}
481 | ///
482 |
--------------------------------------------------------------------------------
/lib/widgets/scrollView/FlutterCustomScrollView.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class FlutterCustomScrollView extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) {
6 | return Scaffold(
7 | body: SafeArea(
8 | child: CustomScrollView(
9 | slivers: [
10 | SliverToBoxAdapter(child: _buildSearch(),),
11 | SliverGrid(
12 | gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
13 | maxCrossAxisExtent: 200.0,
14 | mainAxisSpacing: 10.0,
15 | crossAxisSpacing: 10.0,
16 | childAspectRatio: 4.0,
17 | ),
18 | delegate: SliverChildBuilderDelegate(
19 | (BuildContext context, int index) {
20 | return Container(
21 | alignment: Alignment.center,
22 | color: Colors.teal[100 * (index % 9)],
23 | child: Text('grid item $index'),
24 | );
25 | },
26 | childCount: 20,
27 | ),
28 | ),
29 | SliverFixedExtentList(
30 | itemExtent: 50.0,
31 | delegate: SliverChildBuilderDelegate(
32 | (BuildContext context, int index) {
33 | return Container(
34 | alignment: Alignment.center,
35 | color: Colors.lightBlue[100 * (index % 9)],
36 | child: Text('list item $index'),
37 | );
38 | },
39 | ),
40 | ),
41 | ],
42 | )),
43 | );
44 | }
45 | }
46 |
47 | Widget _buildSearch() {
48 | return Card(
49 | margin: EdgeInsets.fromLTRB(15.0, 10.0, 15.0, 10.0),
50 | elevation: 1.0,
51 | shape: RoundedRectangleBorder(
52 | borderRadius: BorderRadius.all(Radius.circular(50.0)),
53 | ),
54 | child: Container(
55 | padding: EdgeInsets.only(left: 25.0, right: 25.0),
56 | height: 45.0,
57 | child: Center(
58 | child: Row(
59 | children: [
60 | Padding(
61 | padding: EdgeInsets.only(right: 8.0),
62 | child: Icon(
63 | Icons.search,
64 | color: Colors.black26,
65 | size: 20.0,
66 | ),
67 | ),
68 | Expanded(
69 | child: TextField(
70 | keyboardType: TextInputType.text,
71 | decoration: InputDecoration(
72 | border: InputBorder.none,
73 | hintText: 'Search category',
74 | hintStyle: TextStyle(color: Colors.black26)),
75 | cursorColor: Colors.pink,
76 | ))
77 | ],
78 | ),
79 | ),
80 | ),
81 | );
82 | }
--------------------------------------------------------------------------------
/lib/widgets/scrollView/FlutterNestedScrollView.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'dart:math' as math;
3 |
4 | //const NestedScrollView({
5 | //Key key,
6 | //this.controller,
7 | //this.scrollDirection = Axis.vertical,
8 | //this.reverse = false,
9 | //this.physics,
10 | //@required List Function(BuildContext context, bool innerBoxIsScrolled) this.headerSliverBuilder,
11 | //@required this.body,
12 | //})
13 | //实现搜索框隐藏,TabBar切换悬浮吸顶。主要使用自定义_SliverAppBarDelegate
14 | class FlutterNestedScrollView extends StatelessWidget {
15 | @override
16 | Widget build(BuildContext context) {
17 | return Scaffold(
18 | body: SafeArea(
19 | child: NestedScrollView(
20 | headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
21 | return [
22 | SliverPersistentHeader(
23 | pinned: false,
24 | delegate: _SliverAppBarDelegate(
25 | maxHeight: 60.0,
26 | minHeight: 60.0,
27 | child: Container(
28 | child: _buildSearch(),
29 | ))),
30 | SliverPersistentHeader(
31 | pinned: true,
32 | delegate: _SliverAppBarDelegate(
33 | maxHeight: 49.0,
34 | minHeight: 49.0,
35 | child: Container(
36 | color: Colors.white,
37 | child: FlutterTabBar(),
38 | )))
39 | ];
40 | },
41 | body: ListView.builder(
42 | itemBuilder: (BuildContext context, int index) {
43 | return Text("fjwoijefoi$index");
44 | },
45 | itemCount: 100,
46 | ),
47 | )),
48 | );
49 | }
50 | }
51 |
52 | class FlutterTabBar extends StatefulWidget {
53 | FlutterTabBar({Key key}) : super(key: key);
54 |
55 | @override
56 | State createState() {
57 | return _FlutterTabBarState();
58 | }
59 | }
60 |
61 | class _FlutterTabBarState extends State
62 | with SingleTickerProviderStateMixin {
63 | Color selectColor, unselectedColor;
64 | TextStyle selectStyle, unselectedStyle;
65 | var titleList = ['电影', '电视', '综艺', '读书', '音乐', '同城'];
66 |
67 | List tabList;
68 |
69 | TabController _tabController;
70 |
71 | @override
72 | void initState() {
73 | super.initState();
74 | selectColor = Color.fromARGB(255, 45, 45, 45);
75 | unselectedColor = Color.fromARGB(255, 117, 117, 117);
76 | selectStyle = TextStyle(fontSize: 18, color: selectColor);
77 | unselectedStyle = TextStyle(fontSize: 18, color: selectColor);
78 | tabList = getTabList();
79 | _tabController = TabController(vsync: this, length: tabList.length);
80 | }
81 |
82 | List getTabList() {
83 | return titleList
84 | .map((item) => Text(
85 | '$item',
86 | style: TextStyle(fontSize: 18),
87 | ))
88 | .toList();
89 | }
90 |
91 | @override
92 | Widget build(BuildContext context) {
93 | //Tab小部件列表
94 | // List @required this.tabs,
95 | //组件选中以及动画的状态
96 | // TabController this.controller,
97 | //Tab是否可滑动
98 | // bool this.isScrollable = false,
99 | //选项卡下方的导航条的颜色
100 | // Color this.indicatorColor,
101 | //选项卡下方的导航条的线条粗细
102 | // double this.indicatorWeight = 2.0,
103 | // EdgeInsetsGeometry this.indicatorPadding = EdgeInsets.zero,
104 | // Decoration this.indicator,
105 | // TabBarIndicatorSize this.indicatorSize,导航条的长度,(tab:默认等分;label:跟标签长度一致)
106 | // Color this.labelColor,所选标签标签的颜色
107 | // TextStyle this.labelStyle,所选标签标签的文本样式
108 | // EdgeInsetsGeometry this.labelPadding,,所选标签标签的内边距
109 | // Color this.unselectedLabelColor,未选定标签标签的颜色
110 | // TextStyle this.unselectedLabelStyle,未选中标签标签的文字样式
111 | // void Function(T value) this.onTap,按下时的响应事件
112 |
113 | return Container(
114 | margin: EdgeInsets.only(top: 10.0, bottom: 10.0),
115 | child: TabBar(
116 | tabs: tabList,
117 | isScrollable: true,
118 | controller: _tabController,
119 | indicatorColor: selectColor,
120 | labelColor: selectColor,
121 | labelStyle: selectStyle,
122 | unselectedLabelColor: unselectedColor,
123 | unselectedLabelStyle: unselectedStyle,
124 | indicatorSize: TabBarIndicatorSize.label,
125 | ),
126 | );
127 | }
128 | }
129 |
130 | Widget _buildSearch() {
131 | return Card(
132 | margin: EdgeInsets.fromLTRB(15.0, 10.0, 15.0, 10.0),
133 | elevation: 1.0,
134 | shape: RoundedRectangleBorder(
135 | borderRadius: BorderRadius.all(Radius.circular(50.0)),
136 | ),
137 | child: Container(
138 | padding: EdgeInsets.only(left: 25.0, right: 25.0),
139 | height: 45.0,
140 | child: Center(
141 | child: Row(
142 | children: [
143 | Padding(
144 | padding: EdgeInsets.only(right: 8.0),
145 | child: Icon(
146 | Icons.search,
147 | color: Colors.black26,
148 | size: 20.0,
149 | ),
150 | ),
151 | Expanded(
152 | child: TextField(
153 | keyboardType: TextInputType.text,
154 | decoration: InputDecoration(
155 | border: InputBorder.none,
156 | hintText: 'Search category',
157 | hintStyle: TextStyle(color: Colors.black26)),
158 | cursorColor: Colors.pink,
159 | ))
160 | ],
161 | ),
162 | ),
163 | ),
164 | );
165 | }
166 |
167 | class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
168 | _SliverAppBarDelegate({
169 | @required this.minHeight,
170 | @required this.maxHeight,
171 | @required this.child,
172 | });
173 |
174 | final double minHeight;
175 | final double maxHeight;
176 | final Widget child;
177 |
178 | @override
179 | double get minExtent => minHeight;
180 |
181 | @override
182 | double get maxExtent => math.max(maxHeight, minHeight);
183 |
184 | @override
185 | Widget build(
186 | BuildContext context, double shrinkOffset, bool overlapsContent) {
187 | return child;
188 | }
189 |
190 | @override
191 | bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
192 | return maxHeight != oldDelegate.maxHeight ||
193 | minHeight != oldDelegate.minHeight ||
194 | child != oldDelegate.child;
195 | }
196 | }
197 |
--------------------------------------------------------------------------------
/lib/widgets/scrollView/FlutterSliverToBoxAdapter.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | //列表支持水平区域水平滚动,垂直区域垂直滚动。
4 | class FlutterSliverToBoxAdapter extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return Scaffold(body: SafeArea(child: CustomScrollView(
8 | scrollDirection: Axis.vertical,
9 | slivers: [
10 | SliverToBoxAdapter(
11 | child: Container(
12 | height: 140.0,
13 | child: ListView.builder(
14 | itemBuilder: (context, index) {
15 | return Text("SliverToBoxAdapter${index}");
16 | },
17 | itemCount: 40,
18 | scrollDirection: Axis.horizontal,//水平滚动
19 | ),
20 | ),
21 | ),
22 | SliverList(
23 | delegate: SliverChildBuilderDelegate((context, index) {
24 | return Text("SliverList${index}");
25 | }, childCount: 150),
26 | )
27 | ],
28 | )),);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lib/widgets/sliver/README.md:
--------------------------------------------------------------------------------
1 | # Slivers
2 |
3 | 教程:[Flutter:Slivers大家族,让滑动视图的组合变得很简单!](https://www.jianshu.com/p/690ddade5d94)
4 |
5 | 效果图:
6 |
7 | 
--------------------------------------------------------------------------------
/lib/widgets/sliver/sliver_box.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter_app/sharedelement/product_list.dart';
5 |
6 | class SliverBoxPage extends StatelessWidget {
7 | @override
8 | Widget build(BuildContext context) {
9 | return Scaffold(
10 | appBar: AppBar(
11 | title: Text('SliverToBoxAdapter'),
12 | ),
13 | body: CustomScrollView(
14 | physics: ScrollPhysics(),
15 | slivers: [
16 | SliverToBoxAdapter(
17 | child: _buildHeader(),
18 | ),
19 | SliverGrid.count(
20 | crossAxisCount: 3,
21 | children: products.map((product) {
22 | return _buildItemGrid(product);
23 | }).toList(),
24 | ),
25 | SliverToBoxAdapter(
26 | child: _buildSearch(),
27 | ),
28 | SliverFixedExtentList(
29 | itemExtent: 100.0,
30 | delegate: SliverChildListDelegate(
31 | products.map((product) {
32 | return _buildItemList(product);
33 | }).toList(),
34 | ),
35 | ),
36 | SliverToBoxAdapter(
37 | child: _buildFooter(),
38 | ),
39 | ],
40 | ),
41 | );
42 | }
43 |
44 | Widget _buildFooter() {
45 | return Container(
46 | height: 100.0,
47 | decoration: BoxDecoration(
48 | backgroundBlendMode: BlendMode.plus,
49 | image: DecorationImage(
50 | image: AssetImage('images/footer.jpeg'),
51 | fit: BoxFit.cover,
52 | ),
53 | color: Colors.white),
54 | child: BackdropFilter(
55 | filter: ImageFilter.blur(sigmaX: 20.0, sigmaY: 20.0),
56 | child: Container(
57 | child: Center(
58 | child: Text(
59 | 'This is footer',
60 | style: TextStyle(
61 | fontSize: 20.0,
62 | fontWeight: FontWeight.bold,
63 | color: Colors.black54,
64 | ),
65 | ),
66 | ),
67 | ),
68 | ),
69 | );
70 | }
71 |
72 | Widget _buildHeader() {
73 | return Container(
74 | padding: EdgeInsets.all(15.0),
75 | height: 100.0,
76 | child: Row(
77 | children: [
78 | Expanded(
79 | child: Column(
80 | mainAxisAlignment: MainAxisAlignment.center,
81 | crossAxisAlignment: CrossAxisAlignment.start,
82 | children: [
83 | Text(
84 | '吉原拉面',
85 | style: TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
86 | ),
87 | Padding(
88 | padding: EdgeInsets.only(top: 6.0),
89 | child: Row(
90 | children: [
91 | Icon(
92 | Icons.favorite_border,
93 | color: Colors.black26,
94 | size: 12.0,
95 | ),
96 | Padding(
97 | padding: EdgeInsets.only(left: 4.0),
98 | child: Text(
99 | 'yumi',
100 | style: TextStyle(color: Colors.black26),
101 | ),
102 | )
103 | ],
104 | ),
105 | ),
106 | ],
107 | ),
108 | ),
109 | ClipRRect(
110 | child: SizedBox(
111 | width: 60.0,
112 | height: 60.0,
113 | child: Image.asset(
114 | 'images/shop.jpeg',
115 | fit: BoxFit.cover,
116 | ),
117 | ),
118 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
119 | )
120 | ],
121 | ),
122 | );
123 | }
124 |
125 | Widget _buildSearch() {
126 | return Card(
127 | margin: EdgeInsets.fromLTRB(15.0, 10.0, 15.0, 10.0),
128 | elevation: 8.0,
129 | shape: RoundedRectangleBorder(
130 | borderRadius: BorderRadius.all(Radius.circular(50.0)),
131 | ),
132 | child: Container(
133 | padding: EdgeInsets.only(left: 25.0, right: 25.0),
134 | height: 45.0,
135 | child: Center(
136 | child: Row(
137 | children: [
138 | Padding(
139 | padding: EdgeInsets.only(right: 8.0),
140 | child: Icon(
141 | Icons.search,
142 | color: Colors.black26,
143 | size: 20.0,
144 | ),
145 | ),
146 | Expanded(
147 | child: TextField(
148 | keyboardType: TextInputType.text,
149 | decoration: InputDecoration(
150 | border: InputBorder.none,
151 | hintText: 'Search category',
152 | hintStyle: TextStyle(color: Colors.black26)),
153 | cursorColor: Colors.pink,
154 | ))
155 | ],
156 | ),
157 | ),
158 | ),
159 | );
160 | }
161 |
162 | Widget _buildItemGrid(ProductItem product) {
163 | return Padding(
164 | padding: EdgeInsets.fromLTRB(0.0, 5.0, 0.0, 5.0),
165 | child: Card(
166 | child: Padding(
167 | padding: EdgeInsets.all(8.0),
168 | child: Column(
169 | mainAxisAlignment: MainAxisAlignment.center,
170 | children: [
171 | ClipRRect(
172 | child: SizedBox(
173 | width: 65.0,
174 | height: 65.0,
175 | child: Image.asset(
176 | product.asset,
177 | fit: BoxFit.cover,
178 | ),
179 | ),
180 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
181 | ),
182 | Expanded(
183 | child: Padding(
184 | padding: EdgeInsets.only(top: 6.0),
185 | child: Text(
186 | product.name,
187 | textAlign: TextAlign.center,
188 | overflow: TextOverflow.ellipsis,
189 | ),
190 | ),
191 | ),
192 | ],
193 | ),
194 | ),
195 | ),
196 | );
197 | }
198 |
199 | Widget _buildItemList(ProductItem product) {
200 | return Padding(
201 | padding: EdgeInsets.fromLTRB(0.0, 5.0, 0.0, 5.0),
202 | child: Card(
203 | child: Padding(
204 | padding: EdgeInsets.all(8.0),
205 | child: Row(
206 | mainAxisAlignment: MainAxisAlignment.center,
207 | children: [
208 | Padding(
209 | padding: EdgeInsets.only(left: 20.0),
210 | child: ClipRRect(
211 | child: SizedBox(
212 | width: 65.0,
213 | height: 65.0,
214 | child: Image.asset(
215 | product.asset,
216 | fit: BoxFit.cover,
217 | ),
218 | ),
219 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
220 | ),
221 | ),
222 | Expanded(
223 | child: Padding(
224 | padding: EdgeInsets.only(left: 15.0),
225 | child: Text(
226 | product.name,
227 | overflow: TextOverflow.ellipsis,
228 | ),
229 | ),
230 | ),
231 | ],
232 | ),
233 | ),
234 | ),
235 | );
236 | }
237 | }
238 |
--------------------------------------------------------------------------------
/lib/widgets/sliver/sliver_expanded_appbar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/sharedelement/product_list.dart';
3 |
4 | class ExpandedAppBarPage extends StatefulWidget {
5 | @override
6 | State createState() => _ExpandedAppBarState();
7 | }
8 |
9 | class _ExpandedAppBarState extends State {
10 | bool floating = false;
11 | bool snap = false;
12 | bool pinned = false;
13 | String text = "fewofweoi";
14 |
15 | @override
16 | Widget build(BuildContext context) {
17 | return Material(
18 | child: CustomScrollView(
19 | slivers: [
20 | SliverAppBar(
21 | actions: [
22 | _buildAction(),
23 | ],
24 | title: Text('$text'),
25 | backgroundColor: Theme.of(context).accentColor,
26 | expandedHeight: 250.0,
27 | flexibleSpace: FlexibleSpaceBar(
28 | background:
29 | Image.asset('assets/images/food01.jpeg', fit: BoxFit.cover),
30 | ),
31 | floating: floating,
32 | snap: snap,
33 | pinned: pinned,
34 | ),
35 | SliverFixedExtentList(
36 | itemExtent: 120.0,
37 | delegate: SliverChildListDelegate(
38 | products.map((product) {
39 | return _buildItem(product);
40 | }).toList(),
41 | ),
42 | ),
43 | ],
44 | ),
45 | );
46 | }
47 |
48 | Widget _buildAction() {
49 | return PopupMenuButton(
50 | itemBuilder: (context) => [
51 | const PopupMenuItem(
52 | value: 0,
53 | child: Text('reset'),
54 | ),
55 | const PopupMenuItem(
56 | value: 1,
57 | child: Text('floating = true'),
58 | ),
59 | const PopupMenuItem(
60 | value: 2,
61 | child: Text('floating = true , snap = true'),
62 | ),
63 | const PopupMenuItem(
64 | value: 3,
65 | child: Text('pinned = true'),
66 | ),
67 | ],
68 | onSelected: (value) {
69 | switch (value) {
70 | case 0:
71 | setState(() {
72 | floating = false;
73 | snap = false;
74 | pinned = false;
75 | text = 'reset';
76 | });
77 | break;
78 | case 1:
79 | setState(() {
80 | floating = true;
81 | snap = false;
82 | pinned = false;
83 | text = 'floating = true';
84 | });
85 | break;
86 | case 2:
87 | setState(() {
88 | floating = true;
89 | snap = true;
90 | pinned = false;
91 | text = 'floating = true , snap = true';
92 | });
93 | break;
94 | case 3:
95 | setState(() {
96 | floating = false;
97 | snap = false;
98 | pinned = true;
99 | text = 'pinned = true';
100 | });
101 | break;
102 | }
103 | },
104 | );
105 | }
106 |
107 | Widget _buildItem(ProductItem product) {
108 | return Container(
109 | margin: EdgeInsets.all(15.0),
110 | child: Stack(
111 | alignment: AlignmentDirectional.centerStart,
112 | children: [
113 | Positioned(
114 | left: 60.0,
115 | child: Card(
116 | child: Container(
117 | margin: EdgeInsets.only(left: 50.0),
118 | child: Text(
119 | product.name,
120 | style: Theme.of(context).textTheme.title,
121 | ),
122 | ),
123 | )),
124 | ClipRRect(
125 | child: SizedBox(
126 | width: 90.0,
127 | height: 90.0,
128 | child: Image.asset(
129 | product.asset,
130 | fit: BoxFit.cover,
131 | ),
132 | ),
133 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
134 | ),
135 | ],
136 | ),
137 | );
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/lib/widgets/sliver/sliver_grid.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/sharedelement/product_list.dart';
3 |
4 | final List _products = [
5 | ProductItem(
6 | name: 'Bueno Chocolate',
7 | asset: 'images/food01.jpeg',
8 | ),
9 | ProductItem(
10 | name: 'Chocolate with berries',
11 | asset: 'images/food02.jpeg',
12 | ),
13 | ProductItem(
14 | name: 'Trumoo Candies',
15 | asset: 'images/food03.jpeg',
16 | ),
17 | ProductItem(
18 | name: 'Choco-coko',
19 | asset: 'images/food04.jpeg',
20 | ),
21 | ProductItem(
22 | name: 'Chocolate tree',
23 | asset: 'images/food05.jpeg',
24 | ),
25 | ProductItem(
26 | name: 'Chocolate',
27 | asset: 'images/food06.jpeg',
28 | ),
29 | ProductItem(
30 | name: 'Bueno Chocolate',
31 | asset: 'images/food01.jpeg',
32 | ),
33 | ProductItem(
34 | name: 'Choco-coko',
35 | asset: 'images/food04.jpeg',
36 | ),
37 | ProductItem(
38 | name: 'Chocolate tree',
39 | asset: 'images/food05.jpeg',
40 | ),
41 | ];
42 |
43 | class SliverGridPage extends StatelessWidget {
44 | @override
45 | Widget build(BuildContext context) {
46 | return Scaffold(
47 | appBar: AppBar(
48 | title: Text('SliverGrid'),
49 | ),
50 | body: CustomScrollView(
51 | slivers: [
52 | SliverGrid(
53 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
54 | crossAxisCount: 2,
55 | ),
56 | delegate: SliverChildBuilderDelegate(
57 | (BuildContext context, int index) {
58 | return _buildItem(context, _products[index]);
59 | },
60 | childCount: _products.length,
61 | ),
62 | )
63 | ],
64 | ),
65 | );
66 | }
67 |
68 | Widget _buildItem(BuildContext context, ProductItem product) {
69 | return Padding(
70 | padding: EdgeInsets.all(8.0),
71 | child: Card(
72 | child: Padding(
73 | padding: EdgeInsets.all(10.0),
74 | child: Column(
75 | mainAxisAlignment: MainAxisAlignment.center,
76 | children: [
77 | ClipRRect(
78 | child: SizedBox(
79 | width: 65.0,
80 | height: 65.0,
81 | child: Image.asset(
82 | product.asset,
83 | fit: BoxFit.cover,
84 | ),
85 | ),
86 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
87 | ),
88 | Expanded(
89 | child: Padding(
90 | padding: EdgeInsets.only(top: 6.0),
91 | child: Text(
92 | product.name,
93 | style: Theme.of(context).textTheme.title,
94 | textAlign: TextAlign.center,
95 | ),
96 | ),
97 | ),
98 | ],
99 | ),
100 | ),
101 | ),
102 | );
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/lib/widgets/sliver/sliver_header.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'dart:math' as math;
5 |
6 | import 'package:flutter_app/sharedelement/product_list.dart';
7 |
8 | final List titleAssets = [
9 | 'images/food01.jpeg',
10 | 'images/food02.jpeg',
11 | 'images/food03.jpeg',
12 | ];
13 |
14 | final List _products = [
15 | ProductItem(
16 | name: 'Bueno Chocolate',
17 | asset: 'images/food01.jpeg',
18 | ),
19 | ProductItem(
20 | name: 'Chocolate with berries',
21 | asset: 'images/food02.jpeg',
22 | ),
23 | ProductItem(
24 | name: 'Trumoo Candies',
25 | asset: 'images/food03.jpeg',
26 | ),
27 | ProductItem(
28 | name: 'Choco-coko',
29 | asset: 'images/food04.jpeg',
30 | ),
31 | ProductItem(
32 | name: 'Chocolate tree',
33 | asset: 'images/food05.jpeg',
34 | ),
35 | ProductItem(
36 | name: 'Chocolate',
37 | asset: 'images/food06.jpeg',
38 | ),
39 | ProductItem(
40 | name: 'Bueno Chocolate',
41 | asset: 'images/food01.jpeg',
42 | ),
43 | ProductItem(
44 | name: 'Choco-coko',
45 | asset: 'images/food04.jpeg',
46 | ),
47 | ProductItem(
48 | name: 'Chocolate tree',
49 | asset: 'images/food05.jpeg',
50 | ),
51 | ];
52 |
53 | final List _products2 =[]..addAll(_products)..addAll(_products);
54 |
55 | class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
56 | _SliverAppBarDelegate({
57 | @required this.minHeight,
58 | @required this.maxHeight,
59 | @required this.child,
60 | });
61 |
62 | final double minHeight;
63 | final double maxHeight;
64 | final Widget child;
65 |
66 | @override
67 | double get minExtent => minHeight;
68 |
69 | @override
70 | double get maxExtent => math.max(maxHeight, minHeight);
71 |
72 | @override
73 | Widget build(
74 | BuildContext context, double shrinkOffset, bool overlapsContent) {
75 | return new SizedBox.expand(child: child);
76 | }
77 |
78 | @override
79 | bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
80 | return maxHeight != oldDelegate.maxHeight ||
81 | minHeight != oldDelegate.minHeight ||
82 | child != oldDelegate.child;
83 | }
84 | }
85 |
86 | class SliverHeaderPage extends StatefulWidget {
87 | const SliverHeaderPage({Key key}) : super(key: key);
88 |
89 | @override
90 | State createState() => _CollapsingState();
91 | }
92 |
93 | class _CollapsingState extends State {
94 | bool floating = false;
95 | bool pinned = true;
96 |
97 | @override
98 | Widget build(BuildContext context) {
99 | return Scaffold(
100 | appBar: AppBar(
101 | title: Text('SliverHeader'),
102 | actions: [
103 | _buildAction(),
104 | ],
105 | ),
106 | body: CustomScrollView(
107 | slivers: [
108 | _buildHeader(0),
109 | SliverGrid.count(
110 | crossAxisCount: 3,
111 | children: _products.map((product) {
112 | return _buildItemGrid(product);
113 | }).toList(),
114 | ),
115 | _buildHeader(1),
116 | SliverFixedExtentList(
117 | itemExtent: 100.0,
118 | delegate: SliverChildListDelegate(
119 | products.map((product) {
120 | return _buildItemList(product);
121 | }).toList(),
122 | ),
123 | ),
124 | _buildHeader(2),
125 | SliverGrid(
126 | gridDelegate: new SliverGridDelegateWithMaxCrossAxisExtent(
127 | maxCrossAxisExtent: 200.0,
128 | mainAxisSpacing: 10.0,
129 | crossAxisSpacing: 10.0,
130 | childAspectRatio: 3.0,
131 | ),
132 | delegate: new SliverChildBuilderDelegate(
133 | (BuildContext context, int index) {
134 | return _buildItemGrid2(_products2[index]);
135 | },
136 | childCount: _products2.length,
137 | ),
138 | ),
139 | ],
140 | ),
141 | );
142 | }
143 |
144 | Widget _buildAction() {
145 | return PopupMenuButton(
146 | itemBuilder: (context) => [
147 | const PopupMenuItem(
148 | value: 0,
149 | child: Text('reset'),
150 | ),
151 | const PopupMenuItem(
152 | value: 1,
153 | child: Text('floating'),
154 | ),
155 | const PopupMenuItem(
156 | value: 2,
157 | child: Text('pinned'),
158 | ),
159 | ],
160 | onSelected: (value) {
161 | switch (value) {
162 | case 0:
163 | setState(() {
164 | floating = false;
165 | pinned = false;
166 | });
167 | break;
168 | case 1:
169 | setState(() {
170 | floating = true;
171 | pinned = false;
172 | });
173 | break;
174 | case 2:
175 | setState(() {
176 | floating = false;
177 | pinned = true;
178 | });
179 | break;
180 | }
181 | },
182 | );
183 | }
184 |
185 | SliverPersistentHeader _buildHeader(int index) {
186 | String asset = titleAssets[index];
187 | return SliverPersistentHeader(
188 | pinned: pinned,
189 | floating: floating,
190 | delegate: _SliverAppBarDelegate(
191 | minHeight: 60.0,
192 | maxHeight: 180.0,
193 | child: Container(
194 | decoration: BoxDecoration(
195 | backgroundBlendMode: BlendMode.plus,
196 | image: DecorationImage(
197 | image: AssetImage(asset),
198 | fit: BoxFit.fill,
199 | ),
200 | color: Colors.white),
201 | child: BackdropFilter(
202 | filter: ImageFilter.blur(sigmaX: 20.0, sigmaY: 20.0),
203 | child: Container(
204 | child: Center(
205 | child: Text(
206 | 'This is header ${index + 1}',
207 | style: TextStyle(
208 | fontSize: 20.0,
209 | fontWeight: FontWeight.bold,
210 | color: Color(0xE5FFFFFF),
211 | ),
212 | ),
213 | ),
214 | ),
215 | ),
216 | ),
217 | ),
218 | );
219 | }
220 |
221 | Widget _buildItemGrid(ProductItem product) {
222 | return Padding(
223 | padding: EdgeInsets.fromLTRB(0.0, 5.0, 0.0, 5.0),
224 | child: Card(
225 | child: Padding(
226 | padding: EdgeInsets.all(8.0),
227 | child: Column(
228 | mainAxisAlignment: MainAxisAlignment.center,
229 | children: [
230 | ClipRRect(
231 | child: SizedBox(
232 | width: 65.0,
233 | height: 65.0,
234 | child: Image.asset(
235 | product.asset,
236 | fit: BoxFit.cover,
237 | ),
238 | ),
239 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
240 | ),
241 | Expanded(
242 | child: Padding(
243 | padding: EdgeInsets.only(top: 6.0),
244 | child: Text(
245 | product.name,
246 | textAlign: TextAlign.center,
247 | overflow: TextOverflow.ellipsis,
248 | ),
249 | ),
250 | ),
251 | ],
252 | ),
253 | ),
254 | ),
255 | );
256 | }
257 |
258 | Widget _buildItemList(ProductItem product) {
259 | return Padding(
260 | padding: EdgeInsets.fromLTRB(0.0, 5.0, 0.0, 5.0),
261 | child: Card(
262 | child: Padding(
263 | padding: EdgeInsets.all(8.0),
264 | child: Row(
265 | mainAxisAlignment: MainAxisAlignment.center,
266 | children: [
267 | Padding(
268 | padding: EdgeInsets.only(left: 20.0),
269 | child: ClipRRect(
270 | child: SizedBox(
271 | width: 65.0,
272 | height: 65.0,
273 | child: Image.asset(
274 | product.asset,
275 | fit: BoxFit.cover,
276 | ),
277 | ),
278 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
279 | ),
280 | ),
281 | Expanded(
282 | child: Padding(
283 | padding: EdgeInsets.only(left: 15.0),
284 | child: Text(
285 | product.name,
286 | overflow: TextOverflow.ellipsis,
287 | ),
288 | ),
289 | ),
290 | ],
291 | ),
292 | ),
293 | ),
294 | );
295 | }
296 |
297 | Widget _buildItemGrid2(ProductItem product) {
298 | return Padding(
299 | padding: EdgeInsets.fromLTRB(0.0, 5.0, 0.0, 5.0),
300 | child: Card(
301 | child: Padding(
302 | padding: EdgeInsets.all(8.0),
303 | child: Row(
304 | mainAxisAlignment: MainAxisAlignment.center,
305 | children: [
306 | Padding(
307 | padding: EdgeInsets.only(left: 10.0),
308 | child: ClipRRect(
309 | child: SizedBox(
310 | width: 20.0,
311 | height: 20.0,
312 | child: Image.asset(
313 | product.asset,
314 | fit: BoxFit.cover,
315 | ),
316 | ),
317 | borderRadius: BorderRadius.all(Radius.circular(5.0)),
318 | ),
319 | ),
320 | Expanded(
321 | child: Padding(
322 | padding: EdgeInsets.only(left: 6.0),
323 | child: Text(
324 | product.name,
325 | overflow: TextOverflow.ellipsis,
326 | ),
327 | ),
328 | ),
329 | ],
330 | ),
331 | ),
332 | ),
333 | );
334 | }
335 | }
336 |
--------------------------------------------------------------------------------
/lib/widgets/sliver/sliver_list.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/sharedelement/product_list.dart';
3 |
4 | class SliverListPage extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return Scaffold(
8 | appBar: AppBar(
9 | title: Text('SliverList'),
10 | ),
11 | body: CustomScrollView(
12 | slivers: [
13 | SliverList(
14 | delegate: SliverChildBuilderDelegate(
15 | (BuildContext context, int index) {
16 | return _buildItem(context, products[index]);
17 | },
18 | childCount: products.length,
19 | ),
20 | )
21 | ],
22 | ),
23 | );
24 | }
25 |
26 | Widget _buildItem(BuildContext context, ProductItem product) {
27 | return Container(
28 | height: 120.0,
29 | margin: EdgeInsets.fromLTRB(15.0, 5.0, 15.0, 5.0),
30 | child: Stack(
31 | alignment: AlignmentDirectional.centerStart,
32 | children: [
33 | Positioned(
34 | left: 30.0,
35 | child: Card(
36 | child: Container(
37 | margin: EdgeInsets.only(left: 50.0),
38 | child: Text(
39 | product.name,
40 | style: Theme.of(context).textTheme.title,
41 | ),
42 | ),
43 | )),
44 | ClipRRect(
45 | child: SizedBox(
46 | width: 70.0,
47 | height: 70.0,
48 | child: Image.asset(
49 | product.asset,
50 | fit: BoxFit.cover,
51 | ),
52 | ),
53 | borderRadius: BorderRadius.all(Radius.circular(8.0)),
54 | ),
55 | ],
56 | ),
57 | );
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/lib/widgets/sliver/sliver_menu.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_app/widgets/sliver/sliver_expanded_appbar.dart';
3 | import 'package:flutter_app/widgets/sliver/sliver_box.dart';
4 | import 'package:flutter_app/widgets/sliver/sliver_grid.dart';
5 | import 'package:flutter_app/widgets/sliver/sliver_header.dart';
6 | import 'package:flutter_app/widgets/sliver/sliver_list.dart';
7 |
8 | class _MenuData {
9 | const _MenuData({
10 | this.title,
11 | });
12 |
13 | final String title;
14 | }
15 |
16 | final List<_MenuData> menus = [
17 | const _MenuData(
18 | title: 'SliverAppBar',
19 | ),
20 | const _MenuData(
21 | title: 'SliverList',
22 | ),
23 | const _MenuData(
24 | title: 'SliverGrid',
25 | ),
26 | const _MenuData(
27 | title: 'SliverPersistentHeader',
28 | ),
29 | const _MenuData(
30 | title: 'SliverToBoxAdapter',
31 | ),
32 | ];
33 |
34 | class _MenuDataItem extends StatelessWidget {
35 | const _MenuDataItem(this.data);
36 |
37 | final _MenuData data;
38 |
39 | void _pushRoute(BuildContext context, String title) {
40 | switch (title) {
41 | case 'SliverAppBar':
42 | Navigator.of(context).push(MaterialPageRoute(builder: (context) {
43 | return ExpandedAppBarPage();
44 | }));
45 | break;
46 | case 'SliverList':
47 | Navigator.of(context).push(MaterialPageRoute(builder: (context) {
48 | return SliverListPage();
49 | }));
50 | break;
51 | case 'SliverGrid':
52 | Navigator.of(context).push(MaterialPageRoute(builder: (context) {
53 | return SliverGridPage();
54 | }));
55 | break;
56 | case 'SliverPersistentHeader':
57 | Navigator.of(context).push(MaterialPageRoute(builder: (context) {
58 | return SliverHeaderPage();
59 | }));
60 | break;
61 | case 'SliverToBoxAdapter':
62 | Navigator.of(context).push(MaterialPageRoute(builder: (context) {
63 | return SliverBoxPage();
64 | }));
65 | break;
66 | }
67 | }
68 |
69 | @override
70 | Widget build(BuildContext context) {
71 | return GestureDetector(
72 | behavior: HitTestBehavior.translucent,
73 | onTap: () {
74 | _pushRoute(context, data.title);
75 | },
76 | child: Container(
77 | height: 80.0,
78 | margin: EdgeInsets.fromLTRB(10.0, 4.0, 10.0, 4.0),
79 | child: Card(
80 | child: Padding(
81 | padding: const EdgeInsets.all(16.0),
82 | child: Center(
83 | child: Text(
84 | data.title,
85 | style: Theme.of(context).textTheme.subhead,
86 | ),
87 | ),
88 | ),
89 | ),
90 | ),
91 | );
92 | }
93 | }
94 |
95 | class SliverPage extends StatelessWidget {
96 | @override
97 | Widget build(BuildContext context) {
98 | return new Scaffold(
99 | appBar: new AppBar(
100 | title: new Text('Slivers'),
101 | ),
102 | body: new SafeArea(
103 | top: false,
104 | bottom: false,
105 | child: Container(
106 | decoration: BoxDecoration(
107 | gradient: LinearGradient(
108 | begin: Alignment.topLeft,
109 | end: Alignment.bottomRight,
110 | colors: [
111 | Colors.white,
112 | Colors.pinkAccent,
113 | ],
114 | ),
115 | ),
116 | child: ListView.builder(
117 | itemBuilder: (context, index) {
118 | return _MenuDataItem(menus[index]);
119 | },
120 | itemCount: menus.length,
121 | ),
122 | ),
123 | ));
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: flutter_app
2 | description: A new Flutter application.
3 |
4 | # The following defines the version and build number for your application.
5 | # A version number is three numbers separated by dots, like 1.2.43
6 | # followed by an optional build number separated by a +.
7 | # Both the version and the builder number may be overridden in flutter
8 | # build by specifying --build-name and --build-number, respectively.
9 | # Read more about versioning at semver.org.
10 | version: 1.0.0+1
11 |
12 | environment:
13 | sdk: ">=2.0.0-dev.68.0 <3.0.0"
14 |
15 | dependencies:
16 | flutter:
17 | sdk: flutter
18 |
19 | # The following adds the Cupertino Icons font to your application.
20 | # Use with the CupertinoIcons class for iOS style icons.
21 | cupertino_icons: ^0.1.2
22 |
23 | dev_dependencies:
24 | flutter_test:
25 | sdk: flutter
26 |
27 |
28 | # For information on the generic Dart part of this file, see the
29 | # following page: https://www.dartlang.org/tools/pub/pubspec
30 |
31 | # The following section is specific to Flutter.
32 | flutter:
33 |
34 | # The following line ensures that the Material Icons font is
35 | # included with your application, so that you can use the icons in
36 | # the material Icons class.
37 | uses-material-design: true
38 | assets:
39 | - assets/images/
40 | - images/
41 |
42 | # To add assets to your application, add an assets section, like this:
43 | # assets:
44 | # - images/a_dot_burr.jpeg
45 | # - images/a_dot_ham.jpeg
46 |
47 | # An image asset can refer to one or more resolution-specific "variants", see
48 | # https://flutter.io/assets-and-images/#resolution-aware.
49 |
50 | # For details regarding adding assets from package dependencies, see
51 | # https://flutter.io/assets-and-images/#from-packages
52 |
53 | # To add custom fonts to your application, add a fonts section here,
54 | # in this "flutter" section. Each entry in this list should have a
55 | # "family" key with the font family name, and a "fonts" key with a
56 | # list giving the asset and other descriptors for the font. For
57 | # example:
58 | # fonts:
59 | # - family: Schyler
60 | # fonts:
61 | # - asset: fonts/Schyler-Regular.ttf
62 | # - asset: fonts/Schyler-Italic.ttf
63 | # style: italic
64 | # - family: Trajan Pro
65 | # fonts:
66 | # - asset: fonts/TrajanPro.ttf
67 | # - asset: fonts/TrajanPro_Bold.ttf
68 | # weight: 700
69 | #
70 | # For details regarding fonts from package dependencies,
71 | # see https://flutter.io/custom-fonts/#from-packages
72 |
--------------------------------------------------------------------------------
/quaful-release.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kaina404/flutterDemo/46bb2d10ab4a745d4c164aaed319e0221a28131f/quaful-release.apk
--------------------------------------------------------------------------------
/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_app/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 |
--------------------------------------------------------------------------------