├── README.md ├── flutter_road_test ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── draftbk │ │ │ │ │ └── flutter_road_test │ │ │ │ │ └── MainActivity.java │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── 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 │ │ │ └── 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 ├── lib │ ├── counter.dart │ └── main.dart ├── pubspec.lock ├── pubspec.yaml ├── test │ ├── counter_test.dart │ └── widget_test.dart └── test_driver │ ├── app.dart │ └── app_test.dart ├── flutter_road_widgets ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── draftbk │ │ │ │ └── flutterroadwidgets │ │ │ │ └── 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 ├── images │ └── flutter.png ├── ios │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Podfile │ ├── 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 ├── lib │ ├── days │ │ ├── Day1.dart │ │ ├── Day10.dart │ │ ├── Day11.dart │ │ ├── Day12.dart │ │ ├── Day2.dart │ │ ├── Day3.dart │ │ ├── Day4.dart │ │ ├── Day5.dart │ │ ├── Day6.dart │ │ ├── Day7.dart │ │ └── Day8.dart │ ├── index.dart │ ├── main.dart │ ├── subpage │ │ ├── MySingleChooseDialog.dart │ │ └── TopBarPage.dart │ └── utils │ │ ├── carousel.dart │ │ ├── carousel_pro.dart │ │ ├── flutter_icon_icons.dart │ │ └── throttle_debounce.dart ├── pubspec.yaml └── test │ └── widget_test.dart └── notes ├── Dart_Intro.md ├── Flutter_Async.md ├── Flutter_Button.md ├── Flutter_Dialog.md ├── Flutter_Gridview.md ├── Flutter_Image.md ├── Flutter_Interview_Problem.md ├── Flutter_Listview.md ├── Flutter_NavigationBar.md ├── Flutter_Network.md ├── Flutter_Problem_Need_Solve.md ├── Flutter_Problem_Solved.md ├── Flutter_Tests.md └── Flutter_Text.md /README.md: -------------------------------------------------------------------------------- 1 | # Flutter 学习之路 2 | 3 | 一个 Flutter 应用,记录 Flutter 的学习过程。 哈哈哈感觉想往下写挺多的,不知道能不能坚持下去。(ง •̀_•́)ง 4 | 5 | ## 前期准备篇 6 | 7 | - [Dart 入门笔记](https://github.com/draftbk/flutter_road/blob/master/notes/Dart_Intro.md) 8 | - 环境配置(待写) 9 | 10 | ## 控件布局篇 11 | 12 | - [Flutter 学习之路 - Text](https://github.com/draftbk/flutter_road/blob/master/notes/Flutter_Text.md) 13 | - [Flutter 学习之路 - Button](https://github.com/draftbk/flutter_road/blob/master/notes/Flutter_Button.md) 14 | - [Flutter 学习之路 - Image](https://github.com/draftbk/flutter_road/blob/master/notes/Flutter_Image.md) 15 | - [Flutter 学习之路 - ListView](https://github.com/draftbk/flutter_road/blob/master/notes/Flutter_Listview.md) 16 | - [Flutter 学习之路 - Gridview](https://github.com/draftbk/flutter_road/blob/master/notes/Flutter_Gridview.md) 17 | - Flutter 学习之路 - Dialog 试验(待) 18 | - [Flutter 学习之路 - 导航栏](https://github.com/draftbk/flutter_road/blob/master/notes/Flutter_NavigationBar.md) 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | ## 线程网络篇 28 | 29 | - [Flutter 学习之路 - 异步任务](https://github.com/draftbk/flutter_road/blob/master/notes/Flutter_Async.md) 30 | - [Flutter 学习之路 - 网络入门](https://github.com/draftbk/flutter_road/blob/master/notes/Flutter_Network.md) 31 | 32 | 33 | 34 | 35 | ## 其他 36 | - [Flutter 学习之路 - 测试(单元测试,Widget 测试,集成测试)](https://github.com/draftbk/flutter_road/blob/master/notes/Flutter_Tests.md) 37 | 38 | ## 微信群 39 | 40 | 欢迎加入一起入坑 Flutter ! 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /flutter_road_test/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # Visual Studio Code related 19 | .vscode/ 20 | 21 | # Flutter/Dart/Pub related 22 | **/doc/api/ 23 | .dart_tool/ 24 | .flutter-plugins 25 | .packages 26 | .pub-cache/ 27 | .pub/ 28 | /build/ 29 | 30 | # Android related 31 | **/android/**/gradle-wrapper.jar 32 | **/android/.gradle 33 | **/android/captures/ 34 | **/android/gradlew 35 | **/android/gradlew.bat 36 | **/android/local.properties 37 | **/android/**/GeneratedPluginRegistrant.java 38 | 39 | # iOS/XCode related 40 | **/ios/**/*.mode1v3 41 | **/ios/**/*.mode2v3 42 | **/ios/**/*.moved-aside 43 | **/ios/**/*.pbxuser 44 | **/ios/**/*.perspectivev3 45 | **/ios/**/*sync/ 46 | **/ios/**/.sconsign.dblite 47 | **/ios/**/.tags* 48 | **/ios/**/.vagrant/ 49 | **/ios/**/DerivedData/ 50 | **/ios/**/Icon? 51 | **/ios/**/Pods/ 52 | **/ios/**/.symlinks/ 53 | **/ios/**/profile 54 | **/ios/**/xcuserdata 55 | **/ios/.generated/ 56 | **/ios/Flutter/App.framework 57 | **/ios/Flutter/Flutter.framework 58 | **/ios/Flutter/Generated.xcconfig 59 | **/ios/Flutter/app.flx 60 | **/ios/Flutter/app.zip 61 | **/ios/Flutter/flutter_assets/ 62 | **/ios/ServiceDefinitions.json 63 | **/ios/Runner/GeneratedPluginRegistrant.* 64 | 65 | # Exceptions to above rules. 66 | !**/ios/**/default.mode1v3 67 | !**/ios/**/default.mode2v3 68 | !**/ios/**/default.pbxuser 69 | !**/ios/**/default.perspectivev3 70 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 71 | -------------------------------------------------------------------------------- /flutter_road_test/.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: e5b1ed7a7f7b85c1877e09a9495681f719be5578 8 | channel: beta 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /flutter_road_test/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | 27 | android { 28 | compileSdkVersion 28 29 | 30 | lintOptions { 31 | disable 'InvalidPackage' 32 | } 33 | 34 | defaultConfig { 35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 36 | applicationId "com.draftbk.flutter_road_test" 37 | minSdkVersion 16 38 | targetSdkVersion 28 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 | -------------------------------------------------------------------------------- /flutter_road_test/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter_road_test/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 9 | 13 | 20 | 24 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /flutter_road_test/android/app/src/main/java/com/draftbk/flutter_road_test/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.draftbk.flutter_road_test; 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 | -------------------------------------------------------------------------------- /flutter_road_test/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /flutter_road_test/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_road_test/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_road_test/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_road_test/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_road_test/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_road_test/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /flutter_road_test/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter_road_test/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 | -------------------------------------------------------------------------------- /flutter_road_test/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /flutter_road_test/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 | -------------------------------------------------------------------------------- /flutter_road_test/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 | -------------------------------------------------------------------------------- /flutter_road_test/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 | -------------------------------------------------------------------------------- /flutter_road_test/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /flutter_road_test/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildSystemType 6 | Original 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /flutter_road_test/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 | -------------------------------------------------------------------------------- /flutter_road_test/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 | -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /flutter_road_test/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 | -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /flutter_road_test/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. -------------------------------------------------------------------------------- /flutter_road_test/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 | -------------------------------------------------------------------------------- /flutter_road_test/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 | -------------------------------------------------------------------------------- /flutter_road_test/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | flutter_road_test 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /flutter_road_test/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 | -------------------------------------------------------------------------------- /flutter_road_test/lib/counter.dart: -------------------------------------------------------------------------------- 1 | class Counter { 2 | int value = 0; 3 | 4 | void increment() => value++; 5 | 6 | void decrement() => value--; 7 | } -------------------------------------------------------------------------------- /flutter_road_test/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void main() => runApp(MyApp()); 4 | 5 | class MyApp extends StatelessWidget { 6 | @override 7 | Widget build(BuildContext context) { 8 | return MaterialApp( 9 | title: 'Counter App', 10 | home: MyHomePage(title: 'Counter App Home Page'), 11 | ); 12 | } 13 | } 14 | 15 | class MyHomePage extends StatefulWidget { 16 | MyHomePage({Key key, this.title}) : super(key: key); 17 | 18 | final String title; 19 | 20 | @override 21 | _MyHomePageState createState() => _MyHomePageState(); 22 | } 23 | 24 | class _MyHomePageState extends State { 25 | int _counter = 0; 26 | 27 | void _incrementCounter() { 28 | setState(() { 29 | _counter++; 30 | }); 31 | } 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | return Scaffold( 36 | appBar: AppBar( 37 | title: Text(widget.title), 38 | ), 39 | body: Center( 40 | child: Column( 41 | mainAxisAlignment: MainAxisAlignment.center, 42 | children: [ 43 | Text( 44 | 'You have pushed the button this many times:', 45 | ), 46 | Text( 47 | '$_counter', 48 | // Provide a Key to this specific Text Widget. This allows us 49 | // to identify this specific Widget from inside our test suite and 50 | // read the text. 51 | key: Key('counter'), 52 | style: Theme.of(context).textTheme.display1, 53 | ), 54 | ], 55 | ), 56 | ), 57 | floatingActionButton: FloatingActionButton( 58 | // Provide a Key to this the button. This allows us to find this 59 | // specific button and tap it inside the test suite. 60 | key: Key('increment'), 61 | onPressed: _incrementCounter, 62 | tooltip: 'Increment', 63 | child: Icon(Icons.add), 64 | ), 65 | ); 66 | } 67 | } -------------------------------------------------------------------------------- /flutter_road_test/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_road_test 2 | description: A new Flutter application. 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # In Android, build-name is used as versionName while build-number used as versionCode. 10 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 11 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 12 | # Read more about iOS versioning at 13 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 14 | version: 1.0.0+1 15 | 16 | environment: 17 | sdk: ">=2.1.0 <3.0.0" 18 | 19 | dependencies: 20 | test: any 21 | flutter: 22 | sdk: flutter 23 | 24 | # The following adds the Cupertino Icons font to your application. 25 | # Use with the CupertinoIcons class for iOS style icons. 26 | cupertino_icons: ^0.1.2 27 | 28 | dev_dependencies: 29 | flutter_test: 30 | sdk: flutter 31 | flutter_driver: 32 | sdk: flutter 33 | test: any 34 | 35 | 36 | # For information on the generic Dart part of this file, see the 37 | # following page: https://www.dartlang.org/tools/pub/pubspec 38 | 39 | # The following section is specific to Flutter. 40 | flutter: 41 | 42 | # The following line ensures that the Material Icons font is 43 | # included with your application, so that you can use the icons in 44 | # the material Icons class. 45 | uses-material-design: true 46 | 47 | # To add assets to your application, add an assets section, like this: 48 | # assets: 49 | # - images/a_dot_burr.jpeg 50 | # - images/a_dot_ham.jpeg 51 | 52 | # An image asset can refer to one or more resolution-specific "variants", see 53 | # https://flutter.io/assets-and-images/#resolution-aware. 54 | 55 | # For details regarding adding assets from package dependencies, see 56 | # https://flutter.io/assets-and-images/#from-packages 57 | 58 | # To add custom fonts to your application, add a fonts section here, 59 | # in this "flutter" section. Each entry in this list should have a 60 | # "family" key with the font family name, and a "fonts" key with a 61 | # list giving the asset and other descriptors for the font. For 62 | # example: 63 | # fonts: 64 | # - family: Schyler 65 | # fonts: 66 | # - asset: fonts/Schyler-Regular.ttf 67 | # - asset: fonts/Schyler-Italic.ttf 68 | # style: italic 69 | # - family: Trajan Pro 70 | # fonts: 71 | # - asset: fonts/TrajanPro.ttf 72 | # - asset: fonts/TrajanPro_Bold.ttf 73 | # weight: 700 74 | # 75 | # For details regarding fonts from package dependencies, 76 | # see https://flutter.io/custom-fonts/#from-packages 77 | -------------------------------------------------------------------------------- /flutter_road_test/test/counter_test.dart: -------------------------------------------------------------------------------- 1 | // Import the test package and Counter class 2 | import 'package:test/test.dart'; 3 | import 'package:flutter_road_test/counter.dart'; 4 | 5 | void main() { 6 | test('Counter value should be incremented', () { 7 | final counter = Counter(); 8 | 9 | counter.increment(); 10 | 11 | expect(counter.value, 1); 12 | }); 13 | } -------------------------------------------------------------------------------- /flutter_road_test/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | 4 | void main() { 5 | // Define a test. The TestWidgets function will also provide a WidgetTester 6 | // for us to work with. The WidgetTester will allow us to build and interact 7 | // with Widgets in the test environment. 8 | testWidgets('MyWidget has a title and message', (WidgetTester tester) async { 9 | // Create the Widget tell the tester to build it 10 | await tester.pumpWidget(MyWidget(title: 'T', message: 'M')); 11 | 12 | // Create our Finders 13 | final titleFinder = find.text('T'); 14 | final messageFinder = find.text('M'); 15 | 16 | // Use the `findsOneWidget` matcher provided by flutter_test to verify our 17 | // Text Widgets appear exactly once in the Widget tree 18 | expect(titleFinder, findsOneWidget); 19 | expect(messageFinder, findsOneWidget); 20 | }); 21 | } 22 | 23 | class MyWidget extends StatelessWidget { 24 | final String title; 25 | final String message; 26 | 27 | const MyWidget({ 28 | Key key, 29 | @required this.title, 30 | @required this.message, 31 | }) : super(key: key); 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | return MaterialApp( 36 | title: 'Flutter Demo', 37 | home: Scaffold( 38 | appBar: AppBar( 39 | title: Text(title), 40 | ), 41 | body: Center( 42 | child: Text(message), 43 | ), 44 | ), 45 | ); 46 | } 47 | } -------------------------------------------------------------------------------- /flutter_road_test/test_driver/app.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_driver/driver_extension.dart'; 2 | import 'package:flutter_road_test/main.dart' as app; 3 | 4 | void main() { 5 | // This line enables the extension 6 | enableFlutterDriverExtension(); 7 | 8 | // Call the `main()` function of your app or call `runApp` with any widget you 9 | // are interested in testing. 10 | app.main(); 11 | } -------------------------------------------------------------------------------- /flutter_road_test/test_driver/app_test.dart: -------------------------------------------------------------------------------- 1 | // Imports the Flutter Driver API 2 | import 'package:flutter_driver/flutter_driver.dart'; 3 | import 'package:test/test.dart'; 4 | 5 | void main() { 6 | group('Counter App', () { 7 | // 通过 Finders 找到对应的 Widgets 8 | final counterTextFinder = find.byValueKey('counter'); 9 | final buttonFinder = find.byValueKey('increment'); 10 | 11 | FlutterDriver driver; 12 | 13 | // 连接 Flutter driver 14 | setUpAll(() async { 15 | driver = await FlutterDriver.connect(); 16 | }); 17 | 18 | // 当测试完成断开连接 19 | tearDownAll(() async { 20 | if (driver != null) { 21 | driver.close(); 22 | } 23 | }); 24 | 25 | test('starts at 0', () async { 26 | // 用 `driver.getText` 来判断 counter 初始化是 0 27 | expect(await driver.getText(counterTextFinder), "0"); 28 | }); 29 | 30 | test('increments the counter', () async { 31 | // 首先,点击按钮 32 | await driver.tap(buttonFinder); 33 | 34 | // 然后,判断是否增加了 1 35 | expect(await driver.getText(counterTextFinder), "1"); 36 | }); 37 | }); 38 | } -------------------------------------------------------------------------------- /flutter_road_widgets/.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 | -------------------------------------------------------------------------------- /flutter_road_widgets/.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: 5391447fae6209bb21a89e6a5a6583cac1af9b4b 8 | channel: beta 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /flutter_road_widgets/README.md: -------------------------------------------------------------------------------- 1 | ## Flutter Widgets 2 | > 实验一些常用的 Widgets 3 | 4 | -------------------------------------------------------------------------------- /flutter_road_widgets/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.draftbk.flutterroadwidgets" 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 | -------------------------------------------------------------------------------- /flutter_road_widgets/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 15 | 19 | 26 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /flutter_road_widgets/android/app/src/main/java/com/draftbk/flutterroadwidgets/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.draftbk.flutterroadwidgets; 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 | -------------------------------------------------------------------------------- /flutter_road_widgets/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /flutter_road_widgets/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_road_widgets/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_road_widgets/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_road_widgets/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_road_widgets/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_road_widgets/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /flutter_road_widgets/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 | -------------------------------------------------------------------------------- /flutter_road_widgets/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /flutter_road_widgets/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 | -------------------------------------------------------------------------------- /flutter_road_widgets/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 | -------------------------------------------------------------------------------- /flutter_road_widgets/images/flutter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/images/flutter.png -------------------------------------------------------------------------------- /flutter_road_widgets/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 | -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def parse_KV_file(file, separator='=') 14 | file_abs_path = File.expand_path(file) 15 | if !File.exists? file_abs_path 16 | return []; 17 | end 18 | pods_ary = [] 19 | skip_line_start_symbols = ["#", "/"] 20 | File.foreach(file_abs_path) { |line| 21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } 22 | plugin = line.split(pattern=separator) 23 | if plugin.length == 2 24 | podname = plugin[0].strip() 25 | path = plugin[1].strip() 26 | podpath = File.expand_path("#{path}", file_abs_path) 27 | pods_ary.push({:name => podname, :path => podpath}); 28 | else 29 | puts "Invalid plugin specification: #{line}" 30 | end 31 | } 32 | return pods_ary 33 | end 34 | 35 | target 'Runner' do 36 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock 37 | # referring to absolute paths on developers' machines. 38 | system('rm -rf .symlinks') 39 | system('mkdir -p .symlinks/plugins') 40 | 41 | # Flutter Pods 42 | generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') 43 | if generated_xcode_build_settings.empty? 44 | puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first." 45 | end 46 | generated_xcode_build_settings.map { |p| 47 | if p[:name] == 'FLUTTER_FRAMEWORK_DIR' 48 | symlink = File.join('.symlinks', 'flutter') 49 | File.symlink(File.dirname(p[:path]), symlink) 50 | pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) 51 | end 52 | } 53 | 54 | # Plugin Pods 55 | plugin_pods = parse_KV_file('../.flutter-plugins') 56 | plugin_pods.map { |p| 57 | symlink = File.join('.symlinks', 'plugins', p[:name]) 58 | File.symlink(p[:path], symlink) 59 | pod p[:name], :path => File.join(symlink, 'ios') 60 | } 61 | end 62 | 63 | post_install do |installer| 64 | installer.pods_project.targets.each do |target| 65 | target.build_configurations.each do |config| 66 | config.build_settings['ENABLE_BITCODE'] = 'NO' 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildSystemType 6 | Original 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /flutter_road_widgets/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 | -------------------------------------------------------------------------------- /flutter_road_widgets/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 | -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /flutter_road_widgets/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 | -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draftbk/flutter_road/a905158a32eaff5ad021304ecdfbbfc199411f62/flutter_road_widgets/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /flutter_road_widgets/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. -------------------------------------------------------------------------------- /flutter_road_widgets/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 | -------------------------------------------------------------------------------- /flutter_road_widgets/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 | -------------------------------------------------------------------------------- /flutter_road_widgets/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | flutter_road_widgets 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /flutter_road_widgets/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 | -------------------------------------------------------------------------------- /flutter_road_widgets/lib/days/Day1.dart: -------------------------------------------------------------------------------- 1 | /** 2 | * Day 1 3 | * Text 4 | */ 5 | 6 | 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter/cupertino.dart'; 9 | import 'dart:core'; 10 | 11 | 12 | class Day1 extends StatefulWidget { 13 | @override 14 | createState() => Day1State(); 15 | } 16 | 17 | class Day1State extends State { 18 | var _tapText = '文字点击事件, 点我!'; 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | 23 | Widget textSection = Container( 24 | padding: const EdgeInsets.all(15.0), 25 | color: Colors.white, 26 | child: Column( 27 | children: [ 28 | Text('默认的Test'), 29 | //设置字体大小 30 | Padding( 31 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 32 | child: Text( 33 | '设置字体大小', 34 | style: TextStyle( 35 | fontSize: 20, 36 | ), 37 | ), 38 | ), 39 | //设置字体颜色 40 | Padding( 41 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 42 | child: Text( 43 | '设置字体颜色', 44 | style: TextStyle( 45 | color: const Color(0xFFFF856C), 46 | ), 47 | ), 48 | ), 49 | //设置粗体 50 | Padding( 51 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 52 | child: Text( 53 | '设置粗细和斜体', 54 | style: TextStyle( 55 | //字体粗细,粗体和正常 56 | fontWeight: FontWeight.bold, 57 | ), 58 | ), 59 | ), 60 | //设置斜体 61 | Padding( 62 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 63 | child: Text( 64 | '设置粗细和斜体', 65 | style: TextStyle( 66 | //文字样式,斜体和正常 67 | fontStyle: FontStyle.italic, 68 | ), 69 | ), 70 | ), 71 | //自动换行 72 | Padding( 73 | padding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 0.0), 74 | child: Text( 75 | '超出屏幕后设置自动换行,来,大声喊:啊啊啊啊啊啊啊啊啊啊啊啊啊啊', 76 | softWrap: true, 77 | ), 78 | ), 79 | //文字超出屏幕之后的处理方式 TextOverflow.clip剪裁 TextOverflow.fade 渐隐 TextOverflow.ellipsis省略号 80 | Padding( 81 | padding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 0.0), 82 | child: Text( 83 | '超出屏幕后设置用省略号,来,大声喊:啊啊啊啊啊啊啊啊啊啊啊啊啊啊', 84 | overflow: TextOverflow.ellipsis, 85 | ), 86 | ), 87 | 88 | //TextAlign.left左对齐,TextAlign.right右对齐,TextAlign.center居中对齐,TextAlign.justfy两端对齐 89 | Padding( 90 | padding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 0.0), 91 | 92 | child: Text( 93 | '文本居中', 94 | textAlign: TextAlign.center, 95 | ), 96 | ), 97 | 98 | Padding( 99 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 100 | child: Text( 101 | '给文字加下划线', 102 | style: TextStyle( 103 | //none无文字装饰,lineThrough删除线,overline文字上面显示线,underline文字下面显示线 104 | decoration: TextDecoration.underline, 105 | decorationColor: Colors.red, 106 | decorationStyle: TextDecorationStyle.wavy 107 | ), 108 | ), 109 | ), 110 | Padding( 111 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 112 | child: Text( 113 | '文字实现划去效果', 114 | style: TextStyle( 115 | //none无文字装饰,lineThrough删除线,overline文字上面显示线,underline文字下面显示线 116 | decoration: TextDecoration.lineThrough, 117 | decorationColor: Colors.black, 118 | decorationStyle: TextDecorationStyle.solid 119 | ), 120 | ), 121 | ), 122 | //单词间隙设置 123 | Padding( 124 | padding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 0.0), 125 | child: Text( 126 | '单词间隙设置 hello world', 127 | style: TextStyle( 128 | wordSpacing: 10.0, 129 | ), 130 | ), 131 | ), 132 | //字母间隙设置 133 | Padding( 134 | padding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 0.0), 135 | child: Text( 136 | '字母间隙设置 hello world', 137 | style: TextStyle( 138 | letterSpacing: 10.0, 139 | ), 140 | ), 141 | ), 142 | // 文本点击 143 | Padding( 144 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 145 | child: GestureDetector( 146 | onTap: () { 147 | setState(() { 148 | if(_tapText=="啊我被点到了"){ 149 | _tapText="文字点击事件, 点我!"; 150 | }else{ 151 | _tapText="啊我被点到了"; 152 | } 153 | }); 154 | }, 155 | child: Text( 156 | _tapText, 157 | style: TextStyle( 158 | fontSize: 16, 159 | fontWeight: FontWeight.bold, 160 | ), 161 | ), 162 | ), 163 | ), 164 | 165 | // 文本拼接 166 | Padding( 167 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 168 | child: Text.rich( 169 | new TextSpan( 170 | text: '文字拼接: ', 171 | style: new TextStyle( 172 | color: Colors.black, 173 | fontSize: 14, 174 | decoration: TextDecoration.none), 175 | children: [ 176 | new TextSpan( 177 | text: "文字一", 178 | style: new TextStyle( 179 | color: Colors.blue, 180 | fontSize: 20, 181 | decoration: TextDecoration.none)), 182 | new TextSpan( 183 | text: "文字二", 184 | style: new TextStyle( 185 | color: Colors.green, 186 | fontSize: 14, 187 | decoration: TextDecoration.none)), 188 | new TextSpan( 189 | text: "文字三", 190 | style: new TextStyle( 191 | color: Colors.red, 192 | fontSize: 18, 193 | decoration: TextDecoration.none)), 194 | ]), 195 | ), 196 | ) 197 | ], 198 | ), 199 | ); 200 | 201 | return Scaffold( 202 | backgroundColor: Colors.grey[200], 203 | appBar: CupertinoNavigationBar( 204 | middle: Text('Text'), 205 | ), 206 | body: textSection, 207 | 208 | ); 209 | } 210 | } -------------------------------------------------------------------------------- /flutter_road_widgets/lib/days/Day10.dart: -------------------------------------------------------------------------------- 1 | /** 2 | * Day 10 3 | * Async 4 | */ 5 | 6 | 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter/cupertino.dart'; 9 | import 'dart:core'; 10 | 11 | 12 | 13 | 14 | 15 | class Day10 extends StatefulWidget { 16 | @override 17 | createState() => Day10State(); 18 | } 19 | 20 | 21 | class Day10State extends State { 22 | String mytext="Console"; 23 | 24 | void thenCatch(){ 25 | mytext="Started"; 26 | setMyTextState(mytext); 27 | // then 用来说明 1 second 后做什么 28 | Future.delayed(Duration(seconds: 1)).then((_){ 29 | // 当运行完成 30 | mytext = mytext + "\n" + "Completed Task1"; 31 | setMyTextState(mytext); 32 | }).catchError((e){ 33 | // 当运行失败 34 | mytext=mytext+"\n"+'failed: ${e.toString()}'; 35 | setMyTextState(mytext); 36 | }); 37 | } 38 | 39 | void setMyTextState(String newText){ 40 | setState(() { 41 | mytext=newText; 42 | }); 43 | } 44 | 45 | Future asyncAwait() async{ 46 | mytext="Started"; 47 | setMyTextState(mytext); 48 | try{ 49 | // 这里没有 .then, 要加 await, await 是说在 await 完成前别往下执行 50 | await Future.delayed(Duration(seconds: 1)); 51 | mytext=mytext+"\n"+"Completed Task1"; 52 | setMyTextState(mytext); 53 | await Future.delayed(Duration(seconds: 1)); 54 | mytext=mytext+"\n"+"Completed Task2"; 55 | setMyTextState(mytext); 56 | }catch(e){ 57 | print('failed: ${e.toString()}'); 58 | } 59 | } 60 | 61 | Future asyncNoAwait() async{ 62 | mytext="Started"; 63 | setMyTextState(mytext); 64 | try{ 65 | // 这里没有 .then, 要加 await, await 是说在 await 完成前别往下执行 66 | Future.delayed(Duration(seconds: 2)); 67 | mytext=mytext+"\n"+"Completed Task1"; 68 | setMyTextState(mytext); 69 | Future.delayed(Duration(seconds: 1)); 70 | mytext=mytext+"\n"+"Completed Task2"; 71 | setMyTextState(mytext); 72 | }catch(e){ 73 | print('failed: ${e.toString()}'); 74 | } 75 | } 76 | 77 | Future asyncAwaitWithTask() async{ 78 | mytext="Started"; 79 | setMyTextState(mytext); 80 | try{ 81 | // 这里没有 .then, 要加 await, await 是说在 await 完成前别往下执行 82 | await Future.delayed(Duration(seconds: 1)); 83 | mytext=mytext+"\n"+"Completed Task1"; 84 | setMyTextState(mytext); 85 | task2(); 86 | mytext=mytext+"\n"+"Completed Task3"; 87 | setMyTextState(mytext); 88 | mytext=mytext+"\n"+"Completed Task4"; 89 | setMyTextState(mytext); 90 | }catch(e){ 91 | print('failed: ${e.toString()}'); 92 | } 93 | } 94 | 95 | void task2() async{ 96 | await Future.delayed(Duration(seconds: 1)); 97 | mytext=mytext+"\n"+"Completed Task2"; 98 | setMyTextState(mytext); 99 | } 100 | 101 | 102 | @override 103 | Widget build(BuildContext context) { 104 | 105 | Widget asyncSection = Container( 106 | margin: EdgeInsets.fromLTRB(5.0, 5.0, 5.0, 5.0), 107 | height: 400.0, 108 | child: new Center( 109 | child: new Column( 110 | mainAxisAlignment: MainAxisAlignment.center, 111 | children: [ 112 | new RaisedButton( 113 | onPressed: thenCatch, 114 | child: new Text('Future.Then'), 115 | color: Color(0xFFe16552), 116 | ), 117 | new RaisedButton( 118 | onPressed: asyncNoAwait, 119 | child: new Text('Async no await'), 120 | color: Color(0xFFe16552), 121 | ), 122 | new RaisedButton( 123 | onPressed: asyncAwait, 124 | child: new Text('Async await'), 125 | color: Color(0xFFe16552), 126 | ), 127 | new RaisedButton( 128 | onPressed: asyncAwaitWithTask, 129 | child: new Text('Wait With Other Task'), 130 | color: Color(0xFFe16552), 131 | ), 132 | ], 133 | ), 134 | ), 135 | ); 136 | Widget consoleSection = Container( 137 | margin: EdgeInsets.fromLTRB(5.0, 5.0, 5.0, 5.0), 138 | height: 300.0, 139 | width: double.infinity, 140 | child: Text( 141 | mytext, 142 | style: TextStyle( 143 | fontSize: 18, 144 | ), 145 | ), 146 | 147 | ); 148 | 149 | 150 | return Scaffold( 151 | backgroundColor: Colors.grey[200], 152 | appBar: CupertinoNavigationBar( 153 | middle: Text('Async'), 154 | ), 155 | body: Column( 156 | children:[ 157 | asyncSection, 158 | new Container( 159 | color: Color(0xFFe16552), 160 | height: 2, 161 | width: double.infinity, 162 | ), 163 | consoleSection, 164 | ] 165 | ) 166 | ); 167 | } 168 | } -------------------------------------------------------------------------------- /flutter_road_widgets/lib/days/Day11.dart: -------------------------------------------------------------------------------- 1 | /** 2 | * Day 11 3 | * Network 4 | */ 5 | 6 | import 'package:flutter/material.dart'; 7 | import 'package:flutter/cupertino.dart'; 8 | import 'dart:core'; 9 | 10 | // for HttpClient 11 | import 'dart:convert'; 12 | import 'dart:io'; 13 | 14 | // for http 15 | import 'package:http/http.dart' as http; 16 | 17 | // for dio 18 | import 'package:dio/dio.dart'; 19 | 20 | class Day11 extends StatefulWidget { 21 | @override 22 | createState() => Day11State(); 23 | } 24 | 25 | class Day11State extends State { 26 | String mytext = "Console"; 27 | double buttonWidth = 200; 28 | String getUrl="https://httpbin.org/ip"; 29 | String postUrl="http://ip.taobao.com/service/getIpInfo.php"; 30 | String searchIp='117.89.35.58'; 31 | void setMyTextState(String newText) { 32 | setState(() { 33 | mytext = newText; 34 | }); 35 | } 36 | 37 | void HttpClient_Get() async { 38 | mytext = "HttpClient GET Start"; 39 | setMyTextState(mytext); 40 | var httpClient = new HttpClient(); 41 | String result; 42 | try { 43 | var request = await httpClient.getUrl(Uri.parse(getUrl)); 44 | var response = await request.close(); 45 | if (response.statusCode == HttpStatus.OK) { 46 | result = await response.transform(utf8.decoder).join(); 47 | } else { 48 | result = 49 | 'Error getting IP address:\nHttp status ${response.statusCode}'; 50 | } 51 | } catch (exception) { 52 | result = 'Failed getting IP address'; 53 | } 54 | mytext = mytext + "\n" + result; 55 | setMyTextState(mytext); 56 | } 57 | // void HttpClient_Post() async { 58 | // mytext = "HttpClient POST Start"; 59 | // setMyTextState(mytext); 60 | // var httpClient = new HttpClient(); 61 | // String result; 62 | // try { 63 | // Uri uri=new Uri(path:postUrl,queryParameters: {"ip": searchIp} ); 64 | // print(uri.toString()); 65 | // var request = await httpClient.postUrl(uri); 66 | // var response = await request.close(); 67 | // if (response.statusCode == HttpStatus.OK) { 68 | // var my_json = await response.transform(utf8.decoder).join(); 69 | // result = my_json.toString(); 70 | // } else { 71 | // result = 72 | // 'Error getting IP address:\nHttp status ${response.statusCode}'; 73 | // } 74 | // } catch (exception) { 75 | // result = 'Failed getting IP address'; 76 | // } 77 | // mytext = mytext + "\n" + result; 78 | // } 79 | 80 | 81 | 82 | void http_Get() async { 83 | mytext = "http GET Start"; 84 | setMyTextState(mytext); 85 | String result; 86 | try { 87 | var response = await http.get(getUrl); 88 | if (response.statusCode == HttpStatus.OK) { 89 | result = response.body; 90 | } else { 91 | result = 92 | 'Error getting IP address:\nHttp status ${response.statusCode}'; 93 | } 94 | } catch (exception) { 95 | result = 'Failed getting IP address'; 96 | } 97 | mytext = mytext + "\n" + result; 98 | setMyTextState(mytext); 99 | } 100 | 101 | void http_Post() async { 102 | mytext = "http POST Start"; 103 | setMyTextState(mytext); 104 | String result; 105 | try { 106 | 107 | var client = http.Client(); 108 | var response = await client.post(postUrl, body: {"ip": searchIp}); 109 | 110 | if (response.statusCode == HttpStatus.OK) { 111 | result = response.body; 112 | } else { 113 | result = 114 | 'Error getting reslut:\nHttp status ${response.statusCode}'; 115 | } 116 | } catch (exception) { 117 | result = 'Failed getting reslut'; 118 | } 119 | mytext = mytext + "\n" + result; 120 | setMyTextState(mytext); 121 | } 122 | 123 | void dio_Get() async { 124 | mytext = "dio GET Start"; 125 | setMyTextState(mytext); 126 | String result; 127 | try { 128 | Dio dio = new Dio(); 129 | var response = await dio.get(getUrl); 130 | if (response.statusCode == HttpStatus.OK) { 131 | result = response.data.toString(); 132 | } else { 133 | result = 134 | 'Error getting IP address:\nHttp status ${response.statusCode}'; 135 | } 136 | } catch (exception) { 137 | result = 'Failed getting IP address'; 138 | } 139 | mytext = mytext + "\n" + result; 140 | setMyTextState(mytext); 141 | } 142 | 143 | void dio_Post() async { 144 | mytext = "dio POST Start"; 145 | setMyTextState(mytext); 146 | String result=""; 147 | try { 148 | var dio = new Dio(); 149 | var response = await dio.post(postUrl, queryParameters:{"ip": searchIp}); 150 | if (response.statusCode == HttpStatus.OK) { 151 | result = response.data.toString(); 152 | } else { 153 | result = 154 | 'Error getting reslut:\nHttp status ${response.statusCode}'; 155 | } 156 | } catch (exception) { 157 | result = 'Failed getting reslut'; 158 | } 159 | mytext = mytext + "\n" + result; 160 | setMyTextState(mytext); 161 | } 162 | 163 | void Json_Parser()async { 164 | mytext="JSON Parser Start"; 165 | setMyTextState(mytext); 166 | var httpClient = new HttpClient(); 167 | String result; 168 | try { 169 | var request = await httpClient.getUrl(Uri.parse(getUrl)); 170 | var response = await request.close(); 171 | if (response.statusCode == HttpStatus.OK) { 172 | result = await response.transform(utf8.decoder).join(); 173 | var data = json.decode(result); 174 | result = data['origin']; 175 | } else { 176 | result = 177 | 'Error getting IP address:\nHttp status ${response.statusCode}'; 178 | } 179 | } catch (exception) { 180 | result = 'Failed getting IP address'; 181 | } 182 | mytext = mytext + "\n" + result; 183 | setMyTextState(mytext); 184 | } 185 | 186 | 187 | @override 188 | Widget build(BuildContext context) { 189 | Widget asyncSection = Container( 190 | margin: EdgeInsets.fromLTRB(5.0, 5.0, 5.0, 5.0), 191 | height: 400.0, 192 | child: new Center( 193 | child: new Column( 194 | mainAxisAlignment: MainAxisAlignment.center, 195 | children: [ 196 | new ButtonTheme( 197 | minWidth: buttonWidth, 198 | child: RaisedButton( 199 | onPressed: HttpClient_Get, 200 | child: new Text('HttpClient GET'), 201 | color: Color(0xFFe16552), 202 | ), 203 | ), 204 | new ButtonTheme( 205 | minWidth: buttonWidth, 206 | child: RaisedButton( 207 | onPressed: http_Get, 208 | child: new Text('http GET'), 209 | color: Color(0xFFe16552), 210 | ), 211 | ), 212 | new ButtonTheme( 213 | minWidth: buttonWidth, 214 | child: RaisedButton( 215 | onPressed: http_Post, 216 | child: new Text('http POST'), 217 | color: Color(0xFFe16552), 218 | ), 219 | ), 220 | new ButtonTheme( 221 | minWidth: buttonWidth, 222 | child: RaisedButton( 223 | onPressed: dio_Get, 224 | child: new Text('dio GET'), 225 | color: Color(0xFFe16552), 226 | ), 227 | ), 228 | new ButtonTheme( 229 | minWidth: buttonWidth, 230 | child: RaisedButton( 231 | onPressed: dio_Post, 232 | child: new Text('dio POST'), 233 | color: Color(0xFFe16552), 234 | ), 235 | ), 236 | new ButtonTheme( 237 | minWidth: buttonWidth, 238 | child: RaisedButton( 239 | onPressed: Json_Parser, 240 | child: new Text('JSON Parser'), 241 | color: Color(0xFFe16552), 242 | ), 243 | ), 244 | ], 245 | ), 246 | ), 247 | ); 248 | Widget consoleSection = Container( 249 | margin: EdgeInsets.fromLTRB(5.0, 5.0, 5.0, 5.0), 250 | height: 300.0, 251 | width: double.infinity, 252 | child: Text( 253 | mytext, 254 | style: TextStyle( 255 | fontSize: 18, 256 | ), 257 | ), 258 | ); 259 | 260 | return Scaffold( 261 | backgroundColor: Colors.grey[200], 262 | appBar: CupertinoNavigationBar( 263 | middle: Text('Network'), 264 | ), 265 | body: Column(children: [ 266 | asyncSection, 267 | new Container( 268 | color: Color(0xFFe16552), 269 | height: 2, 270 | width: double.infinity, 271 | ), 272 | consoleSection, 273 | ])); 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /flutter_road_widgets/lib/days/Day12.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/gestures.dart'; 2 | /** 3 | * Day 12 4 | * Test 5 | */ 6 | 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter/cupertino.dart'; 9 | import 'package:url_launcher/url_launcher.dart'; 10 | import 'dart:core'; 11 | 12 | 13 | 14 | 15 | class Day12 extends StatefulWidget { 16 | @override 17 | createState() => Day12State(); 18 | } 19 | 20 | class Day12State extends State { 21 | 22 | 23 | void setMyTextState(String newText) { 24 | setState(() { 25 | }); 26 | } 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | @override 35 | Widget build(BuildContext context) { 36 | Widget asyncSection = Container( 37 | margin: EdgeInsets.fromLTRB(5.0, 5.0, 5.0, 5.0), 38 | height: 400.0, 39 | child: new Center( 40 | child: new RichText( 41 | text: new TextSpan( 42 | children: [ 43 | new TextSpan( 44 | text: '测试的项目不适合写在这个项目里,可以查看我写的blog(里面也有代码链接): \n', 45 | style: new TextStyle(color: Colors.black,fontSize: 22), 46 | ), 47 | new TextSpan( 48 | text: 'https://github.com/draftbk/flutter_road/blob/master/notes/Flutter_Tests.md\n', 49 | style: new TextStyle(color: Colors.blue,fontSize: 22), 50 | recognizer: new TapGestureRecognizer() 51 | ..onTap = () { launch('https://github.com/draftbk/flutter_road/blob/master/notes/Flutter_Tests.md'); 52 | }, 53 | ), 54 | new TextSpan( 55 | text: '希望对你有帮助<( ̄︶ ̄)>', 56 | style: new TextStyle(color: Colors.black,fontSize: 22), 57 | ), 58 | ], 59 | ), 60 | ), 61 | ), 62 | ); 63 | 64 | return Scaffold( 65 | backgroundColor: Colors.grey[200], 66 | appBar: CupertinoNavigationBar( 67 | middle: Text('Testing'), 68 | ), 69 | body: Column(children: [ 70 | asyncSection, 71 | ])); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /flutter_road_widgets/lib/days/Day2.dart: -------------------------------------------------------------------------------- 1 | /** 2 | * Day 2 3 | * Button 4 | */ 5 | 6 | 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter/cupertino.dart'; 9 | import 'dart:core'; 10 | 11 | 12 | class Day2 extends StatefulWidget { 13 | @override 14 | createState() => Day2State(); 15 | } 16 | 17 | class Day2State extends State { 18 | var mCurrentValue = 1.0; 19 | var isChecked=false; 20 | int groupValue1,groupValue2; 21 | @override 22 | Widget build(BuildContext context) { 23 | 24 | Widget buttonSection = Container( 25 | padding: const EdgeInsets.all(15.0), 26 | color: Colors.white, 27 | child: Column( 28 | children: [ 29 | // RaisedButton 30 | Padding( 31 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 32 | child: new RaisedButton( 33 | onPressed: () {print('button click');}, 34 | child: new Text("RaisedButton"), 35 | ), 36 | ), 37 | // FlatButton 38 | Padding( 39 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 40 | child: new FlatButton( 41 | onPressed: () {print('button click');}, 42 | child: new Text("FlatButton"), 43 | color: Color(0xFFe16552), 44 | ), 45 | ), 46 | 47 | //FloatingActionButton 多个FloatingActionButton的时候会报错,要加 heroTag: null 48 | Padding( 49 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 50 | child: Row( 51 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 52 | children: [ 53 | // FloatingActionButton 54 | new FloatingActionButton( 55 | onPressed: () {print('button click');}, 56 | foregroundColor: Colors.white, 57 | backgroundColor: Color(0xFFf19670), 58 | child: new Icon(Icons.add), 59 | heroTag: null, 60 | ), 61 | // FloatingActionButton 62 | new FloatingActionButton( 63 | onPressed: () {print('button click');}, 64 | foregroundColor: Colors.white, 65 | backgroundColor: Color(0xFFf19670), 66 | child: new Text("文字"), 67 | heroTag: null, 68 | ), 69 | ], 70 | ), 71 | ), 72 | 73 | // FloatingActionButton.extended 74 | Padding( 75 | padding: const EdgeInsets.fromLTRB(0.0, 15.0, 0.0, 0.0), 76 | child: new FloatingActionButton.extended( 77 | onPressed: () { 78 | print('button click'); 79 | }, 80 | foregroundColor: Colors.white, 81 | backgroundColor: Colors.amber, 82 | icon: new Icon(Icons.flag,color: Colors.red,), 83 | label: new Text('FloatingActionButton.extended', maxLines: 1), 84 | ) 85 | ), 86 | 87 | // Slider 88 | Padding( 89 | padding: const EdgeInsets.fromLTRB(0.0, 15.0, 0.0, 0.0), 90 | child: new Slider( 91 | value: mCurrentValue, 92 | min: 1.0, 93 | max: 10.0, 94 | onChanged: (e) { 95 | setState(() { 96 | //四舍五入的双精度值 97 | mCurrentValue = e.roundToDouble(); 98 | }); 99 | } 100 | ) 101 | ), 102 | 103 | // Checkbox 104 | Padding( 105 | padding: const EdgeInsets.fromLTRB(0.0, 15.0, 0.0, 0.0), 106 | child: new Checkbox( 107 | value: isChecked, 108 | onChanged: (bool){ 109 | setState(() { 110 | isChecked=bool; 111 | }); 112 | }, activeColor: Colors.blue, 113 | ) 114 | ), 115 | 116 | // Radio 117 | Padding( 118 | padding: const EdgeInsets.fromLTRB(0.0, 15.0, 0.0, 0.0), 119 | child: new ButtonBar(//ButtonBar:水平排列按钮 120 | alignment: MainAxisAlignment.center, 121 | children: [ 122 | //value和groupValue值一样的话,则按钮选中 123 | new Radio(value: 1, 124 | groupValue: groupValue1, 125 | onChanged: (int e) => updateGroupValue(e)), 126 | new Radio(value: 2, 127 | groupValue: groupValue1, 128 | onChanged: (int e) => updateGroupValue(e)), 129 | new Radio(value: 3, 130 | groupValue: groupValue1, 131 | onChanged: (int e) => updateGroupValue(e)), 132 | new Radio(value: 4, 133 | groupValue: groupValue1, 134 | onChanged: (int e) => updateGroupValue(e)), 135 | //value 值为 null 则表示按钮不可用 136 | new Radio(value: null, groupValue: null, onChanged: null) 137 | ], 138 | ) 139 | ), 140 | 141 | // Radio 142 | Padding( 143 | padding: const EdgeInsets.fromLTRB(0.0, 15.0, 0.0, 0.0), 144 | child: new Column(//ButtonBar:水平排列按钮 145 | children: [ 146 | //value和groupValue值一样的话,则按钮选中 147 | new RadioListTile( 148 | title: const Text('A'), 149 | value: 1, 150 | activeColor: Colors.red, 151 | groupValue: groupValue2, 152 | onChanged: (int e)=>updateGroupValue2(e), 153 | ), 154 | new RadioListTile( 155 | title: const Text('B'), 156 | value: 2, 157 | activeColor: Colors.yellow, 158 | groupValue: groupValue2, 159 | onChanged: (int e)=>updateGroupValue2(e), 160 | ), 161 | new RadioListTile( 162 | title: const Text('C'), 163 | value: 3, 164 | activeColor: Colors.green, 165 | groupValue: groupValue2, 166 | onChanged: (int e)=>updateGroupValue2(e), 167 | ), 168 | ], 169 | ) 170 | ), 171 | ], 172 | ), 173 | ); 174 | 175 | return Scaffold( 176 | backgroundColor: Colors.grey[200], 177 | appBar: CupertinoNavigationBar( 178 | middle: Text('Button'), 179 | ), 180 | body: buttonSection, 181 | 182 | ); 183 | } 184 | ///更新 groupValue1, 当Radio的value==groupValue 时候,则按钮被选中 185 | void updateGroupValue(int e){ 186 | setState(() { 187 | groupValue1=e; 188 | }); 189 | } 190 | ///更新 groupValue2, 当Radio的value==groupValue 时候,则按钮被选中 191 | void updateGroupValue2(int e){ 192 | setState(() { 193 | groupValue2=e; 194 | }); 195 | } 196 | } -------------------------------------------------------------------------------- /flutter_road_widgets/lib/days/Day3.dart: -------------------------------------------------------------------------------- 1 | /** 2 | * Day 3 3 | * Image 4 | */ 5 | 6 | 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter/cupertino.dart'; 9 | import 'package:cached_network_image/cached_network_image.dart'; 10 | import 'package:transparent_image/transparent_image.dart'; 11 | import 'dart:core'; 12 | 13 | 14 | 15 | 16 | class Day3 extends StatefulWidget { 17 | @override 18 | createState() => Day3State(); 19 | } 20 | 21 | class Day3State extends State { 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | 26 | Widget imageSection = Container( 27 | padding: const EdgeInsets.all(15.0), 28 | width: 1000, 29 | color: Colors.white, 30 | child: Column( 31 | children: [ 32 | // Image from internet 33 | Padding( 34 | padding: const EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 0.0), 35 | child: new Image( 36 | image:new AssetImage('images/flutter.png'), 37 | width: 50, 38 | height: 50, 39 | ), 40 | ), 41 | // Image from asserts 42 | Padding( 43 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 44 | child: Image.network( 45 | 'https://github.com/draftbk/Blog_Resource/blob/master/Flutter/picture/day3/flutter.png?raw=true', 46 | scale: 4, 47 | ), 48 | ), 49 | // Gif from internet 50 | Padding( 51 | padding: const EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0), 52 | child:Image.network( 53 | 'https://github.com/draftbk/Blog_Resource/blob/master/Flutter/gif/day3/google.gif?raw=true', 54 | scale: 4, 55 | ), 56 | ), 57 | 58 | // FadeInImage 59 | Padding( 60 | padding: const EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0), 61 | child: FadeInImage.memoryNetwork( 62 | width: 180, 63 | height: 180, 64 | placeholder: kTransparentImage, 65 | image: 'https://github.com/draftbk/Blog_Resource/blob/master/Flutter/picture/day3/flutter.png?raw=true', 66 | ), 67 | ), 68 | 69 | // CachedNetworkImage 70 | Padding( 71 | padding: const EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0), 72 | child: CachedNetworkImage( 73 | width: 100, 74 | height: 100, 75 | // placeholder: CircularProgressIndicator(), // 一开始能用,后来可能CachedNetworkImage没有 placeholder了就先注释掉 76 | imageUrl: 77 | 'https://github.com/draftbk/Blog_Resource/blob/master/Flutter/picture/day3/flutter.png?raw=true', 78 | ), 79 | ), 80 | 81 | 82 | 83 | ], 84 | ), 85 | ); 86 | 87 | return Scaffold( 88 | backgroundColor: Colors.grey[200], 89 | appBar: CupertinoNavigationBar( 90 | middle: Text('Image'), 91 | ), 92 | body: imageSection, 93 | 94 | ); 95 | } 96 | 97 | } -------------------------------------------------------------------------------- /flutter_road_widgets/lib/days/Day4.dart: -------------------------------------------------------------------------------- 1 | /** 2 | * Day 4 3 | * ListView 4 | */ 5 | 6 | 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter/cupertino.dart'; 9 | import 'dart:core'; 10 | 11 | 12 | 13 | 14 | class Day4 extends StatefulWidget { 15 | @override 16 | createState() => Day4State(); 17 | } 18 | 19 | 20 | class Day4State extends State { 21 | List items=[]; 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | 26 | Widget horizontalListSection = Container( 27 | margin: EdgeInsets.symmetric(vertical: 20.0), 28 | height: 200.0, 29 | child: ListView( 30 | scrollDirection: Axis.horizontal, 31 | children: [ 32 | Container( 33 | width: 160.0, 34 | color: Colors.red, 35 | ), 36 | Container( 37 | width: 160.0, 38 | color: Colors.blue, 39 | ), 40 | Container( 41 | width: 160.0, 42 | color: Colors.green, 43 | ), 44 | Container( 45 | width: 160.0, 46 | color: Colors.yellow, 47 | ), 48 | Container( 49 | width: 160.0, 50 | color: Colors.orange, 51 | ), 52 | ], 53 | ), 54 | ); 55 | 56 | Widget basicListSection = Builder( 57 | builder: (context) => Container( 58 | margin: EdgeInsets.symmetric(vertical: 5.0), 59 | height: 200.0, 60 | child: ListView( 61 | children: [ 62 | ListTile( 63 | leading: Icon(Icons.map), 64 | title: Text('Map'), 65 | onTap: (){ 66 | _showToast(context,"Map"); 67 | }, 68 | ), 69 | ListTile( 70 | leading: Icon(Icons.photo_album), 71 | title: Text('Album'), 72 | onTap: (){ 73 | _showToast(context,"Album"); 74 | }, 75 | ), 76 | ListTile( 77 | leading: Icon(Icons.phone), 78 | title: Text('Phone'), 79 | onTap: (){ 80 | _showToast(context,"Phone"); 81 | }, 82 | ), 83 | ], 84 | ) 85 | ) 86 | ); 87 | 88 | Widget buttonSection = Padding( 89 | padding: const EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0), 90 | child: new RaisedButton( 91 | onPressed: () {_addListDate();}, 92 | child: new Text("Add New Item"), 93 | ), 94 | ); 95 | 96 | Widget dynamicSection = Container( 97 | margin: EdgeInsets.symmetric(vertical: 5.0), 98 | height: 200.0, 99 | child: ListView.builder( 100 | itemCount: items.length, 101 | itemBuilder: (context,index){ 102 | return ListTile( 103 | leading: Icon(Icons.send), 104 | title: new Text("NewItem $index")); 105 | } 106 | ) 107 | ); 108 | 109 | 110 | 111 | return Scaffold( 112 | backgroundColor: Colors.grey[200], 113 | appBar: CupertinoNavigationBar( 114 | middle: Text('ListView'), 115 | ), 116 | body: Column( 117 | children:[ 118 | horizontalListSection, 119 | basicListSection, 120 | buttonSection, 121 | dynamicSection 122 | ] 123 | ) 124 | ); 125 | } 126 | void _showToast(BuildContext context,String text) { 127 | final scaffold = Scaffold.of(context); 128 | scaffold.showSnackBar( 129 | SnackBar( 130 | content: Text(text), 131 | ), 132 | ); 133 | } 134 | 135 | 136 | void _addListDate(){ 137 | setState(() { 138 | items.add(1); 139 | }); 140 | } 141 | } -------------------------------------------------------------------------------- /flutter_road_widgets/lib/days/Day5.dart: -------------------------------------------------------------------------------- 1 | /** 2 | * Day 5 3 | * GridView 4 | */ 5 | 6 | 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter/cupertino.dart'; 9 | import 'dart:core'; 10 | 11 | 12 | 13 | 14 | class Day5 extends StatefulWidget { 15 | @override 16 | createState() => Day5State(); 17 | } 18 | 19 | 20 | class Day5State extends State { 21 | 22 | List words=["abandon","abhor","abnormal","abroad","abrupt", 23 | "absent","absorb","abstract","absurd","abundant","abuse","academy"]; 24 | List translations=["放弃","厌恶","反常的","海外","突然的", 25 | "缺席的","吸收","抽象(的)","不合理的","丰富的","滥用","研究院"]; 26 | Color myColor=Color(0xFFe16552); 27 | int listNumber=6; 28 | 29 | @override 30 | Widget build(BuildContext context) { 31 | Widget gridItem (BuildContext context, int _index) { 32 | int index=_index%words.length; 33 | return Container( 34 | alignment: Alignment.center, 35 | child: GestureDetector( 36 | onTap: () { 37 | setState(() { 38 | String temp=words[index]; 39 | words[index]=translations[index]; 40 | translations[index]=temp; 41 | }); 42 | }, 43 | child: Text( 44 | words[index], 45 | style: TextStyle( 46 | fontSize: 28, 47 | color: Colors.white, 48 | ), 49 | ), 50 | ), 51 | color:myColor, 52 | ); 53 | } 54 | 55 | Widget gridViewSection = Builder( 56 | builder: (context) => Container( 57 | margin: EdgeInsets.fromLTRB(5.0, 5.0, 5.0, 5.0), 58 | height: 500.0, 59 | child: GridView.count( 60 | // 每行有几个子控件 61 | crossAxisCount: 2, 62 | // 水平子Widget之间间距 63 | crossAxisSpacing: 10.0, 64 | // 水平子Widget之间间距 65 | mainAxisSpacing: 8.0, 66 | // 子Widget宽高比例 67 | childAspectRatio: 2.0, 68 | children: List.generate(listNumber, (index) { 69 | return gridItem(context, index); 70 | }), 71 | ), 72 | ) 73 | ); 74 | 75 | 76 | return Scaffold( 77 | backgroundColor: Colors.grey[200], 78 | appBar: CupertinoNavigationBar( 79 | middle: Text('GridView'), 80 | ), 81 | body: Column( 82 | children:[ 83 | gridViewSection, // FloatingActionButton.extended 84 | Padding( 85 | padding: const EdgeInsets.fromLTRB(0.0, 55.0, 0.0, 0.0), 86 | child: new FloatingActionButton.extended( 87 | onPressed: () { 88 | setState(() { 89 | listNumber=listNumber+1; 90 | }); 91 | }, 92 | foregroundColor: Colors.white, 93 | backgroundColor: myColor, 94 | icon: new Icon(Icons.add,color: Colors.white,), 95 | label: new Text('添加新单词 ', maxLines: 1), 96 | ) 97 | ), 98 | 99 | ] 100 | ) 101 | ); 102 | } 103 | } -------------------------------------------------------------------------------- /flutter_road_widgets/lib/days/Day6.dart: -------------------------------------------------------------------------------- 1 | /** 2 | * Day 6 3 | * Dialog 4 | */ 5 | 6 | import 'package:flutter/material.dart'; 7 | import 'package:flutter/cupertino.dart'; 8 | import 'dart:core'; 9 | 10 | import 'package:flutter_road_widgets/subpage/MySingleChooseDialog.dart'; 11 | 12 | class Day6 extends StatefulWidget { 13 | @override 14 | createState() => Day6State(); 15 | } 16 | 17 | class Day6State extends State { 18 | double buttonWidth = 200; 19 | String mytext = "Console"; 20 | 21 | void setMyTextState(String newText) { 22 | setState(() { 23 | mytext = newText; 24 | }); 25 | } 26 | 27 | Future _showSnackBar(BuildContext context, String text) async { 28 | final scaffold = Scaffold.of(context); 29 | scaffold.showSnackBar( 30 | SnackBar( 31 | content: Text(text), 32 | ), 33 | ); 34 | } 35 | 36 | Future _showSimpleAlertDialog(String message) async { 37 | return showDialog( 38 | context: context, 39 | barrierDismissible: false, // user must tap button! 40 | builder: (BuildContext context) { 41 | return AlertDialog( 42 | title: Text('我是一个简单 Dialog'), 43 | content: SingleChildScrollView( 44 | child: ListBody( 45 | children: [ 46 | Text(message), 47 | ], 48 | ), 49 | ), 50 | actions: [ 51 | FlatButton( 52 | child: Text('是的'), 53 | onPressed: () { 54 | Navigator.of(context).pop(); 55 | }, 56 | ), 57 | ], 58 | ); 59 | }, 60 | ); 61 | } 62 | 63 | Future _showListAlertDialog() async { 64 | return showDialog( 65 | context: context, 66 | barrierDismissible: false, // user must tap button! 67 | builder: (BuildContext context) { 68 | return AlertDialog( 69 | title: Text('我是一个列表 Dialog'), 70 | content: SingleChildScrollView( 71 | child: ListBody( 72 | children: [ 73 | ListTile( 74 | leading: Icon(Icons.map), 75 | title: Text('Map'), 76 | onTap: () { 77 | setMyTextState("你点击了: Map"); 78 | Navigator.of(context).pop(); 79 | }, 80 | ), 81 | ListTile( 82 | leading: Icon(Icons.photo_album), 83 | title: Text('Album'), 84 | onTap: () { 85 | setMyTextState("你点击了: Album"); 86 | Navigator.of(context).pop(); 87 | }, 88 | ), 89 | ListTile( 90 | leading: Icon(Icons.phone), 91 | title: Text('Phone'), 92 | onTap: () { 93 | setMyTextState("你点击了: Phone"); 94 | Navigator.of(context).pop(); 95 | }, 96 | ), 97 | ], 98 | ), 99 | ), 100 | actions: [ 101 | FlatButton( 102 | child: Text('返回'), 103 | onPressed: () { 104 | Navigator.of(context).pop(); 105 | }, 106 | ), 107 | ], 108 | ); 109 | }, 110 | ); 111 | } 112 | 113 | Future _showSingleChooseDialog() async { 114 | return showDialog( 115 | context: context, 116 | barrierDismissible: false, // user must tap button! 117 | builder: (BuildContext context) { 118 | return MySingleChooseDialog(); 119 | }, 120 | ); 121 | } 122 | 123 | @override 124 | Widget build(BuildContext context) { 125 | Widget dialogSection = Builder( 126 | builder: (context) => Container( 127 | margin: EdgeInsets.fromLTRB(5.0, 10.0, 5.0, 5.0), 128 | height: 400.0, 129 | child: new Center( 130 | child: Column( 131 | children: [ 132 | new ButtonTheme( 133 | minWidth: buttonWidth, 134 | child: RaisedButton( 135 | onPressed: () => 136 | _showSnackBar(context, '欢迎来到我的 Flutter 博客!'), 137 | child: new Text('底部提示框'), 138 | color: Color(0xFFe16552), 139 | ), 140 | ), 141 | new ButtonTheme( 142 | minWidth: buttonWidth, 143 | child: RaisedButton( 144 | onPressed: () => _showSimpleAlertDialog('Flutter 是不是很棒!'), 145 | child: new Text('简单 Dialog 提示框'), 146 | color: Color(0xFFe16552), 147 | ), 148 | ), 149 | new ButtonTheme( 150 | minWidth: buttonWidth, 151 | child: RaisedButton( 152 | onPressed: () => _showListAlertDialog(), 153 | child: new Text('列表 Dialog 提示框'), 154 | color: Color(0xFFe16552), 155 | ), 156 | ), 157 | new ButtonTheme( 158 | minWidth: buttonWidth, 159 | child: RaisedButton( 160 | onPressed: () => _showSingleChooseDialog(), 161 | child: new Text('单选 Dialog 提示框'), 162 | color: Color(0xFFe16552), 163 | ), 164 | ), 165 | ], 166 | )))); 167 | 168 | Widget consoleSection = Container( 169 | margin: EdgeInsets.fromLTRB(5.0, 5.0, 5.0, 5.0), 170 | height: 300.0, 171 | width: double.infinity, 172 | child: Text( 173 | mytext, 174 | style: TextStyle( 175 | fontSize: 18, 176 | ), 177 | ), 178 | ); 179 | 180 | return Scaffold( 181 | backgroundColor: Colors.grey[200], 182 | appBar: CupertinoNavigationBar( 183 | middle: Text('Dialog'), 184 | ), 185 | body: Column(children: [ 186 | dialogSection, 187 | new Container( 188 | color: Color(0xFFe16552), 189 | height: 2, 190 | width: double.infinity, 191 | ), 192 | consoleSection, 193 | ])); 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /flutter_road_widgets/lib/days/Day7.dart: -------------------------------------------------------------------------------- 1 | /** 2 | * Day 6 3 | * Dialog 4 | */ 5 | 6 | 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter/cupertino.dart'; 9 | import 'dart:core'; 10 | import 'package:flutter_road_widgets/subpage/TopBarPage.dart'; 11 | import 'package:font_awesome_flutter/font_awesome_flutter.dart'; 12 | 13 | 14 | 15 | 16 | class Day7 extends StatefulWidget { 17 | @override 18 | createState() => Day7State(); 19 | } 20 | 21 | 22 | 23 | class Day7State extends State { 24 | 25 | 26 | 27 | PageController pageController; 28 | int page = 1; 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | 33 | return new Scaffold( 34 | 35 | backgroundColor: Colors.grey[200], 36 | 37 | // 传入 38 | body: new PageView( 39 | children: [ 40 | new Scaffold( 41 | backgroundColor: Colors.grey[200], 42 | appBar: CupertinoNavigationBar(middle: Text('PageLeft'),), 43 | body: new Center(child: new Text('PageLeft',style: TextStyle(fontSize: 20,),)), 44 | ), 45 | new TopBarPage(), 46 | new Scaffold( 47 | backgroundColor: Colors.grey[200], 48 | appBar: CupertinoNavigationBar(middle: Text('PageRight'),), 49 | body: new Center(child: new Text('PageRight',style: TextStyle(fontSize: 20,),)), 50 | ), 51 | ], 52 | controller: pageController, 53 | onPageChanged: onPageChanged, 54 | ), 55 | 56 | bottomNavigationBar: new BottomNavigationBar(items: [ 57 | new BottomNavigationBarItem( 58 | icon: new Icon(FontAwesomeIcons.font), 59 | title: new Text("Text"), 60 | backgroundColor: Colors.grey 61 | ), 62 | new BottomNavigationBarItem( 63 | icon: new Icon(FontAwesomeIcons.handPointUp), 64 | title: new Text("Top"), 65 | backgroundColor: Colors.grey), 66 | new BottomNavigationBarItem( 67 | icon: new Icon(FontAwesomeIcons.image), 68 | title: new Text("Button"), 69 | backgroundColor: Colors.grey, 70 | ), 71 | ], 72 | onTap: onTap, 73 | currentIndex: page 74 | ), 75 | ); 76 | } 77 | 78 | @override 79 | void initState() { 80 | super.initState(); 81 | // 设置初始化page 82 | pageController = new PageController(initialPage: this.page); 83 | } 84 | 85 | 86 | void onTap(int index) { 87 | pageController.animateToPage( 88 | index, 89 | // 设置页面转换效果的时间 90 | duration: const Duration(milliseconds: 300), 91 | // 设置转换时的效果 92 | curve: Curves.ease); 93 | } 94 | 95 | 96 | void onPageChanged(int page) { 97 | setState(() { 98 | this.page = page; 99 | }); 100 | } 101 | 102 | } -------------------------------------------------------------------------------- /flutter_road_widgets/lib/days/Day8.dart: -------------------------------------------------------------------------------- 1 | /** 2 | * Day 1 3 | * Text 4 | */ 5 | 6 | 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter/cupertino.dart'; 9 | import 'dart:core'; 10 | 11 | 12 | class Day8 extends StatefulWidget { 13 | @override 14 | createState() => Day8State(); 15 | } 16 | 17 | class Day8State extends State { 18 | var _tapText = '文字点击事件, 点我!'; 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | 23 | Widget textSection = Container( 24 | padding: const EdgeInsets.all(15.0), 25 | color: Colors.white, 26 | child: Column( 27 | children: [ 28 | Text('默认的Test'), 29 | //设置字体大小 30 | Padding( 31 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 32 | child: Text( 33 | '设置字体大小', 34 | style: TextStyle( 35 | fontSize: 20, 36 | ), 37 | ), 38 | ), 39 | //设置字体颜色 40 | Padding( 41 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 42 | child: Text( 43 | '设置字体颜色', 44 | style: TextStyle( 45 | color: const Color(0xFFFF856C), 46 | ), 47 | ), 48 | ), 49 | //设置粗体 50 | Padding( 51 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 52 | child: Text( 53 | '设置粗细和斜体', 54 | style: TextStyle( 55 | //字体粗细,粗体和正常 56 | fontWeight: FontWeight.bold, 57 | ), 58 | ), 59 | ), 60 | //设置斜体 61 | Padding( 62 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 63 | child: Text( 64 | '设置粗细和斜体', 65 | style: TextStyle( 66 | //文字样式,斜体和正常 67 | fontStyle: FontStyle.italic, 68 | ), 69 | ), 70 | ), 71 | //自动换行 72 | Padding( 73 | padding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 0.0), 74 | child: Text( 75 | '超出屏幕后设置自动换行,来,大声喊:啊啊啊啊啊啊啊啊啊啊啊啊啊啊', 76 | softWrap: true, 77 | ), 78 | ), 79 | //文字超出屏幕之后的处理方式 TextOverflow.clip剪裁 TextOverflow.fade 渐隐 TextOverflow.ellipsis省略号 80 | Padding( 81 | padding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 0.0), 82 | child: Text( 83 | '超出屏幕后设置用省略号,来,大声喊:啊啊啊啊啊啊啊啊啊啊啊啊啊啊', 84 | overflow: TextOverflow.ellipsis, 85 | ), 86 | ), 87 | 88 | //TextAlign.left左对齐,TextAlign.right右对齐,TextAlign.center居中对齐,TextAlign.justfy两端对齐 89 | Padding( 90 | padding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 0.0), 91 | 92 | child: Text( 93 | '文本居中', 94 | textAlign: TextAlign.center, 95 | ), 96 | ), 97 | 98 | Padding( 99 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 100 | child: Text( 101 | '给文字加下划线', 102 | style: TextStyle( 103 | //none无文字装饰,lineThrough删除线,overline文字上面显示线,underline文字下面显示线 104 | decoration: TextDecoration.underline, 105 | decorationColor: Colors.red, 106 | decorationStyle: TextDecorationStyle.wavy 107 | ), 108 | ), 109 | ), 110 | Padding( 111 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 112 | child: Text( 113 | '文字实现划去效果', 114 | style: TextStyle( 115 | //none无文字装饰,lineThrough删除线,overline文字上面显示线,underline文字下面显示线 116 | decoration: TextDecoration.lineThrough, 117 | decorationColor: Colors.black, 118 | decorationStyle: TextDecorationStyle.solid 119 | ), 120 | ), 121 | ), 122 | //单词间隙设置 123 | Padding( 124 | padding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 0.0), 125 | child: Text( 126 | '单词间隙设置 hello world', 127 | style: TextStyle( 128 | wordSpacing: 10.0, 129 | ), 130 | ), 131 | ), 132 | //字母间隙设置 133 | Padding( 134 | padding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 0.0), 135 | child: Text( 136 | '字母间隙设置 hello world', 137 | style: TextStyle( 138 | letterSpacing: 10.0, 139 | ), 140 | ), 141 | ), 142 | // 文本点击 143 | Padding( 144 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 145 | child: GestureDetector( 146 | onTap: () { 147 | setState(() { 148 | if(_tapText=="啊我被点到了"){ 149 | _tapText="文字点击事件, 点我!"; 150 | }else{ 151 | _tapText="啊我被点到了"; 152 | } 153 | }); 154 | }, 155 | child: Text( 156 | _tapText, 157 | style: TextStyle( 158 | fontSize: 16, 159 | fontWeight: FontWeight.bold, 160 | ), 161 | ), 162 | ), 163 | ), 164 | 165 | // 文本拼接 166 | Padding( 167 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 168 | child: Text.rich( 169 | new TextSpan( 170 | text: '文字拼接: ', 171 | style: new TextStyle( 172 | color: Colors.black, 173 | fontSize: 14, 174 | decoration: TextDecoration.none), 175 | children: [ 176 | new TextSpan( 177 | text: "文字一", 178 | style: new TextStyle( 179 | color: Colors.blue, 180 | fontSize: 20, 181 | decoration: TextDecoration.none)), 182 | new TextSpan( 183 | text: "文字二", 184 | style: new TextStyle( 185 | color: Colors.green, 186 | fontSize: 14, 187 | decoration: TextDecoration.none)), 188 | new TextSpan( 189 | text: "文字三", 190 | style: new TextStyle( 191 | color: Colors.red, 192 | fontSize: 18, 193 | decoration: TextDecoration.none)), 194 | ]), 195 | ), 196 | ) 197 | ], 198 | ), 199 | ); 200 | 201 | return Scaffold( 202 | backgroundColor: Colors.grey[200], 203 | appBar: CupertinoNavigationBar( 204 | middle: Text('Text'), 205 | ), 206 | body: textSection, 207 | 208 | ); 209 | } 210 | } -------------------------------------------------------------------------------- /flutter_road_widgets/lib/index.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/cupertino.dart'; 3 | import 'package:font_awesome_flutter/font_awesome_flutter.dart'; 4 | import 'package:flutter_road_widgets/days/Day1.dart'; 5 | import 'package:flutter_road_widgets/days/Day2.dart'; 6 | import 'package:flutter_road_widgets/days/Day3.dart'; 7 | import 'package:flutter_road_widgets/days/Day4.dart'; 8 | import 'package:flutter_road_widgets/days/Day5.dart'; 9 | import 'package:flutter_road_widgets/days/Day6.dart'; 10 | import 'package:flutter_road_widgets/days/Day7.dart'; 11 | import 'package:flutter_road_widgets/days/Day8.dart'; 12 | 13 | import 'package:flutter_road_widgets/days/Day10.dart'; 14 | import 'package:flutter_road_widgets/days/Day11.dart'; 15 | import 'package:flutter_road_widgets/days/Day12.dart'; 16 | 17 | void main() => runApp(new IndexPage()); 18 | 19 | class IndexPage extends StatelessWidget { 20 | Widget menuIcons (BuildContext context, Icon icon,String title, Widget nextPage) { 21 | return Container( 22 | decoration: BoxDecoration( 23 | border: BorderDirectional( 24 | bottom: const BorderSide(color: const Color(0xFFCCCCCC)), 25 | end: const BorderSide(color: const Color(0xFFCCCCCC)), 26 | ) 27 | ), 28 | child: InkWell( 29 | onTap: (){ 30 | Navigator.of(context).push(CupertinoPageRoute( 31 | builder: (BuildContext context) => nextPage, 32 | ),); 33 | }, 34 | child: Center( 35 | child: new Column( 36 | mainAxisAlignment: MainAxisAlignment.center, 37 | children: [ 38 | icon, 39 | Container( 40 | margin: EdgeInsets.only(top: 10.0), 41 | child: Text( 42 | title,style: TextStyle(fontSize: 16) 43 | ) 44 | ) 45 | ], 46 | ) 47 | ) 48 | ) 49 | ); 50 | } 51 | 52 | 53 | @override 54 | Widget build(BuildContext context) { 55 | return Scaffold( 56 | appBar: CupertinoNavigationBar( 57 | middle: const Text('Flutter Learning Road'), 58 | ), 59 | body: GridView.count( 60 | primary: false, 61 | crossAxisCount: 3, 62 | children: [ 63 | menuIcons(context, Icon(FontAwesomeIcons.font, size: 50.0, color: Color(0xFFc94a53)), 'Text' ,Day1()), 64 | menuIcons(context, Icon(FontAwesomeIcons.toggleOff, size: 50.0, color: Color(0xFFe16552)), 'Button' ,Day2()), 65 | menuIcons(context, Icon(FontAwesomeIcons.image, size: 50.0, color: Color(0xFFf19670)), 'Image' ,Day3()), 66 | menuIcons(context, Icon(FontAwesomeIcons.thList, size: 50.0, color: Color(0xFFe2975d)), 'ListView' ,Day4()), 67 | menuIcons(context, Icon(FontAwesomeIcons.thLarge, size: 50.0, color: Color(0xFFe9d78e)), 'GridView' ,Day5()), 68 | menuIcons(context, Icon(FontAwesomeIcons.clone, size: 50.0, color: Color(0xFFe4bf80)), 'Dialog' ,Day6()), 69 | menuIcons(context, Icon(FontAwesomeIcons.columns, size: 50.0, color: Color(0xFFe2975d)), 'NavigationBar' ,Day7()), 70 | menuIcons(context, Icon(FontAwesomeIcons.spinner, size: 50.0, color: Color(0xFFe2975d)), 'pending' ,Day8()), 71 | menuIcons(context, Icon(FontAwesomeIcons.spinner, size: 50.0, color: Color(0xFFe2975d)), 'pending' ,Day1()), 72 | menuIcons(context, Icon(FontAwesomeIcons.exchangeAlt, size: 50.0, color: Color(0xFFe2975d)), 'Async' ,Day10()), 73 | menuIcons(context, Icon(FontAwesomeIcons.networkWired, size: 50.0, color: Color(0xFFe2975d)), 'Network' ,Day11()), 74 | menuIcons(context, Icon(FontAwesomeIcons.asterisk, size: 50.0, color: Color(0xFFe2975d)), 'Test' ,Day12()), 75 | ], 76 | ), 77 | backgroundColor: Colors.white, 78 | ); 79 | } 80 | } -------------------------------------------------------------------------------- /flutter_road_widgets/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_road_widgets/index.dart'; 3 | 4 | void main() => runApp(new MyApp()); 5 | 6 | class MyApp extends StatelessWidget { 7 | // This widget is the root of your application. 8 | 9 | 10 | @override 11 | Widget build(BuildContext context) { 12 | return new MaterialApp( 13 | // 去 dubug 水印 14 | debugShowCheckedModeBanner: false, 15 | theme: new ThemeData( 16 | primarySwatch: Colors.blue, 17 | ), 18 | home: new IndexPage() 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /flutter_road_widgets/lib/subpage/MySingleChooseDialog.dart: -------------------------------------------------------------------------------- 1 | /** 2 | * Day 6 3 | * TopBarPage 4 | */ 5 | 6 | 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter/cupertino.dart'; 9 | import 'dart:core'; 10 | 11 | 12 | 13 | 14 | class MySingleChooseDialog extends StatefulWidget { 15 | @override 16 | createState() => MySingleChooseDialogState(); 17 | } 18 | 19 | 20 | class MySingleChooseDialogState extends State{ 21 | 22 | int groupValue1; 23 | 24 | ///更新 groupValue1, RadioListTile==groupValue 时候,则按钮被选中 25 | void updateGroupValue(int e) { 26 | setState(() { 27 | groupValue1 = e; 28 | }); 29 | } 30 | 31 | @override 32 | Widget build(BuildContext context) { 33 | 34 | return AlertDialog( 35 | title: Text('我是一个单选 Dialog'), 36 | content: SingleChildScrollView( 37 | child: ListBody( 38 | children: [ 39 | //value和groupValue值一样的话,则按钮选中 40 | new RadioListTile( 41 | title: const Text('A'), 42 | value: 1, 43 | activeColor: Colors.red, 44 | groupValue: groupValue1, 45 | onChanged: (int e) => updateGroupValue( e), 46 | ), 47 | new RadioListTile( 48 | title: const Text('B'), 49 | value: 2, 50 | activeColor: Colors.yellow, 51 | groupValue: groupValue1, 52 | onChanged: (int e) => updateGroupValue( e), 53 | ), 54 | new RadioListTile( 55 | title: const Text('C'), 56 | value: 3, 57 | activeColor: Colors.green, 58 | groupValue: groupValue1, 59 | onChanged: (int e) => updateGroupValue(e), 60 | ), 61 | ], 62 | ), 63 | ), 64 | actions: [ 65 | FlatButton( 66 | child: Text('确定'), 67 | onPressed: () { 68 | Navigator.of(context).pop(); 69 | }, 70 | ), 71 | ], 72 | ); 73 | } 74 | 75 | 76 | } -------------------------------------------------------------------------------- /flutter_road_widgets/lib/subpage/TopBarPage.dart: -------------------------------------------------------------------------------- 1 | /** 2 | * Day 6 3 | * TopBarPage 4 | */ 5 | 6 | 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter/cupertino.dart'; 9 | import 'dart:core'; 10 | import 'package:font_awesome_flutter/font_awesome_flutter.dart'; 11 | 12 | 13 | 14 | 15 | class TopBarPage extends StatefulWidget { 16 | @override 17 | createState() => TopBarPageState(); 18 | } 19 | 20 | 21 | class TopBarPageState extends State with SingleTickerProviderStateMixin{ 22 | 23 | TabController _tabController; 24 | 25 | @override 26 | void dispose() { 27 | _tabController.dispose(); 28 | super.dispose(); 29 | } 30 | 31 | void initState() { 32 | super.initState(); 33 | _tabController = new TabController(vsync: this, length: 2); 34 | } 35 | 36 | @override 37 | Widget build(BuildContext context) { 38 | return new Scaffold( 39 | appBar: new AppBar( 40 | title: Text('TopBarPage'), 41 | bottom: new TabBar( 42 | tabs: [ 43 | new Tab( 44 | icon: new Icon(FontAwesomeIcons.google), 45 | ), 46 | new Tab( 47 | icon: new Icon(FontAwesomeIcons.facebook), 48 | ), 49 | ], 50 | controller: _tabController, 51 | ), 52 | ), 53 | body: new TabBarView( 54 | controller: _tabController, 55 | children: [ 56 | new Center(child: new Text('Google',style: TextStyle(fontSize: 20,),)), 57 | new Center(child: new Text('Facebook',style: TextStyle(fontSize: 20,),)), 58 | ], 59 | ), 60 | ); 61 | } 62 | 63 | 64 | } -------------------------------------------------------------------------------- /flutter_road_widgets/lib/utils/carousel.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class Carousel extends StatefulWidget { 4 | 5 | ///All the [Widget] on this Carousel. 6 | final List children; 7 | 8 | ///Returns [children]`s [lenght]. 9 | int get childrenCount => children.length; 10 | 11 | ///The transition animation timing curve. Default is [Curves.ease] 12 | final Curve animationCurve; 13 | 14 | ///The transition animation duration. Default is 250ms. 15 | final Duration animationDuration; 16 | 17 | // Enable or Disable the indicator (dots). Default is true 18 | final bool showIndicator; 19 | 20 | //Enable/Disable radius Border for the images. Default is false 21 | final bool borderRadius; 22 | 23 | //Border Radius of the images. Default is [Radius.circular(8.0)] 24 | final Radius radius; 25 | 26 | //Move the Indicator From the Bottom 27 | final double moveIndicatorFromBottom; 28 | 29 | //Remove the radius bottom from the indicator background. Default false 30 | final bool noRadiusForIndicator; 31 | 32 | //Padding Size of the background Indicator. Default is 20.0 33 | final double indicatorBgPadding; 34 | 35 | // The base size of the dots. Default is 8.0 36 | final double dotSize; 37 | 38 | // The distance between the center of each dot. Default is 25.0 39 | final double dotSpacing; 40 | 41 | // The Color of each dot. Default is Colors.grey[300] 42 | final Color dotColor; 43 | 44 | // The Color of selected dot. Default is Colors.grey 45 | final Color dotSelectedColor; 46 | 47 | // The background Color of the dots. Default is [Colors.transparent] 48 | final Color dotBgColor; 49 | 50 | Carousel({ 51 | this.children, 52 | this.animationCurve = Curves.ease, 53 | this.animationDuration = const Duration(milliseconds: 250), 54 | this.showIndicator = true, 55 | this.borderRadius = false, 56 | this.radius, 57 | this.indicatorBgPadding = 20.0, 58 | this.moveIndicatorFromBottom = 0.0, 59 | this.noRadiusForIndicator = false, 60 | this.dotSize = 8.0, 61 | this.dotSpacing = 25.0, 62 | this.dotColor = const Color(0xFFCCCCCC), 63 | this.dotSelectedColor = Colors.grey, 64 | this.dotBgColor, 65 | }) : 66 | assert(children != null), 67 | assert(children.length > 1), 68 | assert(animationCurve != null), 69 | assert(animationDuration != null); 70 | 71 | 72 | @override 73 | State createState() => new _CarouselState(); 74 | } 75 | 76 | class _CarouselState extends State with SingleTickerProviderStateMixin { 77 | TabController _controller; 78 | ///Actual index of the displaying Widget 79 | int get actualIndex => _controller.index; 80 | 81 | int selectedIndex = 0; 82 | 83 | ///Returns the calculated value of the next index. 84 | int get nextIndex { 85 | var nextIndexValue = actualIndex; 86 | 87 | if(nextIndexValue < _controller.length - 1) 88 | nextIndexValue++; 89 | else 90 | nextIndexValue = 0; 91 | 92 | return nextIndexValue; 93 | } 94 | 95 | @override 96 | void initState() { 97 | super.initState(); 98 | 99 | _controller = new TabController(length: widget.childrenCount, vsync: this); 100 | _controller.addListener(_handleTabSelection); 101 | } 102 | 103 | @override 104 | void dispose() { 105 | _controller.dispose(); 106 | super.dispose(); 107 | } 108 | 109 | void _handleTabSelection() { 110 | setState(() { 111 | selectedIndex = _controller.index; 112 | }); 113 | } 114 | 115 | @override 116 | Widget build(BuildContext context) { 117 | return new Scaffold( 118 | body: new Stack( 119 | children: [ 120 | new TabBarView( 121 | children: widget.children.map((widget) => new Center(child: widget,)).toList(), 122 | controller: this._controller, 123 | ), 124 | widget.showIndicator ? new Positioned( 125 | bottom: widget.moveIndicatorFromBottom, 126 | left: 0.0, 127 | right: 0.0, 128 | child: new Container( 129 | decoration: new BoxDecoration( 130 | color: widget.dotBgColor == null ? Colors.transparent : widget.dotBgColor, 131 | borderRadius: widget.borderRadius ? (widget.noRadiusForIndicator ? null : new BorderRadius.only( 132 | bottomLeft: widget.radius != null ? widget.radius : new Radius.circular(8.0), 133 | bottomRight: widget.radius != null ? widget.radius : new Radius.circular(8.0) 134 | )) : null, 135 | ), 136 | padding: new EdgeInsets.all(widget.indicatorBgPadding), 137 | child: new Center( 138 | child: new DotsIndicator( 139 | controller: _controller, 140 | itemCount: widget.children.length, 141 | color: widget.dotColor, 142 | selectedIndex: selectedIndex, 143 | selectedColor: widget.dotSelectedColor, 144 | dotSize: widget.dotSize, 145 | dotSpacing: widget.dotSpacing, 146 | ), 147 | ), 148 | ), 149 | ) : new Container(), 150 | ], 151 | ) 152 | ); 153 | } 154 | } 155 | 156 | /// An indicator showing the currently selected page of a PageController 157 | class DotsIndicator extends StatelessWidget { 158 | DotsIndicator({ 159 | this.controller, 160 | this.itemCount, 161 | this.color, 162 | this.dotSize, 163 | this.selectedIndex, 164 | this.selectedColor, 165 | this.dotSpacing 166 | }); 167 | 168 | // The PageController that this DotsIndicator is representing. 169 | final TabController controller; 170 | 171 | // The number of items managed by the PageController 172 | final int itemCount; 173 | 174 | // Selected index 175 | final int selectedIndex; 176 | 177 | // The color of the dots. 178 | final Color color; 179 | 180 | // The color of the dots. 181 | final Color selectedColor; 182 | 183 | // The base size of the dots 184 | final double dotSize; 185 | 186 | // The distance between the center of each dot 187 | final double dotSpacing; 188 | 189 | Widget _buildDot(int index) { 190 | return new Container( 191 | width: dotSpacing, 192 | child: new Center( 193 | child: new Material( 194 | color: index == selectedIndex ? selectedColor : color, 195 | type: MaterialType.circle, 196 | child: new Container( 197 | width: dotSize, 198 | height: dotSize, 199 | ), 200 | ), 201 | ), 202 | ); 203 | } 204 | 205 | Widget build(BuildContext context) { 206 | return new Row( 207 | mainAxisAlignment: MainAxisAlignment.center, 208 | children: new List.generate(itemCount, _buildDot), 209 | ); 210 | } 211 | } -------------------------------------------------------------------------------- /flutter_road_widgets/lib/utils/carousel_pro.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | import 'package:flutter/material.dart'; 3 | import 'dart:async'; 4 | 5 | class Carousel extends StatefulWidget { 6 | //All the images on this Carousel. 7 | final List images; 8 | 9 | //The transition animation timing curve. Default is [Curves.ease] 10 | final Curve animationCurve; 11 | 12 | //The transition animation duration. Default is 300ms. 13 | final Duration animationDuration; 14 | 15 | // The base size of the dots. Default is 8.0 16 | final double dotSize; 17 | 18 | // The increase in the size of the selected dot. Default is 2.0 19 | final double dotIncreaseSize; 20 | 21 | // The distance between the center of each dot. Default is 25.0 22 | final double dotSpacing; 23 | 24 | // The Color of each dot. Default is Colors.white 25 | final Color dotColor; 26 | 27 | // The background Color of the dots. Default is [Colors.grey[800].withOpacity(0.5)] 28 | final Color dotBgColor; 29 | 30 | // Enable or Disable the indicator (dots). Default is true 31 | final bool showIndicator; 32 | 33 | //Padding Size of the background Indicator. Default is 20.0 34 | final double indicatorBgPadding; 35 | 36 | //How to show the images in the box. Default is cover 37 | final BoxFit boxFit; 38 | 39 | //Enable/Disable radius Border for the images. Default is false 40 | final bool borderRadius; 41 | 42 | //Border Radius of the images. Default is [Radius.circular(8.0)] 43 | final Radius radius; 44 | 45 | //Move the Indicator From the Bottom 46 | final double moveIndicatorFromBottom; 47 | 48 | //Remove the radius bottom from the indicator background. Default false 49 | final bool noRadiusForIndicator; 50 | 51 | //Enable/Disable Image Overlay Shadow. Default false 52 | final bool overlayShadow; 53 | 54 | //Choose the color of the overlay Shadow color. Default Colors.grey[800] 55 | final Color overlayShadowColors; 56 | 57 | //Choose the size of the Overlay Shadow, from 0.0 to 1.0. Default 0.5 58 | final double overlayShadowSize; 59 | 60 | //Enable/Disable the auto play of the slider. Default true 61 | final bool autoplay; 62 | 63 | //Duration of the Auto play slider by seconds. Default 3 seconds 64 | final Duration autoplayDuration; 65 | 66 | final Color selectedColor; 67 | 68 | Carousel({ 69 | this.images, 70 | this.animationCurve = Curves.ease, 71 | this.animationDuration = const Duration(milliseconds: 300), 72 | this.dotSize = 8.0, 73 | this.dotSpacing = 25.0, 74 | this.dotIncreaseSize = 2.0, 75 | this.dotColor = Colors.white, 76 | this.dotBgColor, 77 | this.selectedColor, 78 | this.showIndicator = true, 79 | this.indicatorBgPadding = 20.0, 80 | this.boxFit = BoxFit.cover, 81 | this.borderRadius = false, 82 | this.radius, 83 | this.moveIndicatorFromBottom = 0.0, 84 | this.noRadiusForIndicator = false, 85 | this.overlayShadow = false, 86 | this.overlayShadowColors, 87 | this.overlayShadowSize = 0.5, 88 | this.autoplay = true, 89 | this.autoplayDuration = const Duration(seconds: 3) 90 | }) : 91 | assert(images != null), 92 | assert(animationCurve != null), 93 | assert(animationDuration != null), 94 | assert(dotSize != null), 95 | assert(dotSpacing != null), 96 | assert(dotIncreaseSize != null), 97 | assert(dotColor != null); 98 | 99 | @override 100 | State createState() => new CarouselState(); 101 | } 102 | 103 | class CarouselState extends State { 104 | int _selected = 0; 105 | final _controller = new PageController(); 106 | 107 | @override 108 | void initState() { 109 | super.initState(); 110 | 111 | if(widget.autoplay) { 112 | new Timer.periodic(widget.autoplayDuration, (_) { 113 | if(_controller.page == widget.images.length-1) { 114 | _controller.animateToPage( 115 | 0, 116 | duration: widget.animationDuration, 117 | curve: widget.animationCurve, 118 | ); 119 | } else { 120 | _controller.nextPage(duration: widget.animationDuration, curve: widget.animationCurve); 121 | } 122 | }); 123 | } 124 | } 125 | 126 | @override 127 | void dispose() { 128 | super.dispose(); 129 | } 130 | 131 | @override 132 | Widget build(BuildContext context) { 133 | final List listImages = widget.images; 134 | 135 | return new Scaffold( 136 | body: new Stack( 137 | children: [ 138 | 139 | new Container( 140 | child: new PageView( 141 | physics: new AlwaysScrollableScrollPhysics(), 142 | controller: _controller, 143 | children: listImages, 144 | ), 145 | ), 146 | 147 | widget.showIndicator ? new Positioned( 148 | bottom: widget.moveIndicatorFromBottom, 149 | left: 0.0, 150 | right: 0.0, 151 | child: new Container( 152 | decoration: new BoxDecoration( 153 | color: widget.dotBgColor == null ? Colors.grey[800].withOpacity(0.5) : widget.dotBgColor, 154 | borderRadius: widget.borderRadius ? (widget.noRadiusForIndicator ? null : new BorderRadius.only( 155 | bottomLeft: widget.radius != null ? widget.radius : new Radius.circular(8.0), 156 | bottomRight: widget.radius != null ? widget.radius : new Radius.circular(8.0) 157 | )) : null, 158 | ), 159 | padding: new EdgeInsets.all(widget.indicatorBgPadding), 160 | child: new Center( 161 | child: new DotsIndicator( 162 | controller: _controller, 163 | itemCount: listImages.length, 164 | color: widget.dotColor, 165 | dotSize: widget.dotSize, 166 | selectedIndex: _selected, 167 | selectedColor: widget.selectedColor, 168 | dotSpacing: widget.dotSpacing, 169 | dotIncreaseSize: widget.dotIncreaseSize, 170 | onPageSelected: (int page) { 171 | _controller.animateToPage( 172 | page, 173 | duration: widget.animationDuration, 174 | curve: widget.animationCurve, 175 | ); 176 | 177 | setState(() { 178 | _selected = page; 179 | }); 180 | }, 181 | ), 182 | ), 183 | ), 184 | ) : new Container(), 185 | 186 | ], 187 | ), 188 | ); 189 | } 190 | } 191 | 192 | /// An indicator showing the currently selected page of a PageController 193 | class DotsIndicator extends StatelessWidget { 194 | DotsIndicator({ 195 | this.controller, 196 | this.itemCount, 197 | this.onPageSelected, 198 | this.color, 199 | this.selectedIndex, 200 | this.selectedColor, 201 | this.dotSize, 202 | this.dotIncreaseSize, 203 | this.dotSpacing 204 | }); 205 | 206 | // The PageController that this DotsIndicator is representing. 207 | final PageController controller; 208 | 209 | // The number of items managed by the PageController 210 | final int itemCount; 211 | 212 | // Called when a dot is tapped 213 | final ValueChanged onPageSelected; 214 | 215 | // The color of the dots. 216 | final Color color; 217 | 218 | final int selectedIndex; 219 | 220 | final Color selectedColor; 221 | 222 | // The base size of the dots 223 | final double dotSize; 224 | 225 | // The increase in the size of the selected dot 226 | final double dotIncreaseSize; 227 | 228 | // The distance between the center of each dot 229 | final double dotSpacing; 230 | 231 | Widget _buildDot(int index) { 232 | double selectedness = Curves.easeOut.transform( 233 | max( 234 | 0.0, 235 | 1.0 - ((controller.page ?? controller.initialPage) - index).abs(), 236 | ), 237 | ); 238 | 239 | print('selectednessd ${selectedness.round()} $index'); 240 | 241 | double zoom = 1.0 + (dotIncreaseSize - 1.0) * selectedness; 242 | return new Container( 243 | width: dotSpacing, 244 | child: new Center( 245 | child: new Material( 246 | color: color, 247 | type: MaterialType.circle, 248 | child: new Container( 249 | width: dotSize * zoom, 250 | height: dotSize * zoom, 251 | child: new InkWell( 252 | onTap: () => onPageSelected(index), 253 | ), 254 | ), 255 | ), 256 | ), 257 | ); 258 | } 259 | 260 | Widget build(BuildContext context) { 261 | return new Row( 262 | mainAxisAlignment: MainAxisAlignment.center, 263 | children: new List.generate(itemCount, _buildDot), 264 | ); 265 | } 266 | } -------------------------------------------------------------------------------- /flutter_road_widgets/lib/utils/flutter_icon_icons.dart: -------------------------------------------------------------------------------- 1 | /// Flutter icons FlutterIcon 2 | /// Copyright (C) 2018 by original authors @ fluttericon.com, fontello.com 3 | /// This font was generated by FlutterIcon.com, which is derived from Fontello. 4 | /// 5 | /// To use this font, place it in your fonts/ directory and include the 6 | /// following in your pubspec.yaml 7 | /// 8 | /// flutter: 9 | /// fonts: 10 | /// - family: FlutterIcon 11 | /// fonts: 12 | /// - asset: fonts/FlutterIcon.ttf 13 | /// 14 | /// 15 | /// * Meteocons, Copyright (C) 2012 by Alessio Atzeni 16 | /// Author: Alessio Atzeni 17 | /// License: SIL (http://scripts.sil.org/OFL) 18 | /// Homepage: http://www.alessioatzeni.com 19 | /// 20 | import 'package:flutter/widgets.dart'; 21 | 22 | class FlutterIcon { 23 | FlutterIcon._(); 24 | 25 | static const _kFontFam = 'FlutterIcon'; 26 | 27 | static const IconData cloud_moon = const IconData(0xe800, fontFamily: _kFontFam); 28 | static const IconData fahrenheit = const IconData(0xe801, fontFamily: _kFontFam); 29 | static const IconData clouds_flash_alt = const IconData(0xe802, fontFamily: _kFontFam); 30 | static const IconData sun_inv = const IconData(0xe803, fontFamily: _kFontFam); 31 | static const IconData moon_inv = const IconData(0xe804, fontFamily: _kFontFam); 32 | static const IconData clouds_inv = const IconData(0xe805, fontFamily: _kFontFam); 33 | static const IconData clouds_flash_inv = const IconData(0xe806, fontFamily: _kFontFam); 34 | static const IconData temperature = const IconData(0xe807, fontFamily: _kFontFam); 35 | static const IconData compass = const IconData(0xe808, fontFamily: _kFontFam); 36 | static const IconData na = const IconData(0xe809, fontFamily: _kFontFam); 37 | static const IconData celcius = const IconData(0xe80a, fontFamily: _kFontFam); 38 | static const IconData cloud_sun_inv = const IconData(0xe80b, fontFamily: _kFontFam); 39 | static const IconData cloud_moon_inv = const IconData(0xe80c, fontFamily: _kFontFam); 40 | static const IconData moon = const IconData(0xe80d, fontFamily: _kFontFam); 41 | static const IconData eclipse = const IconData(0xe80e, fontFamily: _kFontFam); 42 | static const IconData mist = const IconData(0xe80f, fontFamily: _kFontFam); 43 | static const IconData wind = const IconData(0xe810, fontFamily: _kFontFam); 44 | static const IconData snowflake = const IconData(0xe811, fontFamily: _kFontFam); 45 | static const IconData snow = const IconData(0xe812, fontFamily: _kFontFam); 46 | static const IconData snow_alt = const IconData(0xe813, fontFamily: _kFontFam); 47 | static const IconData cloud_inv = const IconData(0xe814, fontFamily: _kFontFam); 48 | static const IconData hail = const IconData(0xe815, fontFamily: _kFontFam); 49 | static const IconData clouds = const IconData(0xe816, fontFamily: _kFontFam); 50 | static const IconData clouds_flash = const IconData(0xe817, fontFamily: _kFontFam); 51 | static const IconData cloud_flash_inv = const IconData(0xe818, fontFamily: _kFontFam); 52 | static const IconData drizzle_inv = const IconData(0xe819, fontFamily: _kFontFam); 53 | static const IconData rain_inv = const IconData(0xe81a, fontFamily: _kFontFam); 54 | static const IconData fog_sun = const IconData(0xe81b, fontFamily: _kFontFam); 55 | static const IconData fog_moon = const IconData(0xe81c, fontFamily: _kFontFam); 56 | static const IconData fog_cloud = const IconData(0xe81d, fontFamily: _kFontFam); 57 | static const IconData fog = const IconData(0xe81e, fontFamily: _kFontFam); 58 | static const IconData cloud = const IconData(0xe81f, fontFamily: _kFontFam); 59 | static const IconData cloud_flash = const IconData(0xe820, fontFamily: _kFontFam); 60 | static const IconData cloud_flash_alt = const IconData(0xe821, fontFamily: _kFontFam); 61 | static const IconData drizzle = const IconData(0xe822, fontFamily: _kFontFam); 62 | static const IconData rain = const IconData(0xe823, fontFamily: _kFontFam); 63 | static const IconData windy = const IconData(0xe824, fontFamily: _kFontFam); 64 | static const IconData windy_rain_inv = const IconData(0xe825, fontFamily: _kFontFam); 65 | static const IconData snow_inv = const IconData(0xe826, fontFamily: _kFontFam); 66 | static const IconData snow_heavy_inv = const IconData(0xe827, fontFamily: _kFontFam); 67 | static const IconData windy_inv = const IconData(0xe828, fontFamily: _kFontFam); 68 | static const IconData sunrise = const IconData(0xe829, fontFamily: _kFontFam); 69 | static const IconData sun = const IconData(0xe82a, fontFamily: _kFontFam); 70 | static const IconData hail_inv = const IconData(0xe82b, fontFamily: _kFontFam); 71 | static const IconData windy_rain = const IconData(0xe82c, fontFamily: _kFontFam); 72 | static const IconData snow_heavy = const IconData(0xe82d, fontFamily: _kFontFam); 73 | static const IconData cloud_sun = const IconData(0xe82e, fontFamily: _kFontFam); 74 | } 75 | -------------------------------------------------------------------------------- /flutter_road_widgets/lib/utils/throttle_debounce.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | class Throttler{ 4 | 5 | Duration delay; 6 | var callback; 7 | List args; 8 | bool noTrailing; 9 | 10 | Throttler(this.delay, this.callback, this.args, [this.noTrailing=false]); 11 | 12 | var timeoutId; 13 | 14 | DateTime lastExec = new DateTime.now(); 15 | 16 | void throttle() { 17 | 18 | Duration elapsed = new DateTime.now().difference(lastExec); 19 | 20 | void exec() { 21 | lastExec = new DateTime.now(); 22 | callback(args); 23 | } 24 | 25 | if(elapsed.compareTo(delay) >= 0) { 26 | exec(); 27 | } 28 | //cancel the timeout scheduled for trailing callback 29 | if(timeoutId != null) 30 | timeoutId.cancel(); 31 | 32 | if( noTrailing == false) { 33 | //there should be a trailing callback, so schedule one 34 | //buggy here, should be 'delay - elasped' but dart async only supports const Duration for delay 35 | timeoutId = new Timer(delay, exec); 36 | } 37 | } 38 | } 39 | 40 | class Debouncer { 41 | 42 | Duration delay; 43 | var callback; 44 | List args; 45 | bool atBegin; 46 | 47 | Debouncer(this.delay, this.callback, this.args, [this.atBegin=false]); 48 | 49 | var timeoutId; 50 | 51 | void debounce() { 52 | 53 | void exec() { 54 | callback(args); 55 | } 56 | 57 | void clear() { 58 | timeoutId = null; 59 | } 60 | //cancel the previous timer if debounce is still being called before the delay period is over 61 | if(timeoutId != null) { 62 | timeoutId.cancel(); 63 | } 64 | //if atBegin is true, 'exec' has to executed the first time debounce gets called 65 | if(atBegin && timeoutId == null) { 66 | exec(); 67 | } 68 | //schedule a new call after delay time 69 | timeoutId = new Timer(delay, atBegin ? clear : exec); 70 | } 71 | 72 | } 73 | 74 | -------------------------------------------------------------------------------- /flutter_road_widgets/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_road_widgets 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 | font_awesome_flutter: any 23 | transparent_image: any 24 | cached_network_image: any 25 | dio: any 26 | url_launcher: any 27 | 28 | dev_dependencies: 29 | test: any 30 | flutter_test: 31 | sdk: flutter 32 | 33 | 34 | # For information on the generic Dart part of this file, see the 35 | # following page: https://www.dartlang.org/tools/pub/pubspec 36 | 37 | # The following section is specific to Flutter. 38 | flutter: 39 | 40 | # The following line ensures that the Material Icons font is 41 | # included with your application, so that you can use the icons in 42 | # the material Icons class. 43 | uses-material-design: true 44 | 45 | # To add assets to your application, add an assets section, like this: 46 | # assets: 47 | # - images/a_dot_burr.jpeg 48 | # - images/a_dot_ham.jpeg 49 | assets: 50 | - images/flutter.png 51 | # An image asset can refer to one or more resolution-specific "variants", see 52 | # https://flutter.io/assets-and-images/#resolution-aware. 53 | 54 | # For details regarding adding assets from package dependencies, see 55 | # https://flutter.io/assets-and-images/#from-packages 56 | 57 | # To add custom fonts to your application, add a fonts section here, 58 | # in this "flutter" section. Each entry in this list should have a 59 | # "family" key with the font family name, and a "fonts" key with a 60 | # list giving the asset and other descriptors for the font. For 61 | # example: 62 | # fonts: 63 | # - family: Schyler 64 | # fonts: 65 | # - asset: fonts/Schyler-Regular.ttf 66 | # - asset: fonts/Schyler-Italic.ttf 67 | # style: italic 68 | # - family: Trajan Pro 69 | # fonts: 70 | # - asset: fonts/TrajanPro.ttf 71 | # - asset: fonts/TrajanPro_Bold.ttf 72 | # weight: 700 73 | # 74 | # For details regarding fonts from package dependencies, 75 | # see https://flutter.io/custom-fonts/#from-packages 76 | -------------------------------------------------------------------------------- /flutter_road_widgets/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_road_widgets/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 | -------------------------------------------------------------------------------- /notes/Dart_Intro.md: -------------------------------------------------------------------------------- 1 | ## Dart入门笔记 2 | > 参考文献: https://www.dartlang.org/samples 3 | 4 | 感觉最近要入坑 **Flutter** 了, 于是决定先了解一下它用的语言: **Dart** 的使用方法,然后写一篇笔记总结一下常用方法。 5 | 6 | #### 运行代码的环境 7 | 8 | 大多数代码都可以在这个 DartPad 上运行: 9 | [https://dartpad.dartlang.org/](https://dartpad.dartlang.org/) 10 | #### 首先就是一个 Hello Word 11 | 12 | ``` 13 | void main() { 14 | print('Hello, World!'); 15 | } 16 | ``` 17 | #### Dart 变量类型 18 | 19 | Dart 可以像 JS 一样用 var 来申明不指定它类型的变量,也可以申明特定类型的变量。 20 | 21 | 用 var 来申明变量: 22 | 23 | ``` 24 | // 字符串 25 | var name = 'Voyager I'; 26 | // 整型 27 | var year = 1977; 28 | // 浮点型 29 | var antennaDiameter = 3.7; 30 | // 列表 List 31 | var flybyObjects = ['Jupiter', 'Saturn', 'Uranus', 'Neptune']; 32 | // Map 类型 33 | var image = { 34 | 'tags': ['saturn'], 35 | 'url': '//path/to/saturn.jpg' 36 | }; 37 | ``` 38 | 39 | 申明特定类型的变量: 40 | 41 | ``` 42 | // 字符串 43 | String name = 'Voyager I'; 44 | // 整型 45 | int year = 1977; 46 | // 浮点型 47 | double antennaDiameter = 3.7; 48 | // 列表 List 49 | List flybyObjects = ['Jupiter', 'Saturn', 'Uranus', 'Neptune']; 50 | // Map 类型 51 | Map image = { 52 | 'tags': ['saturn'], 53 | 'url': '//path/to/saturn.jpg' 54 | }; 55 | ``` 56 | 然后,赋值变量的时候要记得考虑关键字:[关键字表](http://wiki.jikexueyuan.com/project/dart-language-tour/keywords.html) 57 | 58 | 59 | #### 条件语句 60 | 61 | ``` 62 | //if 语句 63 | if (判断条件) { 64 | 执行语句; 65 | } else if (判断条件) { 66 | 执行语句; 67 | } else{ 68 | 执行语句; 69 | } 70 | ``` 71 | 72 | ``` 73 | // switch case 74 | var number = '1'; 75 | switch (number) { 76 | case '1': 77 | print('The number is 1'); 78 | break; 79 | case '2': 80 | print('The number is 2'); 81 | break; 82 | case '3': 83 | print('The number is 3'); 84 | break; 85 | default: 86 | print('The number is Unknown'); 87 | } 88 | ``` 89 | 90 | #### 循环语句 91 | 两种 For 循环 92 | 93 | ``` 94 | // 第一种,就像 java 的 for 循环 95 | for (var i = 0; i < 2; i++) { 96 | print(i); 97 | } 98 | // 第二种,遍历 List 和 Set, 和 Python 用法很像 99 | var myList = [0, 1, 2]; 100 | for (var x in myList) { 101 | print(x); // 0 1 2 102 | } 103 | ``` 104 | While 循环 105 | 106 | ``` 107 | var i=1; 108 | while (i < 200) { 109 | print(i); 110 | i += 1; 111 | } 112 | ``` 113 | 和其他语言一样,dart 也可以使用 break 和 continue 114 | 115 | #### Dart 函数 116 | ``` 117 | //计算一个斐波那契数列 118 | int fibonacci(int n) { 119 | if (n == 0 || n == 1) return n; 120 | return fibonacci(n - 1) + fibonacci(n - 2); 121 | } 122 | 123 | var result = fibonacci(20); 124 | ``` 125 | 上面这个函数看着和一般的语言没差别,但是在 Dart 中和还有一个神奇的写法: 126 | 127 | ``` 128 | void main() => RunWhile(20); 129 | 130 | RunWhile(n) { 131 | var i=1; 132 | while (i < n) { 133 | print(i); 134 | i += 1; 135 | } 136 | } 137 | ``` 138 | 这么 main() 函数后面直接跟了一个 => 来调用 RunWhile 方法,这是Dart中单行函数或方法的简写。 139 | 140 | #### 引用库 141 | 142 | 143 | ``` 144 | // 导入内置库 145 | import 'dart:math'; 146 | 147 | // 导入外部库 148 | import 'package:test/test.dart'; 149 | 150 | // 通过文件系统路径导入库 151 | import 'path/to/my_other_file.dart'; 152 | ``` 153 | 154 | #### 创建类 155 | 156 | ``` 157 | // 创建一个猫的类 158 | class Cat { 159 | String name; 160 | num age; 161 | Cat(name, age) { 162 | //初始化 163 | this.name=name; 164 | this.age=age; 165 | } 166 | void talk() { 167 | print('My name is $name, I am ${age} years old now.'); 168 | } 169 | } 170 | 171 | void main(){ 172 | // 实例化并调用方法 173 | var myCat=new Cat("小爪", 1); // 没错,我的🐱叫小爪!! 174 | myCat.talk(); 175 | } 176 | ``` 177 | 178 | 结尾了结尾了!umm, 推荐一个网站,我是看这个网站总结的: 179 | [https://www.dartlang.org/guides/language](https://www.dartlang.org/guides/language) 180 | 181 | 最后!希望 Dart 和 Flutter 能发展的好起来! 182 | 183 | umm, 就这样,拜拜👋 184 | 185 | 186 | 187 | -------------------------------------------------------------------------------- /notes/Flutter_Async.md: -------------------------------------------------------------------------------- 1 | ## Flutter 学习之路 - 异步任务 2 | > 实验 Flutter 的异步任务 --- [代码Github地址](https://github.com/draftbk/flutter_road/blob/master/flutter_road_widgets/lib/days/Day10.dart) 3 | 4 | ### Fultter 异步任务试验 5 | 6 | Flutter 在很多地方需要用到异步的任务,例如,加载网络数据,任务延迟执行等,所以异步任务是不可避免的问题。本次试验主要试验了下面几种情况: 7 | 8 | - 用 Future, then 实现任务延迟执行 9 | - 用 async 和 await 实现任务延迟执行 10 | - 测试调用 async 方法时,代码的执行顺序问题 11 | 12 | [代码地址](https://github.com/draftbk/flutter_road/blob/master/flutter_road_widgets/lib/days/Day10.dart) 13 | 14 | ![](https://github.com/draftbk/Blog_Resource/blob/master/Flutter/gif/flutter_road_async.gif) 15 | 16 | 17 | #### 用 Future, then 实现任务延迟执行 18 | 19 | Future 可以用来执行未来要执行的方法,例如下面代码,先输出 ”Started“, 调用 Future 以后过了一秒钟,再输出 ”Completed Task1“。 20 | 21 | ``` 22 | void thenCatch(){ 23 | mytext="Started"; 24 | setMyTextState(mytext); 25 | // then 用来说明 1 second 后做什么 26 | Future.delayed(Duration(seconds: 1)).then((_){ 27 | // 当运行完成 28 | mytext = mytext + "\n" + "Completed Task1"; 29 | setMyTextState(mytext); 30 | }).catchError((e){ 31 | // 当运行失败 32 | mytext=mytext+"\n"+'failed: ${e.toString()}'; 33 | setMyTextState(mytext); 34 | }); 35 | } 36 | ``` 37 | 38 | #### 用 async 和 await 实现任务延迟执行 39 | 40 | await 也是 Flutter 中很好的一种执行异步任务的方法。 41 | 42 | 但是要使用await,必须在有async标记的函数中运行,否则这个await会报错。 43 | 44 | 下面是一个加了 await 的方法,它的输出是怎么样呢? 45 | 46 | ``` 47 | Future asyncAwait() async{ 48 | mytext="Started"; 49 | setMyTextState(mytext); 50 | try{ 51 | // 这里没有 .then, 要加 await, await 是说在 await 完成前别往下执行 52 | await Future.delayed(Duration(seconds: 1)); 53 | mytext=mytext+"\n"+"Completed Task1"; 54 | setMyTextState(mytext); 55 | await Future.delayed(Duration(seconds: 1)); 56 | mytext=mytext+"\n"+"Completed Task2"; 57 | setMyTextState(mytext); 58 | }catch(e){ 59 | print('failed: ${e.toString()}'); 60 | } 61 | } 62 | ``` 63 | 64 | 答案是: 65 | 66 | ``` 67 | Started 68 | --- 1 second --- 69 | Completed Task1 70 | --- 2 second --- 71 | Completed Task2 72 | ``` 73 | 先输出 ”Start“, 然后过一秒,输出 ”Completed Task1“ 再过一秒输出 ”Completed Task2“ 。 74 | 75 | 如果把方法里的 await 去掉,看看会发生什么呢,结果是,Task1 和 Task2不会等待Future.delayed 完成,会直接执行。 76 | 77 | ``` 78 | Started 79 | Completed Task1 80 | Completed Task2 81 | --- 1 second --- 82 | ``` 83 | 84 | #### 测试调用 async 方法时,代码的执行顺序问题 85 | 86 | 那如果说,代码依次是 Task1, Task2, Task3, Task4, Task2 是一个异步的方法,Task3 , Task4 需要等待 Task2 完成吗? 87 | 88 | 代码如下: 89 | 90 | ``` 91 | Future asyncAwaitWithTask() async{ 92 | mytext="Started"; 93 | setMyTextState(mytext); 94 | try{ 95 | // 这里没有 .then, 要加 await, await 是说在 await 完成前别往下执行 96 | await Future.delayed(Duration(seconds: 1)); 97 | mytext=mytext+"\n"+"Completed Task1"; 98 | setMyTextState(mytext); 99 | task2(); 100 | mytext=mytext+"\n"+"Completed Task3"; 101 | setMyTextState(mytext); 102 | mytext=mytext+"\n"+"Completed Task4"; 103 | setMyTextState(mytext); 104 | }catch(e){ 105 | print('failed: ${e.toString()}'); 106 | } 107 | } 108 | 109 | void task2() async{ 110 | await Future.delayed(Duration(seconds: 1)); 111 | mytext=mytext+"\n"+"Completed Task2"; 112 | setMyTextState(mytext); 113 | } 114 | ``` 115 | 答案是, Task3, Task4 会先于 Task2 执行,最前面的 GIF 图就是在运行的这个场景。 116 | 117 | ``` 118 | Started 119 | --- 1 second --- 120 | Completed Task1 121 | Completed Task3 122 | Completed Task4 123 | --- 2 second --- 124 | Completed Task2 125 | ``` 126 | 127 | 128 | ### Flutter 学习之路 Github 地址 129 | 130 | [https://github.com/draftbk/flutter_road](https://github.com/draftbk/flutter_road) 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /notes/Flutter_Button.md: -------------------------------------------------------------------------------- 1 | ## Flutter 学习之路 - Button 控件 2 | > 实验一些常用的 Button 功能 ([代码Github地址](https://github.com/draftbk/flutter_road/blob/master/flutter_road_widgets/lib/days/Day2.dart)) 3 | 4 | ### Button 实验 5 | 6 | 实验了 Button 常用的一些功能 7 | 8 | - RaisedButton 9 | - FlatButton 10 | - 悬浮按钮 (FloatingActionButton) 11 | - 宽的悬浮按钮 (FloatingActionButton.extended) 12 | - 滚动条(Slider) 13 | - 复选框(Checkbox) 14 | - 选项按钮 (Radio Buttons) 15 | 16 | [代码地址](https://github.com/draftbk/flutter_road/blob/master/flutter_road_widgets/lib/days/Day2.dart) 17 | 18 | ![](https://github.com/draftbk/Blog_Resource/blob/master/Flutter/gif/flutter_road_button.gif) 19 | 20 | 21 | 22 | #### RaisedButton 23 | 24 | 用 child 的方式添加文字,用 onPressed 方法监听按钮行为。 25 | 26 | ``` 27 | // RaisedButton 28 | Padding( 29 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 30 | child: new RaisedButton( 31 | onPressed: () {print('button click');}, 32 | child: new Text("RaisedButton"), 33 | ), 34 | ), 35 | ``` 36 | 37 | #### FlatButton 38 | 39 | 和 RaisedButton 一样用 child 的方式添加文字,用 onPressed 方法监听按钮行为。 40 | FlatButton 本身是透明且没有突出的,所以设置了 color 使它更明显 41 | 42 | 43 | ``` 44 | // FlatButton 45 | Padding( 46 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 47 | child: new FlatButton( 48 | onPressed: () {print('button click');}, 49 | child: new Text("FlatButton"), 50 | color: Color(0xFFe16552), 51 | ), 52 | ), 53 | ``` 54 | 55 | #### 悬浮按钮 (FloatingActionButton) 56 | 57 | 悬浮按钮,可以通过改变 child 来设置 button 上显示文字或者 icon。 58 | 59 | 同时这里有个要注意的点,就是 **material design** 建议每个屏幕只有一个 FloatingActionButton,所以如果一定要两个(比如像我这样写demo),就要把这个 heroTag 设置为 null。 60 | 61 | ``` 62 | //FloatingActionButton 多个FloatingActionButton的时候会报错,要加 heroTag: null 63 | Padding( 64 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 65 | child: Row( 66 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 67 | children: [ 68 | // FloatingActionButton 69 | new FloatingActionButton( 70 | onPressed: () {print('button click');}, 71 | foregroundColor: Colors.white, 72 | backgroundColor: Color(0xFFf19670), 73 | child: new Icon(Icons.add), 74 | heroTag: null, 75 | ), 76 | // FloatingActionButton 77 | new FloatingActionButton( 78 | onPressed: () {print('button click');}, 79 | foregroundColor: Colors.white, 80 | backgroundColor: Color(0xFFf19670), 81 | child: new Text("文字"), 82 | heroTag: null, 83 | ), 84 | ], 85 | ), 86 | ), 87 | ``` 88 | #### 宽的悬浮按钮 (FloatingActionButton.extended) 89 | 90 | 可以看我上面的动图,有这个按钮的效果,感觉还挺棒的哈哈。 91 | 92 | ``` 93 | // FloatingActionButton.extended 94 | Padding( 95 | padding: const EdgeInsets.fromLTRB(0.0, 15.0, 0.0, 0.0), 96 | child: new FloatingActionButton.extended( 97 | onPressed: () { 98 | print('button click'); 99 | }, 100 | foregroundColor: Colors.white, 101 | backgroundColor: Colors.amber, 102 | icon: new Icon(Icons.flag,color: Colors.red,), 103 | label: new Text('FloatingActionButton.extended', maxLines: 1), 104 | ) 105 | ), 106 | ``` 107 | 108 | #### 滚动条(Slider) 109 | 110 | ``` 111 | Padding( 112 | padding: const EdgeInsets.fromLTRB(0.0, 15.0, 0.0, 0.0), 113 | child: new Slider( 114 | value: mCurrentValue, 115 | min: 1.0, 116 | max: 10.0, 117 | onChanged: (e) { 118 | setState(() { 119 | //四舍五入的双精度值 120 | mCurrentValue = e.roundToDouble(); 121 | }); 122 | } 123 | ) 124 | ), 125 | ``` 126 | 127 | #### 复选框(Checkbox) 128 | 129 | ``` 130 | Padding( 131 | padding: const EdgeInsets.fromLTRB(0.0, 15.0, 0.0, 0.0), 132 | child: new Checkbox( 133 | value: isChecked, 134 | onChanged: (bool){ 135 | setState(() { 136 | isChecked=bool; 137 | }); 138 | }, activeColor: Colors.blue, 139 | ) 140 | ), 141 | ``` 142 | 143 | #### 选项按钮 (Radio Buttons) 144 | 145 | 这里如果把新建的 Radio 的值设置为 null, 这个 Radio 就是不可选的,会显示一个灰色的状态。 146 | 147 | ``` 148 | // Radio 149 | Padding( 150 | padding: const EdgeInsets.fromLTRB(0.0, 15.0, 0.0, 0.0), 151 | child: new ButtonBar(//ButtonBar:水平排列按钮 152 | alignment: MainAxisAlignment.center, 153 | children: [ 154 | //value和groupValue值一样的话,则按钮选中 155 | new Radio(value: 1, 156 | groupValue: groupValue1, 157 | onChanged: (int e) => updateGroupValue(e)), 158 | new Radio(value: 2, 159 | groupValue: groupValue1, 160 | onChanged: (int e) => updateGroupValue(e)), 161 | new Radio(value: 3, 162 | groupValue: groupValue1, 163 | onChanged: (int e) => updateGroupValue(e)), 164 | new Radio(value: 4, 165 | groupValue: groupValue1, 166 | onChanged: (int e) => updateGroupValue(e)), 167 | //value 值为 null 则表示按钮不可用 168 | new Radio(value: null, groupValue: null, onChanged: null) 169 | ], 170 | ) 171 | ), 172 | ``` 173 | 174 | #### 遇到的问题 175 | 176 | 感觉对于控件,各个参数主要是看官网文档,然后自己改改, 所以还是记录一下遇到的问题。 177 | 178 | ##### 问题一: 当多个 FloatingActionButton 的时候程序运行会黑屏 179 | 180 | 解决方案:把 **heroTag** 设置为 **null** 181 | 182 | ``` 183 | new FloatingActionButton( 184 | onPressed: () {print('button click');}, 185 | foregroundColor: Colors.white, 186 | backgroundColor: Color(0xFFf19670), 187 | child: new Icon(Icons.add), 188 | heroTag: null, 189 | ), 190 | ``` 191 | 看了官网的说明,大意是 **material design** 建议每个屏幕只有一个 FloatingActionButton,所以如果一定要两个(比如像我这样写demo),就把这个 heroTag 设置为 null。 192 | 193 | 官网对于 heroTag 的说明: [link](https://docs.flutter.io/flutter/material/FloatingActionButton/heroTag.html) 194 | 195 | #### Flutter 学习之路 Github 地址 196 | 197 | [https://github.com/draftbk/flutter_road](https://github.com/draftbk/flutter_road) 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | -------------------------------------------------------------------------------- /notes/Flutter_Dialog.md: -------------------------------------------------------------------------------- 1 | ## Flutter 学习之路 - 对话框(Dialog) 2 | > 实验一些常用的对话框实现方式--- [代码Github地址](https://github.com/draftbk/flutter_road/blob/master/flutter_road_widgets/lib/days/Day6.dart) 3 | 4 | ### Dialog 实验 5 | 6 | 补上这个应该在第六篇博客就想写的坑,试验在 Flutter 中对 dialog 的各种使用方式。 7 | 8 | Flutter 官方建议使用 SimpleDialog 和 AlertDialog 两种方式来实现 Dialog, 然后这篇文章受下面这篇安卓的博客的启发,尝试实现一些不同功能的 Dialog: 9 | 10 | [https://www.cnblogs.com/gzdaijie/p/5222191.html](https://www.cnblogs.com/gzdaijie/p/5222191.html) 11 | 12 | 13 | ![](https://github.com/draftbk/Blog_Resource/blob/master/Flutter/gif/flutter_road_navigationbar.gif) 14 | 15 | 16 | #### 底部提示栏 17 | 18 | 最简单的提示方式,从底部弹出提示。 19 | 20 | ```Dart 21 | Future _showSnackBar(BuildContext context, String text) async { 22 | final scaffold = Scaffold.of(context); 23 | scaffold.showSnackBar( 24 | SnackBar( 25 | content: Text(text), 26 | ), 27 | ); 28 | } 29 | ``` 30 | 31 | 32 | #### 简单的 Dialog 33 | 34 | 见到提示对话框,只是提示功能,不需要交互。当看到显示之后,就只需要点击 “是的”,表示知道就行了。 35 | 36 | ```Dart 37 | Future _showSnackBar(BuildContext context, String text) async { 38 | final scaffold = Scaffold.of(context); 39 | scaffold.showSnackBar( 40 | SnackBar( 41 | content: Text(text), 42 | ), 43 | ); 44 | } 45 | ``` 46 | 47 | #### 一个列表的 Dialog 48 | 49 | 列表的 Dialog 可以选择点击不同的 item 进行不同的操作。 50 | 51 | 在实现的时候遇到了一个坑,就是,在SingleChildScrollView里不能用 ListView,是直接在 ListBody 里面加入 ListTile 就好了。 52 | 53 | ```Dart 54 | Future _showListAlertDialog() async { 55 | return showDialog( 56 | context: context, 57 | barrierDismissible: false, // user must tap button! 58 | builder: (BuildContext context) { 59 | return AlertDialog( 60 | title: Text('我是一个列表 Dialog'), 61 | content: SingleChildScrollView( 62 | child: ListBody( 63 | children: [ 64 | ListTile( 65 | leading: Icon(Icons.map), 66 | title: Text('Map'), 67 | onTap: () { 68 | setMyTextState("你选择了: Map"); 69 | Navigator.of(context).pop(); 70 | }, 71 | ), 72 | ListTile( 73 | leading: Icon(Icons.photo_album), 74 | title: Text('Album'), 75 | onTap: () { 76 | setMyTextState("你选择了: Album"); 77 | Navigator.of(context).pop(); 78 | }, 79 | ), 80 | ListTile( 81 | leading: Icon(Icons.phone), 82 | title: Text('Phone'), 83 | onTap: () { 84 | setMyTextState("你选择了: Phone"); 85 | Navigator.of(context).pop(); 86 | }, 87 | ), 88 | ], 89 | ), 90 | ), 91 | actions: [ 92 | FlatButton( 93 | child: Text('返回'), 94 | onPressed: () { 95 | Navigator.of(context).pop(); 96 | }, 97 | ), 98 | ], 99 | ); 100 | }, 101 | ); 102 | } 103 | ``` 104 | 105 | 106 | 107 | #### 单选框 Dialog (啊啊啊我还是先写一篇 setState, stateful widget 之类的文章再写这个好了!现在写就是在乱试,乱写!) 108 | 109 | 一开始以为会和上面那个 Dialog 差不多实现,实际上还是遇到了问题,发现在按下按钮不会产生选中效果,因为这个 110 | 111 | ### Flutter 学习之路 Github 地址 112 | 113 | 这是项目的 GitHub 地址,正在持续更新,欢迎 Star 呀!╮( ̄▽ ̄)╭ 114 | 115 | [https://github.com/draftbk/flutter_road](https://github.com/draftbk/flutter_road) 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /notes/Flutter_Gridview.md: -------------------------------------------------------------------------------- 1 | ## Flutter 学习之路 - Gridview 2 | > 实验一些常用的 Gridview 功能 --- [代码Github地址](https://github.com/draftbk/flutter_road/blob/master/flutter_road_widgets/lib/days/Day5.dart) 3 | 4 | ### Gridview 实验 5 | 6 | Flutter 学习之路第五次实验,实验了 Gridview 常用的一些功能,用 Gridview 实现单词软件的一个基础功能。 7 | 8 | - 设置 gridview 各个属性设置(间距,每行个数,长宽比) 9 | - 自定义 item, 以及 gridview item 点击事件 10 | - 动态添加 gridview 的 item 11 | 12 | [代码地址](https://github.com/draftbk/flutter_road/blob/master/flutter_road_widgets/lib/days/Day5.dart) 13 | 14 | ![](https://github.com/draftbk/Blog_Resource/blob/master/Flutter/gif/flutter_road_gridview.gif) 15 | 16 | 17 | #### 设置 gridview 各个属性设置(间距,每行个数,长宽比) 18 | 19 | - 用 crossAxisCount 来设置每行个数 20 | - 用 crossAxisSpacing 设置水平间隙 21 | - 用 mainAxisSpacing 设置上下间隙 22 | - 用 childAspectRatio 来设置宽高比例 23 | 24 | ``` 25 | child: GridView.count( 26 | // 每行有几个子控件 27 | crossAxisCount: 2, 28 | // 水平子Widget之间间距 29 | crossAxisSpacing: 10.0, 30 | // 设置上下间隙 31 | mainAxisSpacing: 8.0, 32 | // 子Widget宽高比例 33 | childAspectRatio: 2.0, 34 | children: List.generate(listNumber, (index) { 35 | return gridItem(context, index); 36 | }), 37 | ), 38 | ``` 39 | 40 | #### 自定义 item, 以及 gridview item 点击事件 41 | 42 | 这两个一起写是因为,实际上,item 点击是建立在自定义 item 上的,能自定义 item 了就能点击了。 43 | 44 | 自定义一个 gridItem 的 Widget 45 | 46 | ``` 47 | Widget gridItem (BuildContext context, int _index) { 48 | int index=_index%words.length; 49 | return Container( 50 | alignment: Alignment.center, 51 | child: GestureDetector( 52 | onTap: () { 53 | setState(() { 54 | String temp=words[index]; 55 | words[index]=translations[index]; 56 | translations[index]=temp; 57 | }); 58 | }, 59 | child: Text( 60 | words[index], 61 | style: TextStyle( 62 | fontSize: 28, 63 | color: Colors.white, 64 | ), 65 | ), 66 | ), 67 | color:myColor, 68 | ); 69 | } 70 | ``` 71 | 72 | 用 List.generate 加载自定义的 gridItem 73 | 74 | ``` 75 | Widget gridViewSection = Builder( 76 | builder: (context) => Container( 77 | margin: EdgeInsets.fromLTRB(5.0, 5.0, 5.0, 5.0), 78 | height: 600.0, 79 | child: GridView.count( 80 | // 每行有几个子控件 81 | crossAxisCount: 2, 82 | // 水平子Widget之间间距 83 | crossAxisSpacing: 10.0, 84 | // 水平子Widget之间间距 85 | mainAxisSpacing: 8.0, 86 | // 子Widget宽高比例 87 | childAspectRatio: 2.0, 88 | children: List.generate(listNumber, (index) { 89 | return gridItem(context, index); 90 | }), 91 | ), 92 | ) 93 | ); 94 | ``` 95 | 96 | #### 动态添加 gridview 的 item 97 | 98 | 这个和之前写 listview 的动态添加套路差不多,就是改变下面这个 listNumber 的值,就可以完成动态添加. 99 | 100 | ``` 101 | children: List.generate(listNumber, (index) { 102 | return gridItem(context, index); 103 | }), 104 | ``` 105 | 同样,别忘了用 setState 106 | 107 | ``` 108 | onTap: () { 109 | setState(() { 110 | String temp=words[index]; 111 | words[index]=translations[index]; 112 | translations[index]=temp; 113 | }); 114 | }, 115 | ``` 116 | 117 | ### Flutter 学习之路 Github 地址 118 | 119 | [https://github.com/draftbk/flutter_road](https://github.com/draftbk/flutter_road) 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /notes/Flutter_Image.md: -------------------------------------------------------------------------------- 1 | ## Flutter 学习之路 - Image 控件 2 | > 实验一些常用的 Image 功能 ([代码Github地址](https://github.com/draftbk/flutter_road/blob/master/flutter_road_widgets/lib/days/Day3.dart)) 3 | 4 | ### Image 试验 5 | 6 | Flutter 学习之路第三次试验,试验了有关于 Image 常用的一些功能,包括图片本地加载,图片和 GIF 的网络加载,图片渐现呈现,从网络加载图片并缓存在内存中。 7 | 8 | [代码地址](https://github.com/draftbk/flutter_road/blob/master/flutter_road_widgets/lib/days/Day3.dart) 9 | 10 | ![](https://github.com/draftbk/Blog_Resource/blob/master/Flutter/gif/flutter_road_image.gif) 11 | 12 | ##### 加载本地图片 13 | 14 | 在 lib 同级目录下创建文件夹 images, 并且在 pubspec.yaml 文件中添加如下几行。 15 | 16 | ``` 17 | flutter: 18 | assets: 19 | - images/flutter.png 20 | ``` 21 | 22 | 用 AssetImage 获取图片 23 | 24 | ``` 25 | // Image from asserts 26 | Padding( 27 | padding: const EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 0.0), 28 | child: new Image( 29 | image:new AssetImage('images/flutter.png'), 30 | width: 50, 31 | height: 50, 32 | ), 33 | ), 34 | ``` 35 | 36 | ##### 根据网络链接加载图片 37 | 38 | ``` 39 | // Image from internet 40 | Padding( 41 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 42 | child: Image.network( 43 | 'https://github.com/draftbk/Blog_Resource/blob/master/Flutter/picture/day3/flutter.png?raw=true', 44 | scale: 4, 45 | ), 46 | ), 47 | ``` 48 | 49 | ##### 从网络链接加载 **GIF** 50 | 51 | 可以很方便地加载 GIF 是个很棒的功能了,找了个 Google 动图哈哈 52 | 53 | ``` 54 | // Gif from internet 55 | Padding( 56 | padding: const EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0), 57 | child:Image.network( 58 | 'https://github.com/draftbk/Blog_Resource/blob/master/Flutter/gif/day3/google.gif?raw=true', 59 | scale: 4, 60 | ), 61 | ), 62 | ``` 63 | 64 | ##### FadeInImage(图片渐现呈现) 65 | 66 | 在 pubspec.yaml 加入 cached\_network\_image 67 | 68 | ``` 69 | // FadeInImage 70 | Padding( 71 | padding: const EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0), 72 | child: FadeInImage.memoryNetwork( 73 | width: 180, 74 | height: 180, 75 | placeholder: kTransparentImage, 76 | image: 'https://github.com/draftbk/Blog_Resource/blob/master/Flutter/picture/day3/flutter.png?raw=true', 77 | ), 78 | ), 79 | ``` 80 | 81 | ##### CachedNetworkImage (从网络加载图片并缓存在内存中) 82 | 83 | 在 pubspec.yaml 加入 cached\_network\_image 84 | 85 | ``` 86 | // CachedNetworkImage 87 | Padding( 88 | padding: const EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0), 89 | child: CachedNetworkImage( 90 | width: 100, 91 | height: 100, 92 | placeholder: CircularProgressIndicator(), 93 | imageUrl: 94 | 'https://github.com/draftbk/Blog_Resource/blob/master/Flutter/picture/day3/flutter.png?raw=true', 95 | ), 96 | ), 97 | ``` 98 | 99 | 100 | #### 遇到的问题 101 | 102 | 所以还是记录一些自己遇到的问题。 103 | 104 | ##### 问题一: 当我使用如下代码加载 Gif 以及 png 时,不能显示 105 | 106 | 107 | ``` 108 | // Gif from internet 109 | adding( 110 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 111 | child:Image.network( 112 | 'https://github.com/draftbk/Blog_Resource/blob/master/Flutter/gif/day3/google.gif?raw=true', 113 | scale: 2, 114 | ), 115 | ) 116 | ``` 117 | 118 | 解决方法:在链接后面加上 **?raw=true** 就可以显示了 119 | 120 | ``` 121 | 'https://github.com/draftbk/Blog_Resource/blob/master/Flutter/gif/day3/google.gif?raw=true', 122 | ``` 123 | ##### 问题二: 不知道 assets 文件夹在哪创建,图片放哪可以被用到 124 | 125 | 126 | 查了一下发现,其实不用非要 assets 文件夹,Flutter 使用 pubspec.yaml 文件(位于项目根目录),来识别应用程序所需的asset。 可以创建一个其他名字的文件夹来标识 assets 路径。 127 | 128 | ``` 129 | flutter: 130 | assets: 131 | - images/flutter.png 132 | ``` 133 | 134 | ##### 问题三:在导入 package 的时候有时候不知道导入什么版本 135 | 136 | 懒人方法:any 137 | 138 | ``` 139 | dependencies: 140 | flutter: 141 | sdk: flutter 142 | transparent_image: any 143 | cached_network_image: any 144 | ``` 145 | 146 | ##### 问题四:最开始没有给 Container 设置宽度,在加载图片时动画布局变化很糟(果然还是新手233) 147 | 148 | 解决:给 Container 设置 width 149 | 150 | ``` 151 | Widget buttonSection = Container( 152 | padding: const EdgeInsets.all(15.0), 153 | width: 1000, 154 | ``` 155 | 156 | #### Flutter 学习之路 Github 地址 157 | 158 | [https://github.com/draftbk/flutter_road](https://github.com/draftbk/flutter_road) 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /notes/Flutter_Interview_Problem.md: -------------------------------------------------------------------------------- 1 | ## Flutter 面试可能遇到的问题 2 | > 整理一些面试问题,也好明白以后学习的方向 3 | 4 | 5 | 6 | 7 | ### Dart 语言 8 | 9 | #### 1. dart是值传递还是引用传递 10 | 11 | 值传递(Java 也是) 12 | 13 | 14 | 15 | ### Android 端 16 | 17 | 18 | 19 | ### 来源 20 | 21 | 感谢网上分享面经的前辈们,给我们提供要提高的方向。 22 | 23 | - [可以算是Flutter面试凉凉经吧](https://juejin.im/post/5c67d621518825620a7f133e) -------------------------------------------------------------------------------- /notes/Flutter_Listview.md: -------------------------------------------------------------------------------- 1 | ## Flutter 学习之路 - Listview 入门 2 | > 实验一些常用的 List 功能 --- [代码Github地址](https://github.com/draftbk/flutter_road/blob/master/flutter_road_widgets/lib/days/Day4.dart) 3 | 4 | ### Listview 实验 5 | 6 | 实验了 Listview 常用的一些功能 7 | 8 | - 实现水平的 Listview 9 | - 给Listview item 加上点击事件 10 | - Listview 动态更新 11 | 12 | [代码地址](https://github.com/draftbk/flutter_road/blob/master/flutter_road_widgets/lib/days/Day4.dart) 13 | 14 | ![](https://github.com/draftbk/Blog_Resource/blob/master/Flutter/gif/flutter_road_listview.gif) 15 | 16 | #### 实现水平的 Listview 17 | 18 | 把属性 scrollDirection 设置为 Axis.horizontal 就能水平了,真的好方便。下面的代码为了避免太长我就选了一部分,实际上children还要多才有效果,可以看我 github 上的源码,或者自己加几个就好了。 19 | 20 | 21 | ``` 22 | child: ListView( 23 | scrollDirection: Axis.horizontal, 24 | children: [ 25 | Container( 26 | width: 160.0, 27 | color: Colors.red, 28 | ), 29 | Container( 30 | width: 160.0, 31 | color: Colors.blue, 32 | ), 33 | // Add more childre 34 | ], 35 | ), 36 | ``` 37 | 38 | #### 给 Listview item 加上点击事件 39 | 40 | 点击事件感觉和处在 listview 里的 children 有关,children 是怎么设置点击事件,就按它的设置就好。 41 | 42 | ``` 43 | child: ListView( 44 | children: [ 45 | ListTile( 46 | leading: Icon(Icons.map), 47 | title: Text('Map'), 48 | onTap: (){ 49 | _showToast(context,"Map"); 50 | }, 51 | ), 52 | ], 53 | ) 54 | ``` 55 | 56 | ##### Listview 动态更新 57 | 用 ListView.builder 以及 一个外部的 List, 然后写一个方法更新 List 的值 58 | 59 | ``` 60 | List items=[]; 61 | // show listview by item 62 | Widget dynamicSection = Container( 63 | margin: EdgeInsets.symmetric(vertical: 5.0), 64 | height: 200.0, 65 | child: ListView.builder( 66 | itemCount: items.length, 67 | itemBuilder: (context,index){ 68 | return ListTile( 69 | leading: Icon(Icons.send), 70 | title: new Text("NewItem $index")); 71 | } 72 | ) 73 | ); 74 | // modify items 75 | void _addListDate(){ 76 | setState(() { 77 | items.add(1); 78 | }); 79 | } 80 | ``` 81 | 82 | 83 | #### 遇到的问题 84 | 85 | 记录一下遇到的问题。 86 | 87 | ##### 问题一: Snackbar 报错不显示 88 | 89 | 原本代码: 90 | 91 | ``` 92 | Widget basicListSection = Container( 93 | margin: EdgeInsets.symmetric(vertical: 20.0), 94 | height: 200.0, 95 | child: ListView( 96 | children: [ 97 | ListTile( 98 | leading: Icon(Icons.map), 99 | title: Text('Map'), 100 | onTap: (){ 101 | _showToast(context,"Map"); 102 | }, 103 | ), 104 | ], 105 | ) 106 | ); 107 | ``` 108 | 109 | 原因:原本用的 context 是 Scaffold 的实例化的 widget 的 context, 不是 Scaffold 的。 110 | 111 | 参考:[link](https://stackoverflow.com/questions/51304568/scaffold-of-called-with-a-context-that-does-not-contain-a-scaffold/51304732) 112 | 113 | 所以要改成下面这样:(用 Builder( 114 | builder: (context) => ) 包起来 115 | 116 | ``` 117 | Widget basicListSection = Builder( 118 | builder: (context) => Container( 119 | margin: EdgeInsets.symmetric(vertical: 20.0), 120 | height: 200.0, 121 | child: ListView( 122 | children: [ 123 | ListTile( 124 | leading: Icon(Icons.map), 125 | title: Text('Map'), 126 | onTap: (){ 127 | _showToast(context,"Map"); 128 | }, 129 | ), 130 | ], 131 | ) 132 | ) 133 | ); 134 | ``` 135 | 136 | 137 | #### Flutter 学习之路 Github 地址 138 | 139 | [https://github.com/draftbk/flutter_road](https://github.com/draftbk/flutter_road) 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /notes/Flutter_NavigationBar.md: -------------------------------------------------------------------------------- 1 | ## Flutter 学习之路 - 导航栏(NavigationBar) 2 | > 实验一些常用的 NavigationBar 功能 --- [代码Github地址](https://github.com/draftbk/flutter_road/blob/master/flutter_road_widgets/lib/days/Day7.dart) 3 | 4 | ### NavigationBar 实验 5 | 6 | 7 | - 底部导航栏 [代码地址](https://github.com/draftbk/flutter_road/blob/master/flutter_road_widgets/lib/days/Day7.dart) 8 | - 顶部导航栏 [代码地址](https://github.com/draftbk/flutter_road/blob/master/flutter_road_widgets/lib/subpage/TopBarPage.dart) 9 | 10 | 11 | 12 | 13 | ![](https://github.com/draftbk/Blog_Resource/blob/master/Flutter/gif/flutter_road_navigationbar.gif) 14 | 15 | 16 | #### 底部导航栏(Part1) 17 | 18 | 底部导航用 PageView 和 BottomNavigationBar 完成。大段的代码就不贴了,在 [Github 代码地址](https://github.com/draftbk/flutter_road/blob/master/flutter_road_widgets/lib/days/Day7.dart) 就能找到。 19 | 20 | ##### BottomNavigationBar 21 | 22 | BottomNavigationBar 在 items 里面添加想要的 BottomNavigationBarItem,然后 currentIndex 代表当前 item, page 在 PageView 的 onPageChanged()更改。 23 | 24 | ``` 25 | bottomNavigationBar: new BottomNavigationBar(items: [ 26 | new BottomNavigationBarItem( 27 | icon: new Icon(FontAwesomeIcons.font), 28 | title: new Text("Text"), 29 | backgroundColor: Colors.grey 30 | ), 31 | //更多 BottomNavigationBarItem 32 | ], 33 | onTap: onTap, 34 | currentIndex: page 35 | ), 36 | ``` 37 | 38 | ##### 改变页面切换时候的动画效果 39 | 看 onTap 方法,其中改变 curve 可以改变页面切换时候的动画效果,可以点进 curves,dart 里面看看,有挺多种方法,尝试了一下,还是 Curves.ease 是一种最让人舒服的动画。 然后 duration 可以设置动画时间,可以尝试设置成 1000,你会发现切换页面,嗯,很慢。 40 | 41 | ``` 42 | void onTap(int index) { 43 | pageController.animateToPage( 44 | index, 45 | // 设置页面转换效果的时间 46 | duration: const Duration(milliseconds: 300), 47 | // 设置转换时的效果 48 | curve: Curves.ease); 49 | } 50 | ``` 51 | 52 | ##### PageView 53 | 54 | 然后是 PageView:用把子页面放到 children 里面(这里Page1() 什么的是为了简化篇幅,实际上没这个 class),然后用一个 pageController 来监听页面切换,可以上面的代码里就有 pageController 来控制页面和转换效果。用 onPageChanged 监听页面切换,执行页面切换以后的要执行的操作。 55 | 56 | ``` 57 | body: new PageView( 58 | children: [ 59 | new Page1(), 60 | new Page2(), 61 | new Page3(), 62 | ], 63 | controller: pageController, 64 | onPageChanged: onPageChanged, 65 | ), 66 | ``` 67 | 用 onPageChanged 监听页面切换,切换后设置当前 page 值。 68 | 69 | ``` 70 | void onPageChanged(int page) { 71 | setState(() { 72 | this.page = page; 73 | }); 74 | } 75 | ``` 76 | ##### 设置起始子页面: 77 | 78 | ``` 79 | @override 80 | void initState() { 81 | super.initState(); 82 | // 设置初始化page 83 | pageController = new PageController(initialPage: this.page); 84 | } 85 | ``` 86 | 87 | #### 顶部导航栏(Part2) 88 | 89 | 用 AppBar 实现,用 title 设置顶部 bar 的文字,bottom用 TabBar 设置导航栏的图标,然后界面上在 TabBarView 里面完成不同的 subpage。 90 | 91 | ``` 92 | new AppBar( 93 | title: Text('TopBarPage'), 94 | bottom: new TabBar( 95 | tabs: [ 96 | new Tab( 97 | icon: new Icon(FontAwesomeIcons.google), 98 | ), 99 | new Tab( 100 | icon: new Icon(FontAwesomeIcons.facebook), 101 | ), 102 | ], 103 | controller: _tabController, 104 | ), 105 | ), 106 | body: new TabBarView( 107 | controller: _tabController, 108 | children: [ 109 | new Center(child: new Text('Google',style: TextStyle(fontSize: 20,),)), 110 | new Center(child: new Text('Facebook',style: TextStyle(fontSize: 20,),)), 111 | ], 112 | ), 113 | ``` 114 | 115 | #### 其他 116 | 117 | 刚刚在油管上浏览,看到 Flutter 又出新视频,上面有用 Cupertino Package 实现 iOS 风格的导航栏,有兴趣也可以看一下。 118 | 119 | [https://www.youtube.com/watch?v=3PdUaidHc-E](https://www.youtube.com/watch?v=3PdUaidHc-E) 120 | 121 | ### Flutter 学习之路 Github 地址 122 | 123 | 这是项目的 GitHub 地址,正在持续更新,欢迎 Star 呀!╮( ̄▽ ̄)╭ 124 | 125 | [https://github.com/draftbk/flutter_road](https://github.com/draftbk/flutter_road) 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /notes/Flutter_Network.md: -------------------------------------------------------------------------------- 1 | ## Flutter 学习之路 - 网络入门 2 | > 实验一些 Flutter 的网络方面的功能 ([代码Github地址](https://github.com/draftbk/flutter_road/blob/master/flutter_road_widgets/lib/days/Day11.dart)) 3 | 4 | ### 概述 5 | 6 | 一开始在想标题要叫什么呢,想想网络是个很复杂的东西,这里就实验了最基本的,开发过程中最常用的 Get Post, 就叫网络入门吧哈哈。 7 | 8 | Flutter 现在常用的网络方式有如下三种: 9 | 10 | - HttpClient 11 | - http 12 | - dio 13 | 14 | 这里试验了三种方法的 GET,POST 方法,以及 JSON 的解析。 15 | 16 | 实现通过 ip 获取 ip 所在地信息等方法。 17 | 18 | 19 | [代码地址](https://github.com/draftbk/flutter_road/blob/master/flutter_road_widgets/lib/days/Day11.dart) 20 | 21 | ![](https://github.com/draftbk/Blog_Resource/blob/master/Flutter/gif/flutter_road_network.gif) 22 | 23 | 本次试验 url: 24 | 25 | ```Dart 26 | String getUrl="https://httpbin.org/ip"; 27 | String postUrl="http://ip.taobao.com/service/getIpInfo.php"; 28 | String searchIp='117.89.35.58'; 29 | ``` 30 | 分别是获取 ip(虽然我觉得它获取的ip 很奇怪),以及通过 ip 获取 ip 的所在地以及其他信息。 31 | 32 | 为了方便,第二个url 要用的 ip 设定为一个固定值。 33 | 34 | ### 用 HttpClient 实现 35 | HttpClient 是 Dart 原生的网络请求,flutter 中文网上的 cookbook 是用这个来实现的 36 | 37 | 不需要在 pubspec.yaml 添加依赖 38 | 39 | 引入: 40 | 41 | ```Dart 42 | import 'dart:convert'; 43 | import 'dart:io'; 44 | ``` 45 | 46 | #### GET 请求 47 | 48 | ```Dart 49 | void HttpClient_Get() async { 50 | var httpClient = new HttpClient(); 51 | String result; 52 | try { 53 | var request = await httpClient.getUrl(Uri.parse(getUrl)); 54 | var response = await request.close(); 55 | if (response.statusCode == HttpStatus.OK) { 56 | result = await response.transform(utf8.decoder).join(); 57 | } else { 58 | result = 59 | 'Error getting IP address:\nHttp status ${response.statusCode}'; 60 | } 61 | } catch (exception) { 62 | result = 'Failed getting IP address'; 63 | } 64 | } 65 | ``` 66 | 67 | #### POST 请求 68 | 69 | 网上找没有,然后对应着官网 API 尝试用了下面这个方法还是失败, 不清楚为什么,如果有同学找到方法解决求告知一下! 70 | 71 | ```Dart 72 | Uri uri=new Uri(path:postUrl,queryParameters: {"ip": searchIp} ); 73 | var request = await httpClient.postUrl(uri); 74 | var response = await request.close(); 75 | ``` 76 | 其他两个方法 POST 都可以,umm, 而且功能还更全,所以还是用另外两种方法吧! 77 | 78 | ### 用 http 实现 79 | flutter 官网上的 cookbook 是用这个来实现的 80 | 81 | 不需要在 pubspec.yaml 添加依赖 82 | 83 | 引入: 84 | 85 | ```Dart 86 | import 'package:http/http.dart' as http; 87 | ``` 88 | 89 | #### GET 请求 90 | 91 | ```Dart 92 | void http_Get() async { 93 | String result; 94 | try { 95 | var response = await http.get(getUrl); 96 | if (response.statusCode == HttpStatus.OK) { 97 | result = response.body; 98 | } else { 99 | result = 100 | 'Error getting IP address:\nHttp status ${response.statusCode}'; 101 | } 102 | } catch (exception) { 103 | result = 'Failed getting IP address'; 104 | } 105 | } 106 | ``` 107 | 108 | #### POST 请求 109 | 110 | ```Dart 111 | void http_Post() async { 112 | String result; 113 | try { 114 | 115 | var client = http.Client(); 116 | var response = await client.post(postUrl, body: {"ip": searchIp}); 117 | 118 | if (response.statusCode == HttpStatus.OK) { 119 | result = response.body; 120 | } else { 121 | result = 122 | 'Error getting IP address:\nHttp status ${response.statusCode}'; 123 | } 124 | } catch (exception) { 125 | result = 'Failed getting IP address'; 126 | } 127 | } 128 | ``` 129 | 130 | ### 用 dio 实现 131 | 132 | dio是Flutter中文网开源的一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时等 133 | 134 | 需要在 pubspec.yaml 添加依赖 **dio: any** 135 | 136 | ```Dart 137 | dependencies: 138 | flutter: 139 | sdk: flutter 140 | dio: any 141 | ``` 142 | 143 | 引入: 144 | 145 | ```Dart 146 | import 'package:dio/dio.dart'; 147 | ``` 148 | 149 | 150 | #### GET 请求 151 | 152 | ```Dart 153 | void dio_Get() async { 154 | String result; 155 | try { 156 | Dio dio = new Dio(); 157 | var response = await dio.get(getUrl); 158 | if (response.statusCode == HttpStatus.OK) { 159 | result = response.data.toString(); 160 | } else { 161 | result = 162 | 'Error getting IP address:\nHttp status ${response.statusCode}'; 163 | } 164 | } catch (exception) { 165 | result = 'Failed getting IP address'; 166 | } 167 | } 168 | ``` 169 | 170 | #### POST 请求 171 | 172 | ```Dart 173 | void dio_Post() async { 174 | String result=""; 175 | try { 176 | var dio = new Dio(); 177 | var response = await dio.post(postUrl, queryParameters:{"ip": searchIp}); 178 | if (response.statusCode == HttpStatus.OK) { 179 | result = response.data.toString(); 180 | } else { 181 | result = 182 | 'Error getting IP address:\nHttp status ${response.statusCode}'; 183 | } 184 | } catch (exception) { 185 | result = 'Failed getting IP address'; 186 | } 187 | } 188 | ``` 189 | 190 | #### 其他 191 | 192 | dio 还有好多方法,可以看看这个链接: 193 | [https://pub.dartlang.org/packages/dio](https://pub.dartlang.org/packages/dio) 194 | 195 | ### JSON 解析 196 | 197 | 就直接用下面的方法就可以解析了,真的很方便 198 | 199 | ```Dart 200 | var data = json.decode(result); 201 | result = data['origin']; 202 | ``` 203 | 204 | 205 | ### Flutter 学习之路 Github 地址 206 | 207 | 这是项目的 GitHub 地址,正在持续更新,欢迎 Star 呀!╮( ̄▽ ̄)╭ 208 | 209 | [https://github.com/draftbk/flutter_road](https://github.com/draftbk/flutter_road) 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | -------------------------------------------------------------------------------- /notes/Flutter_Problem_Need_Solve.md: -------------------------------------------------------------------------------- 1 | ## Flutter 想要学习的问题 2 | > 整理一些想要学习或者了解的 Flutter 的东西 3 | 4 | - 在原生 Android 项目里添加 Flutter 代码 5 | - 热更新 6 | - 第三方登录 7 | - 储存 8 | - Flutter 机器学习 9 | - 拍照,视频 10 | - 二维码扫描 11 | - 不同的布局(例如两个控件叠加,一个半透明作为背景,这种要怎么实现) 12 | - 如何看代码结构 -- 例如用 Open DevTools 13 | - Flutter 动画 -------------------------------------------------------------------------------- /notes/Flutter_Problem_Solved.md: -------------------------------------------------------------------------------- 1 | ## Flutter 遇到并解决的问题 2 | > Flutter 遇到并解决的问题 3 | 4 | 5 | #### Dart 代码排版问题 6 | 7 | 1. 在编译器的设置里面可以设置 dart 代码的格式 8 | 2. 在代码界面右键然后选择 **Reformat Code with dartfmt**,排版就 ok了! 9 | -------------------------------------------------------------------------------- /notes/Flutter_Text.md: -------------------------------------------------------------------------------- 1 | ## Flutter 学习之路 - Text 控件 2 | > 实验一些常用的 Text 功能 ([代码Github地址](https://github.com/draftbk/flutter_road/blob/master/flutter_road_widgets/lib/days/Day1.dart)) 3 | 4 | ### Text 实验 5 | 6 | Text 实验了 Text 常用的一些功能 7 | 8 | - 文字大小调整 9 | - 文字颜色设置 10 | - 文字粗体,斜体 11 | - Text 显示的 maxLines 以及 是否换行 12 | - 文字居中 13 | - 文字的装饰(下划线,划去) 14 | - 单词间隙,字母间隙的设置 15 | - 文字点击事件 16 | - 文字拼接 17 | 18 | [代码地址](https://github.com/draftbk/flutter_road/blob/master/flutter_road_widgets/lib/days/Day1.dart) 19 | 20 | ![](https://github.com/draftbk/Blog_Resource/blob/master/Flutter/gif/flutter_road_text.gif) 21 | 22 | 23 | #### Text Style 属性 24 | 25 | 感觉Text的前面的一些地方都是通过改 Text 的属性,可以直接进入我的代码地址看代码看懂的,这边就放一个属性表。 26 | 27 | | 属性 | 意义 | 28 | | ---------- | ----------- | 29 | | fontSize | 文字大小 | 30 | | fontWeight | 文字粗细 | 31 | | color | 文字颜色 | 32 | | fontFamily | 字体 | 33 | | fontStyle | 文字风格(可以设置斜体) | 34 | | wordSpacing | 单词之间的间隙 | 35 | | letterSpacing |字母之间的间隙 | 36 | | locale |区域设置 | 37 | | decoration | 文字装饰(例如下划线,上划线,划去的效果) | 38 | | decorationStyle |文字装饰的风格(例如我上面代码实现的波浪线) | 39 | | decorationColor |文字装饰的颜色 | 40 | 41 | #### 文本点击 42 | 点击事件改变自己参数的时候要用 setState, 不然直接改 _tapText 界面并不会有反应。 43 | 44 | ``` 45 | Padding( 46 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 47 | child: GestureDetector( 48 | onTap: () { 49 | setState(() { 50 | if(_tapText=="啊我被点到了"){ 51 | _tapText="文字点击事件, 点我!"; 52 | }else{ 53 | _tapText="啊我被点到了"; 54 | } 55 | }); 56 | }, 57 | child: Text( 58 | _tapText, 59 | style: TextStyle( 60 | fontSize: 16, 61 | fontWeight: FontWeight.bold, 62 | ), 63 | ), 64 | ), 65 | ), 66 | ``` 67 | 68 | #### 文本拼接 69 | 70 | 拼接效果可以看上面的动图,感觉拼接是一个很有趣的功能,可以在一段文字里实现不同的功能,或者不同的点击,感觉例如一个英文文档,可以点击不同的文字获取不同的中文翻译这样的功能可以这样实现。 71 | 72 | ``` 73 | // 文本拼接 74 | Padding( 75 | padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0), 76 | child: Text.rich( 77 | new TextSpan( 78 | text: '文字拼接: ', 79 | style: new TextStyle( 80 | color: Colors.black, 81 | fontSize: 14, 82 | decoration: TextDecoration.none), 83 | children: [ 84 | new TextSpan( 85 | text: "文字一", 86 | style: new TextStyle( 87 | color: Colors.blue, 88 | fontSize: 20, 89 | decoration: TextDecoration.none)), 90 | new TextSpan( 91 | text: "文字二", 92 | style: new TextStyle( 93 | color: Colors.green, 94 | fontSize: 14, 95 | decoration: TextDecoration.none)), 96 | new TextSpan( 97 | text: "文字三", 98 | style: new TextStyle( 99 | color: Colors.red, 100 | fontSize: 18, 101 | decoration: TextDecoration.none)), 102 | ]), 103 | ), 104 | ) 105 | ``` 106 | 107 | #### Flutter 学习之路 Github 地址 108 | 109 | [https://github.com/draftbk/flutter_road](https://github.com/draftbk/flutter_road) 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | --------------------------------------------------------------------------------