├── .gitignore ├── .metadata ├── README.md ├── ScreenCut ├── 1.jpg └── 2.jpg ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── whu │ │ │ └── flutterbingocode │ │ │ └── MainActivity.java │ │ └── res │ │ ├── drawable │ │ ├── choose_bus_bg.jpg │ │ └── 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 │ │ ├── strings.xml │ │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── key.properties └── settings.gradle ├── assets ├── SpaceDemo.flr ├── choose_bus_bg.jpg ├── choose_buses_bg.jpg ├── ic_launcher.png ├── runLoading.nima ├── runLoading0.png ├── runLoading1.png ├── runLoading2.png ├── runLoading3.png ├── runLoading4.png ├── runLoading5.png └── show_bus_bg.jpg ├── flutter_bingocode.iml ├── flutter_bingocode_android.iml ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Podfile ├── Podfile.lock ├── 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 ├── SplashPage.dart ├── bean │ ├── DirInfo.dart │ └── StationInfo.dart ├── choosebus │ ├── ChooseBusPage.dart │ └── SearchBusPage.dart ├── main.dart ├── manager │ └── BusManager.dart ├── myinfo │ ├── FavoriteIcon.dart │ ├── MyInfoIcon.dart │ └── MyInfoPage.dart ├── resources │ ├── colors.dart │ ├── strings.dart │ ├── styles.dart │ └── themes.dart ├── route │ └── CustomRoute.dart ├── savebus │ └── SaveBusIcon.dart ├── showbus │ ├── ShowBusPage.dart │ └── StationItem.dart └── util │ ├── AnimationUtil.dart │ ├── CommonUtil.dart │ ├── ConstantUtil.dart │ └── FileUtil.dart ├── pubspec.lock ├── pubspec.yaml └── test ├── bingo_test.dart ├── bus_test.dart └── widget_test.dart /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | 4 | .packages 5 | .pub/ 6 | 7 | build/ 8 | 9 | .flutter-plugins 10 | .idea/ -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: c7ea3ca377e909469c68f2ab878a5bc53d3cf66b 8 | channel: beta 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # flutter_bingocode 2 | 3 | flutter项目实践,实现查询北京实时公交信息,保存公交路线 4 | 5 | ## 查询北京实时公交信息 6 | ### 下载地址 7 | ![北京公交OL](https://github.com/bingocode/flutter_bingocode/blob/master/android/app/src/main/res/mipmap-hdpi/ic_launcher.png?raw=true) 8 | 9 | [Android App](https://fir.im/bingobus) 10 | 11 | ### 应用截图 12 | ![1](https://github.com/bingocode/flutter_bingocode/blob/master/ScreenCut/1.jpg?raw=true) 13 | 14 | ![2](https://github.com/bingocode/flutter_bingocode/blob/master/ScreenCut/2.jpg?raw=true) 15 | 16 | ### 技术博客 17 | [北京实时公交查询](https://juejin.im/post/5c4aea47f265da617831c3e0) 18 | 19 | 20 | -------------------------------------------------------------------------------- /ScreenCut/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ScreenCut/1.jpg -------------------------------------------------------------------------------- /ScreenCut/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ScreenCut/2.jpg -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | *.class 3 | .gradle 4 | /local.properties 5 | /.idea/workspace.xml 6 | /.idea/libraries 7 | .DS_Store 8 | /build 9 | /captures 10 | GeneratedPluginRegistrant.java 11 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | apply plugin: 'com.android.application' 15 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 16 | def keystorePropertiesFile = rootProject.file("key.properties") 17 | def keystoreProperties = new Properties() 18 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) 19 | 20 | android { 21 | compileSdkVersion 28 22 | 23 | lintOptions { 24 | disable 'InvalidPackage' 25 | } 26 | 27 | defaultConfig { 28 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 29 | applicationId "com.whu.flutterbingocode" 30 | minSdkVersion 16 31 | targetSdkVersion 28 32 | versionCode 1 33 | versionName "1.0" 34 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 35 | } 36 | 37 | signingConfigs { 38 | release { 39 | keyAlias keystoreProperties['keyAlias'] 40 | keyPassword keystoreProperties['keyPassword'] 41 | storeFile file(keystoreProperties['storeFile']) 42 | storePassword keystoreProperties['storePassword'] 43 | } 44 | } 45 | buildTypes { 46 | release { 47 | // TODO: Add your own signing config for the release build. 48 | // Signing with the debug keys for now, so `flutter run --release` works. 49 | signingConfig signingConfigs.debug 50 | } 51 | } 52 | } 53 | 54 | flutter { 55 | source '../..' 56 | } 57 | 58 | dependencies { 59 | testImplementation 'junit:junit:4.12' 60 | androidTestImplementation 'com.android.support.test:runner:1.0.1' 61 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' 62 | } 63 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 15 | 19 | 26 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/whu/flutterbingocode/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.whu.flutterbingocode; 2 | 3 | import android.os.Bundle; 4 | import io.flutter.app.FlutterActivity; 5 | import io.flutter.plugins.GeneratedPluginRegistrant; 6 | 7 | public class MainActivity extends FlutterActivity { 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | GeneratedPluginRegistrant.registerWith(this); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/choose_bus_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/android/app/src/main/res/drawable/choose_bus_bg.jpg -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 北京公交OL 4 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.5.0' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /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-5.6.2-all.zip 7 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /android/key.properties: -------------------------------------------------------------------------------- 1 | storePassword=zb82619zb 2 | keyPassword=zb82619zb 3 | keyAlias=key 4 | storeFile=/Users/zengbin/key.jks -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /assets/SpaceDemo.flr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/assets/SpaceDemo.flr -------------------------------------------------------------------------------- /assets/choose_bus_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/assets/choose_bus_bg.jpg -------------------------------------------------------------------------------- /assets/choose_buses_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/assets/choose_buses_bg.jpg -------------------------------------------------------------------------------- /assets/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/assets/ic_launcher.png -------------------------------------------------------------------------------- /assets/runLoading.nima: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/assets/runLoading.nima -------------------------------------------------------------------------------- /assets/runLoading0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/assets/runLoading0.png -------------------------------------------------------------------------------- /assets/runLoading1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/assets/runLoading1.png -------------------------------------------------------------------------------- /assets/runLoading2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/assets/runLoading2.png -------------------------------------------------------------------------------- /assets/runLoading3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/assets/runLoading3.png -------------------------------------------------------------------------------- /assets/runLoading4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/assets/runLoading4.png -------------------------------------------------------------------------------- /assets/runLoading5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/assets/runLoading5.png -------------------------------------------------------------------------------- /assets/show_bus_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/assets/show_bus_bg.jpg -------------------------------------------------------------------------------- /flutter_bingocode.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 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 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /flutter_bingocode_android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/app.flx 37 | /Flutter/app.zip 38 | /Flutter/flutter_assets/ 39 | /Flutter/App.framework 40 | /Flutter/Flutter.framework 41 | /Flutter/Generated.xcconfig 42 | /ServiceDefinitions.json 43 | 44 | Pods/ 45 | .symlinks/ 46 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def 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 | -------------------------------------------------------------------------------- /ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Flutter (1.0.0) 3 | - fluttertoast (0.0.2): 4 | - Flutter 5 | - path_provider (0.0.1): 6 | - Flutter 7 | - shared_preferences (0.0.1): 8 | - Flutter 9 | - url_launcher (0.0.1): 10 | - Flutter 11 | 12 | DEPENDENCIES: 13 | - Flutter (from `.symlinks/flutter/ios-release`) 14 | - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) 15 | - path_provider (from `.symlinks/plugins/path_provider/ios`) 16 | - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`) 17 | - url_launcher (from `.symlinks/plugins/url_launcher/ios`) 18 | 19 | EXTERNAL SOURCES: 20 | Flutter: 21 | :path: ".symlinks/flutter/ios-release" 22 | fluttertoast: 23 | :path: ".symlinks/plugins/fluttertoast/ios" 24 | path_provider: 25 | :path: ".symlinks/plugins/path_provider/ios" 26 | shared_preferences: 27 | :path: ".symlinks/plugins/shared_preferences/ios" 28 | url_launcher: 29 | :path: ".symlinks/plugins/url_launcher/ios" 30 | 31 | SPEC CHECKSUMS: 32 | Flutter: 9d0fac939486c9aba2809b7982dfdbb47a7b0296 33 | fluttertoast: 0a20dcbbb8ecfd1a61b6285651ff2d5989d033fb 34 | path_provider: 09407919825bfe3c2deae39453b7a5b44f467873 35 | shared_preferences: 5a1d487c427ee18fcd3ea1f2a131569481834b53 36 | url_launcher: 92b89c1029a0373879933c21642958c874539095 37 | 38 | PODFILE CHECKSUM: aff02bfeed411c636180d6812254b2daeea14d09 39 | 40 | COCOAPODS: 1.5.3 41 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; }; 12 | 2EC53491C02DA3CAE0865C75 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 17DE5EF7E4CDB9A207BE594B /* libPods-Runner.a */; }; 13 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 14 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 15 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 16 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; 17 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 18 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 19 | 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 20 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 21 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 22 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXCopyFilesBuildPhase section */ 26 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 27 | isa = PBXCopyFilesBuildPhase; 28 | buildActionMask = 2147483647; 29 | dstPath = ""; 30 | dstSubfolderSpec = 10; 31 | files = ( 32 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, 33 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, 34 | ); 35 | name = "Embed Frameworks"; 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXCopyFilesBuildPhase section */ 39 | 40 | /* Begin PBXFileReference section */ 41 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 42 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 43 | 17DE5EF7E4CDB9A207BE594B /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; }; 45 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 46 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 47 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 48 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 49 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 50 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 51 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 52 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 53 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 55 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 56 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 57 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 58 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 59 | /* End PBXFileReference section */ 60 | 61 | /* Begin PBXFrameworksBuildPhase section */ 62 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 67 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, 68 | 2EC53491C02DA3CAE0865C75 /* libPods-Runner.a in Frameworks */, 69 | ); 70 | runOnlyForDeploymentPostprocessing = 0; 71 | }; 72 | /* End PBXFrameworksBuildPhase section */ 73 | 74 | /* Begin PBXGroup section */ 75 | 7035C293E5926025FE0A3E0F /* Pods */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | ); 79 | name = Pods; 80 | sourceTree = ""; 81 | }; 82 | 9740EEB11CF90186004384FC /* Flutter */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | 2D5378251FAA1A9400D5DBA9 /* flutter_assets */, 86 | 3B80C3931E831B6300D905FE /* App.framework */, 87 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 88 | 9740EEBA1CF902C7004384FC /* Flutter.framework */, 89 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 90 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 91 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 92 | ); 93 | name = Flutter; 94 | sourceTree = ""; 95 | }; 96 | 97C146E51CF9000F007C117D = { 97 | isa = PBXGroup; 98 | children = ( 99 | 9740EEB11CF90186004384FC /* Flutter */, 100 | 97C146F01CF9000F007C117D /* Runner */, 101 | 97C146EF1CF9000F007C117D /* Products */, 102 | 7035C293E5926025FE0A3E0F /* Pods */, 103 | FE3B6590EB7F0E380A12A4BC /* Frameworks */, 104 | ); 105 | sourceTree = ""; 106 | }; 107 | 97C146EF1CF9000F007C117D /* Products */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 97C146EE1CF9000F007C117D /* Runner.app */, 111 | ); 112 | name = Products; 113 | sourceTree = ""; 114 | }; 115 | 97C146F01CF9000F007C117D /* Runner */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, 119 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 120 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 121 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 122 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 123 | 97C147021CF9000F007C117D /* Info.plist */, 124 | 97C146F11CF9000F007C117D /* Supporting Files */, 125 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 126 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 127 | ); 128 | path = Runner; 129 | sourceTree = ""; 130 | }; 131 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 97C146F21CF9000F007C117D /* main.m */, 135 | ); 136 | name = "Supporting Files"; 137 | sourceTree = ""; 138 | }; 139 | FE3B6590EB7F0E380A12A4BC /* Frameworks */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | 17DE5EF7E4CDB9A207BE594B /* libPods-Runner.a */, 143 | ); 144 | name = Frameworks; 145 | sourceTree = ""; 146 | }; 147 | /* End PBXGroup section */ 148 | 149 | /* Begin PBXNativeTarget section */ 150 | 97C146ED1CF9000F007C117D /* Runner */ = { 151 | isa = PBXNativeTarget; 152 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 153 | buildPhases = ( 154 | 98C791C0073DECFFA0B3854C /* [CP] Check Pods Manifest.lock */, 155 | 9740EEB61CF901F6004384FC /* Run Script */, 156 | 97C146EA1CF9000F007C117D /* Sources */, 157 | 97C146EB1CF9000F007C117D /* Frameworks */, 158 | 97C146EC1CF9000F007C117D /* Resources */, 159 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 160 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 161 | 4B6EE528A38496CBED59D151 /* [CP] Embed Pods Frameworks */, 162 | ); 163 | buildRules = ( 164 | ); 165 | dependencies = ( 166 | ); 167 | name = Runner; 168 | productName = Runner; 169 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 170 | productType = "com.apple.product-type.application"; 171 | }; 172 | /* End PBXNativeTarget section */ 173 | 174 | /* Begin PBXProject section */ 175 | 97C146E61CF9000F007C117D /* Project object */ = { 176 | isa = PBXProject; 177 | attributes = { 178 | LastUpgradeCheck = 1010; 179 | ORGANIZATIONNAME = "The Chromium Authors"; 180 | TargetAttributes = { 181 | 97C146ED1CF9000F007C117D = { 182 | CreatedOnToolsVersion = 7.3.1; 183 | ProvisioningStyle = Automatic; 184 | }; 185 | }; 186 | }; 187 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 188 | compatibilityVersion = "Xcode 3.2"; 189 | developmentRegion = English; 190 | hasScannedForEncodings = 0; 191 | knownRegions = ( 192 | en, 193 | Base, 194 | ); 195 | mainGroup = 97C146E51CF9000F007C117D; 196 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 197 | projectDirPath = ""; 198 | projectRoot = ""; 199 | targets = ( 200 | 97C146ED1CF9000F007C117D /* Runner */, 201 | ); 202 | }; 203 | /* End PBXProject section */ 204 | 205 | /* Begin PBXResourcesBuildPhase section */ 206 | 97C146EC1CF9000F007C117D /* Resources */ = { 207 | isa = PBXResourcesBuildPhase; 208 | buildActionMask = 2147483647; 209 | files = ( 210 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 211 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 212 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 213 | 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */, 214 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 215 | ); 216 | runOnlyForDeploymentPostprocessing = 0; 217 | }; 218 | /* End PBXResourcesBuildPhase section */ 219 | 220 | /* Begin PBXShellScriptBuildPhase section */ 221 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 222 | isa = PBXShellScriptBuildPhase; 223 | buildActionMask = 2147483647; 224 | files = ( 225 | ); 226 | inputPaths = ( 227 | ); 228 | name = "Thin Binary"; 229 | outputPaths = ( 230 | ); 231 | runOnlyForDeploymentPostprocessing = 0; 232 | shellPath = /bin/sh; 233 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; 234 | }; 235 | 4B6EE528A38496CBED59D151 /* [CP] Embed Pods Frameworks */ = { 236 | isa = PBXShellScriptBuildPhase; 237 | buildActionMask = 2147483647; 238 | files = ( 239 | ); 240 | inputPaths = ( 241 | "${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", 242 | "${PODS_ROOT}/../.symlinks/flutter/ios-release/Flutter.framework", 243 | ); 244 | name = "[CP] Embed Pods Frameworks"; 245 | outputPaths = ( 246 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", 247 | ); 248 | runOnlyForDeploymentPostprocessing = 0; 249 | shellPath = /bin/sh; 250 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; 251 | showEnvVarsInLog = 0; 252 | }; 253 | 9740EEB61CF901F6004384FC /* Run Script */ = { 254 | isa = PBXShellScriptBuildPhase; 255 | buildActionMask = 2147483647; 256 | files = ( 257 | ); 258 | inputPaths = ( 259 | ); 260 | name = "Run Script"; 261 | outputPaths = ( 262 | ); 263 | runOnlyForDeploymentPostprocessing = 0; 264 | shellPath = /bin/sh; 265 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 266 | }; 267 | 98C791C0073DECFFA0B3854C /* [CP] Check Pods Manifest.lock */ = { 268 | isa = PBXShellScriptBuildPhase; 269 | buildActionMask = 2147483647; 270 | files = ( 271 | ); 272 | inputPaths = ( 273 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 274 | "${PODS_ROOT}/Manifest.lock", 275 | ); 276 | name = "[CP] Check Pods Manifest.lock"; 277 | outputPaths = ( 278 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", 279 | ); 280 | runOnlyForDeploymentPostprocessing = 0; 281 | shellPath = /bin/sh; 282 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 283 | showEnvVarsInLog = 0; 284 | }; 285 | /* End PBXShellScriptBuildPhase section */ 286 | 287 | /* Begin PBXSourcesBuildPhase section */ 288 | 97C146EA1CF9000F007C117D /* Sources */ = { 289 | isa = PBXSourcesBuildPhase; 290 | buildActionMask = 2147483647; 291 | files = ( 292 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, 293 | 97C146F31CF9000F007C117D /* main.m in Sources */, 294 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 295 | ); 296 | runOnlyForDeploymentPostprocessing = 0; 297 | }; 298 | /* End PBXSourcesBuildPhase section */ 299 | 300 | /* Begin PBXVariantGroup section */ 301 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 302 | isa = PBXVariantGroup; 303 | children = ( 304 | 97C146FB1CF9000F007C117D /* Base */, 305 | ); 306 | name = Main.storyboard; 307 | sourceTree = ""; 308 | }; 309 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 310 | isa = PBXVariantGroup; 311 | children = ( 312 | 97C147001CF9000F007C117D /* Base */, 313 | ); 314 | name = LaunchScreen.storyboard; 315 | sourceTree = ""; 316 | }; 317 | /* End PBXVariantGroup section */ 318 | 319 | /* Begin XCBuildConfiguration section */ 320 | 97C147031CF9000F007C117D /* Debug */ = { 321 | isa = XCBuildConfiguration; 322 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 323 | buildSettings = { 324 | ALWAYS_SEARCH_USER_PATHS = NO; 325 | CLANG_ANALYZER_NONNULL = YES; 326 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 327 | CLANG_CXX_LIBRARY = "libc++"; 328 | CLANG_ENABLE_MODULES = YES; 329 | CLANG_ENABLE_OBJC_ARC = YES; 330 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 331 | CLANG_WARN_BOOL_CONVERSION = YES; 332 | CLANG_WARN_COMMA = YES; 333 | CLANG_WARN_CONSTANT_CONVERSION = YES; 334 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 335 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 336 | CLANG_WARN_EMPTY_BODY = YES; 337 | CLANG_WARN_ENUM_CONVERSION = YES; 338 | CLANG_WARN_INFINITE_RECURSION = YES; 339 | CLANG_WARN_INT_CONVERSION = YES; 340 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 341 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 342 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 343 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 344 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 345 | CLANG_WARN_STRICT_PROTOTYPES = YES; 346 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 347 | CLANG_WARN_UNREACHABLE_CODE = YES; 348 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 349 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 350 | COPY_PHASE_STRIP = NO; 351 | DEBUG_INFORMATION_FORMAT = dwarf; 352 | ENABLE_STRICT_OBJC_MSGSEND = YES; 353 | ENABLE_TESTABILITY = YES; 354 | GCC_C_LANGUAGE_STANDARD = gnu99; 355 | GCC_DYNAMIC_NO_PIC = NO; 356 | GCC_NO_COMMON_BLOCKS = YES; 357 | GCC_OPTIMIZATION_LEVEL = 0; 358 | GCC_PREPROCESSOR_DEFINITIONS = ( 359 | "DEBUG=1", 360 | "$(inherited)", 361 | ); 362 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 363 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 364 | GCC_WARN_UNDECLARED_SELECTOR = YES; 365 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 366 | GCC_WARN_UNUSED_FUNCTION = YES; 367 | GCC_WARN_UNUSED_VARIABLE = YES; 368 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 369 | MTL_ENABLE_DEBUG_INFO = YES; 370 | ONLY_ACTIVE_ARCH = YES; 371 | SDKROOT = iphoneos; 372 | TARGETED_DEVICE_FAMILY = "1,2"; 373 | }; 374 | name = Debug; 375 | }; 376 | 97C147041CF9000F007C117D /* Release */ = { 377 | isa = XCBuildConfiguration; 378 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 379 | buildSettings = { 380 | ALWAYS_SEARCH_USER_PATHS = NO; 381 | CLANG_ANALYZER_NONNULL = YES; 382 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 383 | CLANG_CXX_LIBRARY = "libc++"; 384 | CLANG_ENABLE_MODULES = YES; 385 | CLANG_ENABLE_OBJC_ARC = YES; 386 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 387 | CLANG_WARN_BOOL_CONVERSION = YES; 388 | CLANG_WARN_COMMA = YES; 389 | CLANG_WARN_CONSTANT_CONVERSION = YES; 390 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 391 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 392 | CLANG_WARN_EMPTY_BODY = YES; 393 | CLANG_WARN_ENUM_CONVERSION = YES; 394 | CLANG_WARN_INFINITE_RECURSION = YES; 395 | CLANG_WARN_INT_CONVERSION = YES; 396 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 397 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 398 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 399 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 400 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 401 | CLANG_WARN_STRICT_PROTOTYPES = YES; 402 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 403 | CLANG_WARN_UNREACHABLE_CODE = YES; 404 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 405 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 406 | COPY_PHASE_STRIP = NO; 407 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 408 | ENABLE_NS_ASSERTIONS = NO; 409 | ENABLE_STRICT_OBJC_MSGSEND = YES; 410 | GCC_C_LANGUAGE_STANDARD = gnu99; 411 | GCC_NO_COMMON_BLOCKS = YES; 412 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 413 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 414 | GCC_WARN_UNDECLARED_SELECTOR = YES; 415 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 416 | GCC_WARN_UNUSED_FUNCTION = YES; 417 | GCC_WARN_UNUSED_VARIABLE = YES; 418 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 419 | MTL_ENABLE_DEBUG_INFO = NO; 420 | SDKROOT = iphoneos; 421 | TARGETED_DEVICE_FAMILY = "1,2"; 422 | VALIDATE_PRODUCT = YES; 423 | }; 424 | name = Release; 425 | }; 426 | 97C147061CF9000F007C117D /* Debug */ = { 427 | isa = XCBuildConfiguration; 428 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 429 | buildSettings = { 430 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 431 | CODE_SIGN_IDENTITY = "iPhone Developer"; 432 | CODE_SIGN_STYLE = Automatic; 433 | CURRENT_PROJECT_VERSION = 1; 434 | DEVELOPMENT_TEAM = ""; 435 | ENABLE_BITCODE = NO; 436 | FRAMEWORK_SEARCH_PATHS = ( 437 | "$(inherited)", 438 | "$(PROJECT_DIR)/Flutter", 439 | ); 440 | INFOPLIST_FILE = Runner/Info.plist; 441 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 442 | LIBRARY_SEARCH_PATHS = ( 443 | "$(inherited)", 444 | "$(PROJECT_DIR)/Flutter", 445 | ); 446 | PRODUCT_BUNDLE_IDENTIFIER = com.whu.flutterBingocode; 447 | PRODUCT_NAME = "$(TARGET_NAME)"; 448 | PROVISIONING_PROFILE_SPECIFIER = ""; 449 | VERSIONING_SYSTEM = "apple-generic"; 450 | }; 451 | name = Debug; 452 | }; 453 | 97C147071CF9000F007C117D /* Release */ = { 454 | isa = XCBuildConfiguration; 455 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 456 | buildSettings = { 457 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 458 | CODE_SIGN_IDENTITY = "iPhone Developer"; 459 | CODE_SIGN_STYLE = Automatic; 460 | CURRENT_PROJECT_VERSION = 1; 461 | DEVELOPMENT_TEAM = ""; 462 | ENABLE_BITCODE = NO; 463 | FRAMEWORK_SEARCH_PATHS = ( 464 | "$(inherited)", 465 | "$(PROJECT_DIR)/Flutter", 466 | ); 467 | INFOPLIST_FILE = Runner/Info.plist; 468 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 469 | LIBRARY_SEARCH_PATHS = ( 470 | "$(inherited)", 471 | "$(PROJECT_DIR)/Flutter", 472 | ); 473 | PRODUCT_BUNDLE_IDENTIFIER = com.whu.flutterBingocode; 474 | PRODUCT_NAME = "$(TARGET_NAME)"; 475 | PROVISIONING_PROFILE_SPECIFIER = ""; 476 | VERSIONING_SYSTEM = "apple-generic"; 477 | }; 478 | name = Release; 479 | }; 480 | /* End XCBuildConfiguration section */ 481 | 482 | /* Begin XCConfigurationList section */ 483 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 484 | isa = XCConfigurationList; 485 | buildConfigurations = ( 486 | 97C147031CF9000F007C117D /* Debug */, 487 | 97C147041CF9000F007C117D /* Release */, 488 | ); 489 | defaultConfigurationIsVisible = 0; 490 | defaultConfigurationName = Release; 491 | }; 492 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 493 | isa = XCConfigurationList; 494 | buildConfigurations = ( 495 | 97C147061CF9000F007C117D /* Debug */, 496 | 97C147071CF9000F007C117D /* Release */, 497 | ); 498 | defaultConfigurationIsVisible = 0; 499 | defaultConfigurationName = Release; 500 | }; 501 | /* End XCConfigurationList section */ 502 | }; 503 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 504 | } 505 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildSystemType 6 | Original 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #include "AppDelegate.h" 2 | #include "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingocode/flutter_bingocode/aa447e54f55abc4b17941e3190cad34aadc64c31/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | 北京公交OL 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lib/SplashPage.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bingocode/choosebus/ChooseBusPage.dart'; 3 | import 'package:flutter_bingocode/route/CustomRoute.dart'; 4 | import 'package:flutter_bingocode/util/AnimationUtil.dart'; 5 | 6 | class SplashPage extends StatefulWidget { 7 | @override 8 | State createState() { 9 | // TODO: implement createState 10 | return SplashPageState(); 11 | } 12 | } 13 | 14 | class SplashPageState extends State 15 | with SingleTickerProviderStateMixin { 16 | AnimationController animationController; 17 | Animation animation; 18 | 19 | @override 20 | void initState() { 21 | super.initState(); 22 | animationController = 23 | AnimationController(vsync: this, duration: Duration(seconds: 2)); 24 | animation = Tween(begin: 0.0, end: 100.0).animate(animationController); 25 | animationController.forward(); //启动动画 26 | animation.addStatusListener((status) { 27 | if (status == AnimationStatus.completed || 28 | status == AnimationStatus.dismissed) { 29 | Navigator.pushReplacement( 30 | context, SlideRoute(ChooseBusPage(), SlideRoute.DOWN)); 31 | } 32 | }); 33 | } 34 | 35 | @override 36 | Widget build(BuildContext context) { 37 | // TODO: implement build 38 | return Container( 39 | child: Center( 40 | child: TransitionAnimation( 41 | child: Image.asset(('assets/ic_launcher.png')), 42 | animation: animation), 43 | ), 44 | ); 45 | } 46 | 47 | @override 48 | void dispose() { 49 | animationController.dispose(); 50 | super.dispose(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/bean/DirInfo.dart: -------------------------------------------------------------------------------- 1 | class DirInfo { 2 | String direction; 3 | String directionId; 4 | 5 | DirInfo(this.direction, this.directionId); 6 | 7 | } -------------------------------------------------------------------------------- /lib/bean/StationInfo.dart: -------------------------------------------------------------------------------- 1 | class StationInfo { 2 | String name; 3 | String index; 4 | // 当前站有公交 5 | var hasBus = false; 6 | // 有公交正在驶往该站 7 | var hasNextBus = false; 8 | 9 | var isSelfStop = false; 10 | StationInfo(this.name, this.index); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /lib/choosebus/ChooseBusPage.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_bingocode/bean/DirInfo.dart'; 5 | import 'package:flutter_bingocode/bean/StationInfo.dart'; 6 | import 'package:flutter_bingocode/choosebus/SearchBusPage.dart'; 7 | import 'package:flutter_bingocode/manager/BusManager.dart'; 8 | import 'package:flutter_bingocode/myinfo/MyInfoIcon.dart'; 9 | import 'package:flutter_bingocode/resources/strings.dart'; 10 | import 'package:flutter_bingocode/resources/styles.dart'; 11 | import 'package:flutter_bingocode/route/CustomRoute.dart'; 12 | import 'package:flutter_bingocode/savebus/SaveBusIcon.dart'; 13 | import 'package:flutter_bingocode/showbus/ShowBusPage.dart'; 14 | import 'package:flutter_bingocode/util/CommonUtil.dart'; 15 | import 'package:flutter_bingocode/util/ConstantUtil.dart'; 16 | import 'package:nima/nima_actor.dart'; 17 | 18 | class ChooseBusPage extends StatefulWidget { 19 | @override 20 | State createState() { 21 | return ChooseBusState(); 22 | } 23 | } 24 | 25 | class ChooseBusState extends State { 26 | static const STEP_COUNT = 3; 27 | static const STEP_CHOOSE_BUS = 0; 28 | static const STEP_CHOOSE_DIR = 1; 29 | static const STEP_CHOOSE_STATION = 2; 30 | final Utf8Decoder decoder = new Utf8Decoder(); 31 | BusManager _busManager; 32 | UpdateCallBack> updateBusesCallBack; 33 | UpdateCallBack> updateDirCallBack; 34 | UpdateCallBack> updateStationsCallBack; 35 | UpdateCallBack> queryStationsCallBack; 36 | int currentStep = STEP_CHOOSE_BUS; 37 | bool hasDirSaved = true; 38 | bool hasStationSaved = true; 39 | 40 | @override 41 | void initState() { 42 | super.initState(); 43 | _busManager = BusManager(); 44 | updateBusesCallBack = (List buses) { 45 | showSearch(context: context, delegate: searchBarDelegate(buses)) 46 | .then((String bus) { 47 | setState(() { 48 | if (bus != null && bus != _busManager.busLine) { 49 | _busManager.busLine = bus; 50 | } 51 | }); 52 | }); 53 | }; 54 | updateDirCallBack = (List dirinfos) { 55 | setState(() { 56 | currentStep = STEP_CHOOSE_DIR; 57 | if (hasDirSaved) { 58 | for (DirInfo info in dirinfos) { 59 | if (info.directionId == _busManager.busDirId) { 60 | _busManager.busDir = info; 61 | if (hasStationSaved) { 62 | _busManager.getStationList().then(updateStationsCallBack); 63 | } 64 | } 65 | } 66 | } 67 | hasDirSaved = false; 68 | }); 69 | }; 70 | updateStationsCallBack = (List staionInfos) { 71 | setState(() { 72 | currentStep = STEP_CHOOSE_STATION; 73 | if (hasStationSaved) { 74 | for (StationInfo info in staionInfos) { 75 | if (info.index == _busManager.busSelfStopId) { 76 | _busManager.busSelfStop = info; 77 | } 78 | } 79 | } 80 | hasStationSaved = false; 81 | }); 82 | }; 83 | 84 | queryStationsCallBack = (List dirinfos) { 85 | print("query onLine busInfo"); 86 | Navigator.push(context, FadeRoute(ShowBusPage())); 87 | }; 88 | _busManager.getSavedBusLine().then((Map savedMap) { 89 | setState(() { 90 | _busManager.busLine = savedMap[KeyConstant.keyBusLine]; 91 | _busManager.busDirId = savedMap[KeyConstant.keyBusDir]; 92 | _busManager.busSelfStopId = savedMap[KeyConstant.keyBusStation]; 93 | hasDirSaved = _busManager.busDirId != null; 94 | hasStationSaved = _busManager.busSelfStopId != null; 95 | if (hasDirSaved) { 96 | _busManager.getDirList().then(updateDirCallBack); 97 | } 98 | }); 99 | }); 100 | } 101 | 102 | @override 103 | Widget build(BuildContext context) { 104 | return MaterialApp( 105 | title: 'Flutter Demo', 106 | debugShowCheckedModeBanner: false, 107 | theme: ThemeData( 108 | backgroundColor: Colors.transparent, 109 | primarySwatch: Colors.blue, 110 | ), 111 | home: Scaffold( 112 | body: Stack( 113 | children: [ 114 | buildContainer(context), 115 | Container( 116 | alignment: Alignment.bottomLeft, 117 | margin: EdgeInsets.fromLTRB(16, 0, 0, 16), 118 | child: MyInfoIcon(), 119 | ) 120 | ], 121 | ), 122 | floatingActionButton: SaveBusIcon(), 123 | )); 124 | } 125 | 126 | Container buildContainer(BuildContext context) { 127 | return Container( 128 | decoration: BoxDecoration( 129 | image: DecorationImage( 130 | image: AssetImage('assets/choose_buses_bg.jpg'), 131 | fit: BoxFit.fitHeight)), 132 | child: Center( 133 | child: Column( 134 | mainAxisAlignment: MainAxisAlignment.center, 135 | children: [ 136 | Container( 137 | width: 100, 138 | height: 100, 139 | child: currentStep >= STEP_CHOOSE_DIR 140 | ? NimaActor('assets/runLoading.nima', 141 | fit: BoxFit.scaleDown, animation: 'Run') 142 | : NimaActor('assets/runLoading.nima', fit: BoxFit.scaleDown), 143 | ), 144 | (hasDirSaved || hasStationSaved) 145 | ? Container() 146 | : Stepper( 147 | currentStep: this.currentStep, 148 | steps: [ 149 | new Step( 150 | // Title of the Step 151 | title: new Text( 152 | _busManager.busLine == null 153 | ? StringRes.chooseBus 154 | : StringRes.chooseBus + 155 | ': ${_busManager.busLine}', 156 | softWrap: false, 157 | overflow: TextOverflow.ellipsis, 158 | style: StyleRes.chooseBusButtonTextStyle), 159 | content: _getChooseBusItem(), 160 | isActive: currentStep >= STEP_CHOOSE_BUS), 161 | new Step( 162 | title: new Text( 163 | _busManager.busDir == null 164 | ? StringRes.chooseDir 165 | : StringRes.chooseDir + 166 | ': ${_busManager.busDir.direction}', 167 | softWrap: false, 168 | overflow: TextOverflow.ellipsis, 169 | style: StyleRes.chooseBusButtonTextStyle), 170 | content: _getChooseDirItem(), 171 | // You can change the style of the step icon i.e number, editing, etc. 172 | isActive: currentStep >= STEP_CHOOSE_DIR), 173 | new Step( 174 | title: new Text( 175 | _busManager.busSelfStop == null 176 | ? StringRes.chooseStation 177 | : StringRes.chooseStation + 178 | ': ${_busManager.busSelfStop.name}', 179 | softWrap: false, 180 | overflow: TextOverflow.ellipsis, 181 | style: StyleRes.chooseBusButtonTextStyle), 182 | content: _getChooseStationItem(), 183 | isActive: currentStep >= STEP_CHOOSE_STATION), 184 | ], 185 | controlsBuilder: (BuildContext context, 186 | {VoidCallback onStepContinue, 187 | VoidCallback onStepCancel}) { 188 | return Row( 189 | children: [ 190 | FlatButton( 191 | onPressed: onStepContinue, 192 | child: Text( 193 | currentStep < STEP_CHOOSE_STATION 194 | ? StringRes.next_step 195 | : StringRes.queryBus, 196 | style: StyleRes.saveBusButtonTextStyle), 197 | ), 198 | FlatButton( 199 | onPressed: onStepCancel, 200 | child: Text(StringRes.concel, 201 | style: StyleRes.chooseBusButtonTextStyle), 202 | ), 203 | ], 204 | ); 205 | }, 206 | type: StepperType.vertical, 207 | onStepCancel: () { 208 | setState(() { 209 | switch (currentStep) { 210 | case STEP_CHOOSE_BUS: 211 | _busManager.busLine = null; 212 | currentStep = 0; 213 | break; 214 | case STEP_CHOOSE_DIR: 215 | _busManager.dirInfoList.clear(); 216 | _busManager.busDir = null; 217 | currentStep = currentStep - 1; 218 | break; 219 | case STEP_CHOOSE_STATION: 220 | _busManager.stationInfoList.clear(); 221 | _busManager.busSelfStop = null; 222 | currentStep = currentStep - 1; 223 | break; 224 | } 225 | }); 226 | print("onStepCancel : " + currentStep.toString()); 227 | }, 228 | onStepContinue: () { 229 | String msg; 230 | if (_busManager.busLine == null) { 231 | msg = StringRes.choose_bus_hint; 232 | } else if (_busManager.busDir == null) { 233 | msg = StringRes.choose_dir_hint; 234 | } else if (_busManager.busSelfStop == null) { 235 | msg = StringRes.choose_selfStop_hint; 236 | } 237 | switch (currentStep) { 238 | case STEP_CHOOSE_BUS: 239 | if (_busManager.busLine != null) { 240 | //todo 加载进度 241 | setState(() { 242 | _busManager.getDirList().then(updateDirCallBack); 243 | }); 244 | } else { 245 | CommonUtil.toast(msg); 246 | } 247 | break; 248 | case STEP_CHOOSE_DIR: 249 | if (_busManager.busDir != null) { 250 | //todo 加载进度 251 | setState(() { 252 | _busManager 253 | .getStationList() 254 | .then(updateStationsCallBack); 255 | }); 256 | } else { 257 | CommonUtil.toast(msg); 258 | } 259 | break; 260 | case STEP_CHOOSE_STATION: 261 | if (msg == null) { 262 | //todo 加载进度 263 | setState(() { 264 | _busManager 265 | .getOnlineBusInfo(context) 266 | .then(queryStationsCallBack); 267 | }); 268 | } else { 269 | CommonUtil.toast(msg); 270 | } 271 | break; 272 | } 273 | print("onStepContinue : " + currentStep.toString()); 274 | }, 275 | ), 276 | ], 277 | ))); 278 | } 279 | 280 | Widget _getChooseBusItem() { 281 | return MaterialButton( 282 | color: Colors.blueAccent, 283 | child: _busManager.busLine == null 284 | ? Text(StringRes.chooseBus, style: StyleRes.chooseBusButtonTextStyle) 285 | : Text(_busManager.busLine, style: StyleRes.chooseBusButtonTextStyle), 286 | onPressed: () { 287 | setState(() { 288 | _busManager.getBusList().then(updateBusesCallBack); 289 | }); 290 | }, 291 | ); 292 | } 293 | 294 | Widget _getChooseDirItem() { 295 | return MaterialButton( 296 | color: Colors.blueAccent, 297 | child: _busManager.busDir == null 298 | ? Text(StringRes.chooseDir, 299 | style: StyleRes.chooseBusButtonTextStyle) 300 | : Text(_busManager.busDir.direction, 301 | style: StyleRes.chooseBusButtonTextStyle), 302 | onPressed: () { 303 | showDialog( 304 | context: context, 305 | builder: (BuildContext context) { 306 | return SimpleDialog( 307 | title: Text(StringRes.chooseDir), 308 | children: _getBusDirWidgets(context), 309 | ); 310 | }); 311 | }); 312 | } 313 | 314 | Widget _getChooseStationItem() { 315 | return MaterialButton( 316 | color: Colors.blueAccent, 317 | child: _busManager.busSelfStop == null 318 | ? Text(StringRes.chooseStation, 319 | style: StyleRes.chooseBusButtonTextStyle) 320 | : Text(_busManager.busSelfStop.name, 321 | style: StyleRes.chooseBusButtonTextStyle), 322 | onPressed: () { 323 | showDialog( 324 | context: context, 325 | builder: (BuildContext context) { 326 | return SimpleDialog( 327 | title: Text(StringRes.chooseStation), 328 | children: _getBusStationWidgets(context), 329 | ); 330 | }); 331 | }); 332 | } 333 | 334 | List _getBusDirWidgets(BuildContext context) { 335 | var busLineWeights = []; 336 | for (DirInfo dir in _busManager.dirInfoList) { 337 | busLineWeights.add(SimpleDialogOption( 338 | child: Text(dir.direction), 339 | onPressed: () { 340 | Navigator.of(context).pop(); 341 | print('chooseDir${dir.direction}'); 342 | setState(() { 343 | _busManager.busDir = dir; 344 | }); 345 | }, 346 | )); 347 | } 348 | return busLineWeights; 349 | } 350 | 351 | List _getBusStationWidgets(BuildContext context) { 352 | var busLineWeights = []; 353 | for (StationInfo station in _busManager.stationInfoList) { 354 | busLineWeights.add(SimpleDialogOption( 355 | child: Text(station.name), 356 | onPressed: () { 357 | Navigator.of(context).pop(); 358 | print('chooseStation${station.name}'); 359 | setState(() { 360 | _busManager.busSelfStop = station; 361 | }); 362 | }, 363 | )); 364 | } 365 | return busLineWeights; 366 | } 367 | } 368 | -------------------------------------------------------------------------------- /lib/choosebus/SearchBusPage.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class searchBarDelegate extends SearchDelegate { 4 | List searchList; 5 | 6 | searchBarDelegate(this.searchList); 7 | 8 | @override 9 | List buildActions(BuildContext context) { 10 | return [ 11 | IconButton( 12 | icon: Icon(Icons.clear), 13 | onPressed: () => query = "", 14 | ) 15 | ]; 16 | } 17 | 18 | @override 19 | Widget buildLeading(BuildContext context) { 20 | return IconButton( 21 | icon: AnimatedIcon( 22 | icon: AnimatedIcons.menu_arrow, progress: transitionAnimation), 23 | onPressed: () => close(context, null)); 24 | } 25 | 26 | @override 27 | Widget buildResults(BuildContext context) { 28 | return _buildSearchItems(); 29 | } 30 | 31 | @override 32 | Widget buildSuggestions(BuildContext context) { 33 | return _buildSearchItems(); 34 | } 35 | 36 | Widget _buildSearchItems() { 37 | final suggestionList = query.isEmpty 38 | ? [] 39 | : searchList.where((input) => input.startsWith(query)).toList(); 40 | return ListView.builder( 41 | itemCount: suggestionList.length, 42 | itemBuilder: (context, index) => ListTile( 43 | title: InkWell( 44 | onTap: () { 45 | close(context, suggestionList[index]); 46 | }, 47 | child: RichText( 48 | text: TextSpan( 49 | text: suggestionList[index].substring(0, query.length), 50 | style: TextStyle( 51 | color: Colors.black, fontWeight: FontWeight.bold), 52 | children: [ 53 | TextSpan( 54 | text: suggestionList[index].substring(query.length), 55 | style: TextStyle(color: Colors.grey)) 56 | ]))))); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:flutter_bingocode/SplashPage.dart'; 4 | 5 | void main() { 6 | // 开启布局边界 7 | //debugPaintSizeEnabled=true; 8 | // 沉浸式状态栏 9 | //SystemChrome.setEnabledSystemUIOverlays([]); 10 | // 强制竖屏 11 | runApp(new MyApp()); 12 | } 13 | 14 | class MyApp extends StatelessWidget { 15 | // This widget is the root of your application. 16 | @override 17 | Widget build(BuildContext context) { 18 | return new MaterialApp( 19 | title: 'Flutter Demo', 20 | debugShowCheckedModeBanner: false, 21 | theme: new ThemeData( 22 | primarySwatch: Colors.blue, backgroundColor: Colors.transparent), 23 | home: Scaffold( 24 | body: SplashPage(), 25 | ), 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/manager/BusManager.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_bingocode/bean/DirInfo.dart'; 5 | import 'package:flutter_bingocode/bean/StationInfo.dart'; 6 | import 'package:flutter_bingocode/resources/strings.dart'; 7 | import 'package:flutter_bingocode/util/CommonUtil.dart'; 8 | import 'package:flutter_bingocode/util/ConstantUtil.dart'; 9 | import 'package:flutter_bingocode/util/FileUtil.dart'; 10 | import 'package:html/dom.dart' as dom; 11 | import 'package:html/parser.dart' show parse; 12 | import 'package:http/http.dart' as http; 13 | import 'package:shared_preferences/shared_preferences.dart'; 14 | 15 | typedef UpdateCallBack = Function(T data); 16 | 17 | class BusManager { 18 | // 工厂模式 19 | factory BusManager() => _getInstance(); 20 | 21 | static BusManager get instance => _getInstance(); 22 | static BusManager _instance; 23 | final Utf8Decoder decoder = new Utf8Decoder(); 24 | var busLineList = []; 25 | var dirInfoList = []; 26 | var stationInfoList = []; 27 | String busLine; 28 | String busDirId; 29 | String busSelfStopId; 30 | DirInfo busDir; 31 | StationInfo busSelfStop; 32 | 33 | BusManager._internal() { 34 | // 初始化 35 | } 36 | 37 | static BusManager _getInstance() { 38 | if (_instance == null) { 39 | _instance = new BusManager._internal(); 40 | } 41 | return _instance; 42 | } 43 | 44 | Future> getSavedBusLine() async { 45 | SharedPreferences prefs = await SharedPreferences.getInstance(); 46 | return { 47 | KeyConstant.keyBusLine: prefs.getString(KeyConstant.keyBusLine), 48 | KeyConstant.keyBusDir: prefs.getString(KeyConstant.keyBusDir), 49 | KeyConstant.keyBusStation: prefs.getString(KeyConstant.keyBusStation) 50 | }; 51 | } 52 | 53 | saveBusLine(BuildContext context) async { 54 | SharedPreferences prefs = await SharedPreferences.getInstance(); 55 | if (busLine == null) { 56 | CommonUtil.toast(StringRes.choose_bus_hint); 57 | } else { 58 | showDialog( 59 | context: context, 60 | builder: (BuildContext context) { 61 | return AlertDialog( 62 | title: Text(StringRes.saveBusLine), 63 | content: Column( 64 | mainAxisSize: MainAxisSize.min, 65 | crossAxisAlignment: CrossAxisAlignment.start, 66 | children: _getSaveDialogItems(), 67 | ), 68 | actions: [ 69 | FlatButton( 70 | child: Text(StringRes.concel), 71 | onPressed: () { 72 | Navigator.of(context).pop(); 73 | }, 74 | ), 75 | FlatButton( 76 | child: Text(StringRes.confirm), 77 | onPressed: () { 78 | prefs.setString(KeyConstant.keyBusLine, busLine); 79 | prefs.setString(KeyConstant.keyBusDir, 80 | busDir == null ? null : busDir.directionId); 81 | prefs.setString(KeyConstant.keyBusStation, 82 | busSelfStop == null ? null : busSelfStop.index); 83 | CommonUtil.toast(StringRes.save_successed); 84 | Navigator.of(context).pop(); 85 | }, 86 | ), 87 | ], 88 | ); 89 | }); 90 | } 91 | } 92 | 93 | List _getSaveDialogItems() { 94 | var items = []; 95 | items.add(Text(StringRes.chooseBus + ': $busLine')); 96 | if (busDir != null) { 97 | items.add(Text(StringRes.chooseDir + ':${busDir.direction}')); 98 | } 99 | if (busSelfStop != null) { 100 | items.add(Text(StringRes.chooseStation + ':${busSelfStop.name}')); 101 | } 102 | return items; 103 | } 104 | 105 | // 获取所有公交线(内存 -> 文件 -> 网络 三级缓存) 106 | Future> getBusList() async { 107 | if (busLineList.isNotEmpty) { 108 | return busLineList; 109 | } 110 | return FileUtil.readLocalBuses().then((List buses) async { 111 | busLineList = buses; 112 | if (busLineList.isNotEmpty) { 113 | return busLineList; 114 | } 115 | busLineList.clear(); 116 | var responseAllBus = await http.get(UrlConstant.getBusesUrl); 117 | var data = decoder.convert(responseAllBus.bodyBytes); 118 | if (responseAllBus.statusCode == 200) { 119 | dom.Document document = parse(data); 120 | List aEliments = 121 | document.getElementsByTagName("dd").where((dom.Element e) { 122 | return e.attributes["id"] == 'selBLine'; 123 | }).toList(); 124 | print('all busLine:'); 125 | for (dom.Element e in aEliments) { 126 | for (dom.Element child in e.children) { 127 | print(child.text); 128 | busLineList.add(child.text); 129 | } 130 | } 131 | } else { 132 | print('fetch buses list error ${responseAllBus.statusCode.toString()}'); 133 | } 134 | FileUtil.saveBused(busLineList); 135 | return busLineList; 136 | }); 137 | } 138 | 139 | // 根据选择的公交线获取两个方向信息 140 | Future> getDirList() async { 141 | busDir = null; 142 | busSelfStop = null; 143 | stationInfoList.clear(); 144 | dirInfoList.clear(); 145 | var busDirUrl = '${UrlConstant.getDirUrl}&selBLine=$busLine'; 146 | var responseBusDir = await http.get(busDirUrl); 147 | var data = decoder.convert(responseBusDir.bodyBytes); 148 | if (responseBusDir.statusCode == 200) { 149 | dom.Document document = parse(data); 150 | List aEliments = document.getElementsByTagName("a"); 151 | for (dom.Element e in aEliments) { 152 | print(e.text); 153 | print(e.attributes["data-uuid"]); 154 | dirInfoList.add(DirInfo(e.text, e.attributes["data-uuid"])); 155 | } 156 | } else { 157 | print('request busdir error ${responseBusDir.statusCode.toString()}'); 158 | } 159 | return dirInfoList; 160 | } 161 | 162 | // 根据所选线路和方向获取所有站点信息 163 | Future> getStationList() async { 164 | busSelfStop = null; 165 | stationInfoList.clear(); 166 | var busStationUrl = 167 | '${UrlConstant.getStationUrl}&selBLine=$busLine&selBDir=${busDir.directionId}'; 168 | var responseBusStation = await http.get(busStationUrl); 169 | var data = decoder.convert(responseBusStation.bodyBytes); 170 | if (responseBusStation.statusCode == 200) { 171 | dom.Document document = parse(data); 172 | List aEliments = document.getElementsByTagName("a"); 173 | for (dom.Element e in aEliments) { 174 | print(e.text); 175 | print(e.attributes["data-seq"]); 176 | stationInfoList.add(StationInfo(e.text, e.attributes["data-seq"])); 177 | } 178 | } else { 179 | print( 180 | 'request busStationLists error ${responseBusStation.statusCode.toString()}'); 181 | } 182 | return stationInfoList; 183 | } 184 | 185 | // 获取实时公交信息 186 | Future> getOnlineBusInfo(final BuildContext context) async { 187 | var busOnlineUrl = 188 | '${UrlConstant.getBusOnLineUrl}&selBLine=$busLine&selBDir=${busDir.directionId}&busDir&selBStop=${busSelfStop.index}'; 189 | var responseBusOnline = await http.get(busOnlineUrl); 190 | var data = decoder.convert(responseBusOnline.bodyBytes); 191 | var buscList = []; //途中车辆 192 | var bussList = []; // 到站车辆 193 | if (responseBusOnline.statusCode == 200) { 194 | Map dataMap = json.decode(data); 195 | String htmlStr = dataMap['html']; 196 | dom.Document document = parse(htmlStr); 197 | var aEliments = document.getElementsByTagName("i"); 198 | for (dom.Element e in aEliments) { 199 | var classValue = e.attributes['class']; 200 | if (classValue != null) { 201 | if (classValue == 'busc') { 202 | //途中车辆 203 | dom.Element parent = e.parent; 204 | String parentId = parent.attributes['id']; 205 | buscList.add(parentId.substring(0, parentId.length - 1)); 206 | } else if (classValue == 'buss') { 207 | // 到站车辆 208 | dom.Element parent = e.parent; 209 | bussList.add((parent.attributes['id'])); 210 | } 211 | } 212 | } 213 | } else { 214 | print( 215 | 'request busOnline error ${responseBusOnline.statusCode.toString()}'); 216 | } 217 | _clearTags(); 218 | for (StationInfo station in stationInfoList) { 219 | if (station.index == busSelfStop.index) { 220 | station.isSelfStop = true; 221 | } 222 | if (buscList.length > 0) { 223 | for (String index in buscList) { 224 | if (index == station.index) { 225 | station.hasNextBus = true; 226 | break; 227 | } 228 | } 229 | } 230 | 231 | if (bussList.length > 0) { 232 | for (String index in bussList) { 233 | if (index == station.index) { 234 | station.hasBus = true; 235 | break; 236 | } 237 | } 238 | } 239 | } 240 | return stationInfoList; 241 | } 242 | 243 | void _clearTags() { 244 | for (StationInfo station in stationInfoList) { 245 | station.isSelfStop = false; 246 | station.hasNextBus = false; 247 | station.hasBus = false; 248 | } 249 | } 250 | } 251 | -------------------------------------------------------------------------------- /lib/myinfo/FavoriteIcon.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bingocode/util/CommonUtil.dart'; 3 | 4 | class FavoriteIcon extends StatelessWidget { 5 | @override 6 | Widget build(BuildContext context) { 7 | return new Theme( 8 | data: Theme.of(context).copyWith(accentColor: Colors.white), 9 | child: FloatingActionButton( 10 | isExtended: true, 11 | onPressed: () { 12 | CommonUtil.toast("谢谢赞赏"); 13 | }, 14 | child: Icon( 15 | Icons.thumb_up, 16 | color: Colors.redAccent, 17 | size: 36, 18 | ))); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/myinfo/MyInfoIcon.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bingocode/myinfo/MyInfoPage.dart'; 3 | import 'package:flutter_bingocode/route/CustomRoute.dart'; 4 | 5 | class MyInfoIcon extends StatelessWidget { 6 | @override 7 | Widget build(BuildContext context) { 8 | return new InkWell( 9 | onTap: () { 10 | Navigator.push(context, SlideRoute(MyInfoPage(), SlideRoute.RIGHT)); 11 | }, 12 | child: Icon( 13 | Icons.thumb_up, 14 | color: Colors.redAccent, 15 | size: 36, 16 | )); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/myinfo/MyInfoPage.dart: -------------------------------------------------------------------------------- 1 | import 'package:flare_flutter/flare_actor.dart'; 2 | import 'package:flutter/gestures.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/services.dart'; 5 | import 'package:flutter_bingocode/myinfo/FavoriteIcon.dart'; 6 | import 'package:flutter_bingocode/resources/strings.dart'; 7 | import 'package:flutter_bingocode/resources/styles.dart'; 8 | import 'package:flutter_bingocode/util/CommonUtil.dart'; 9 | import 'package:flutter_bingocode/util/ConstantUtil.dart'; 10 | import 'package:http/http.dart' as http; 11 | import 'package:url_launcher/url_launcher.dart'; 12 | 13 | class MyInfoPage extends StatefulWidget { 14 | @override 15 | State createState() { 16 | // TODO: implement createState 17 | return MyInfoState(); 18 | } 19 | } 20 | 21 | class MyInfoState extends State { 22 | final TextEditingController _controller = new TextEditingController(); 23 | 24 | var seprateItems = []; 25 | var mainItems = []; 26 | 27 | @override 28 | void initState() { 29 | super.initState(); 30 | _initSeprateItems(); 31 | _initMainItems(); 32 | } 33 | 34 | @override 35 | Widget build(BuildContext context) { 36 | // TODO: implement build 37 | return MaterialApp( 38 | title: 'Flutter Demo', 39 | debugShowCheckedModeBanner: false, 40 | theme: ThemeData( 41 | backgroundColor: Colors.white70, 42 | primarySwatch: Colors.blue, 43 | ), 44 | home: Scaffold( 45 | body: ListView.separated( 46 | padding: EdgeInsets.all(0.0), 47 | // 直接这一句就可以实现沉浸式状态栏 48 | itemCount: mainItems.length, 49 | shrinkWrap: true, 50 | separatorBuilder: (context, index) { 51 | return index >= seprateItems.length 52 | ? Divider() 53 | : seprateItems[index]; 54 | }, 55 | itemBuilder: (context, index) { 56 | return mainItems[index]; 57 | }, 58 | ), 59 | floatingActionButton: FavoriteIcon(), 60 | )); 61 | } 62 | 63 | 64 | @override 65 | void dispose() { 66 | //todo 去除监听器 67 | super.dispose(); 68 | } 69 | 70 | _initSeprateItems() { 71 | seprateItems.add(_buildSeprateItem(StringRes.project_introduce)); 72 | seprateItems.add(_buildSeprateItem(StringRes.project_address)); 73 | seprateItems.add(_buildSeprateItem(StringRes.version_info)); 74 | seprateItems.add(_buildSeprateItem(StringRes.comment)); 75 | } 76 | 77 | Widget _buildSeprateItem(String title) { 78 | return Padding( 79 | padding: EdgeInsets.fromLTRB(15, 10, 15, 10), 80 | child: Text(title, style: StyleRes.seprate_text), 81 | ); 82 | } 83 | 84 | Widget _buildMainItem(Widget content) { 85 | return Padding( 86 | padding: EdgeInsets.fromLTRB(15, 10, 15, 10), 87 | child: Card( 88 | color: Colors.white, 89 | elevation: 8, 90 | child: Padding(padding: const EdgeInsets.all(15.0), child: content)), 91 | ); 92 | } 93 | 94 | _initMainItems() { 95 | var m0 = Container( 96 | height: 200, 97 | alignment: Alignment.topCenter, 98 | child: FlareActor( 99 | "assets/SpaceDemo.flr", 100 | alignment: Alignment.topCenter, 101 | fit: BoxFit.fitWidth, 102 | animation: "loading", 103 | ), 104 | ); 105 | 106 | var m1 = _buildMainItem( 107 | Text.rich(TextSpan(text: StringRes.my_infos, children: [ 108 | TextSpan( 109 | text: StringRes.beijin_bus, 110 | style: StyleRes.LinkTextStyle, 111 | recognizer: new TapGestureRecognizer() 112 | ..onTap = () { 113 | //增加一个点击事件 114 | print('open ${StringRes.beijin_bus_addr}'); 115 | launch(StringRes.beijin_bus_addr); 116 | }, 117 | ), 118 | TextSpan(text: StringRes.contact_me), 119 | TextSpan( 120 | text: StringRes.my_email, 121 | style: StyleRes.LinkTextStyle, 122 | recognizer: new TapGestureRecognizer() 123 | ..onTap = () { 124 | //增加一个点击事件 125 | Clipboard.setData(new ClipboardData(text: StringRes.my_email)); 126 | CommonUtil.toast("已复制邮箱"); 127 | }, 128 | ), 129 | ]))); 130 | 131 | var m2 = _buildMainItem(Text.rich(TextSpan( 132 | text: StringRes.project_github, 133 | style: StyleRes.LinkTextStyle, 134 | recognizer: new TapGestureRecognizer() 135 | ..onTap = () { 136 | //增加一个点击事件 137 | print('open ${StringRes.project_github_address}'); 138 | launch(StringRes.project_github_address); 139 | }, 140 | children: [ 141 | TextSpan( 142 | text: StringRes.project_juejing, 143 | style: StyleRes.LinkTextStyle, 144 | recognizer: new TapGestureRecognizer() 145 | ..onTap = () { 146 | //增加一个点击事件 147 | print('open ${StringRes.project_juejing_address}'); 148 | launch(StringRes.project_juejing_address); 149 | }, 150 | ) 151 | ]))); 152 | var m3 = _buildMainItem(Text(StringRes.version)); 153 | 154 | var m4 = _buildMainItem(Column( 155 | crossAxisAlignment: CrossAxisAlignment.start, 156 | mainAxisSize: MainAxisSize.max, 157 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 158 | children: [ 159 | Padding( 160 | padding: const EdgeInsets.only(bottom: 10), 161 | child: TextField( 162 | controller: _controller, 163 | maxLines: 5, 164 | decoration: InputDecoration( 165 | contentPadding: EdgeInsets.all(10.0), 166 | border: OutlineInputBorder( 167 | borderRadius: BorderRadius.circular(10.0), 168 | ))), 169 | ), 170 | InkWell( 171 | onTap: () { 172 | _submitComment(); 173 | }, 174 | child: Container( 175 | padding: EdgeInsets.fromLTRB(8, 3, 8, 3), 176 | decoration: BoxDecoration( 177 | shape: BoxShape.rectangle, 178 | border: Border.all(color: Colors.blueAccent, width: 1), 179 | borderRadius: BorderRadius.all(Radius.circular(5))), 180 | child: Text(StringRes.submit, 181 | style: StyleRes.saveBusButtonTextStyle)), 182 | ), 183 | ], 184 | )); 185 | 186 | mainItems.add(m0); 187 | mainItems.add(m1); 188 | mainItems.add(m2); 189 | mainItems.add(m3); 190 | mainItems.add(m4); 191 | } 192 | 193 | Future _submitComment() async { 194 | var content = _controller.text; 195 | if (content.isEmpty) { 196 | CommonUtil.toast("请输入内容"); 197 | return; 198 | } 199 | var submitUrl = '${UrlConstant.commentUrl}$content'; 200 | var responseBusDir = await http.get(submitUrl); 201 | if (responseBusDir.statusCode == 200) { 202 | //清空评论 203 | _controller.clear(); 204 | CommonUtil.toast("提交成功"); 205 | } else { 206 | print('submit comment error ${responseBusDir.statusCode.toString()}'); 207 | CommonUtil.toast("提交失败"); 208 | } 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /lib/resources/colors.dart: -------------------------------------------------------------------------------- 1 | class ColorRes { 2 | static const String gray_toast_bg = '#434A4C'; 3 | static const String white = "#ffffff"; 4 | } -------------------------------------------------------------------------------- /lib/resources/strings.dart: -------------------------------------------------------------------------------- 1 | class StringRes { 2 | static const String chooseBus = '选择公交'; 3 | static const String chooseDir = '选择方向'; 4 | static const String chooseStation = '选择站点'; 5 | static const String queryBus = '查询'; 6 | static const String saveBusLine = '保存路线'; 7 | static const String choose_bus_hint = '请选择公交路线'; 8 | static const String choose_dir_hint = '请选择方向'; 9 | static const String choose_selfStop_hint = '请选择所在站点'; 10 | static const String save_successed = '保存成功'; 11 | static const String next_step = '下一步'; 12 | static const String confirm = '确定'; 13 | static const String concel = '取消'; 14 | static const String arrived_bus = '已到站: '; 15 | static const String coming_bus = '即将到站: '; 16 | static const String project_introduce = '应用简介'; 17 | static const String my_infos = '本应用提供搜查询实时北京公交到站信息功能,阁下亦可保存常用的路线信息,简化查询流程。数据来源于'; 18 | static const String beijin_bus = '北京公交网'; 19 | static const String beijin_bus_addr = 'http://www.bjbus.com/home/index.php'; 20 | static const String contact_me = '。若数据有不实之处,请以官网为准。在下不才,但凡是金玉良言,请于下方留言反馈,意犹未尽者,请联系以下邮箱,在下必逐一批阅\n'; 21 | static const String my_email = 'bingocoder@outlook.com'; 22 | static const String project_address = '项目地址'; 23 | static const String project_github = 'github地址\n'; 24 | static const String project_github_address = 'https://github.com/bingocode/flutter_bingocode'; 25 | static const String project_juejing = '博客地址'; 26 | static const String project_juejing_address = 'https://juejin.im/user/598c1964f265da3e190da56e'; 27 | static const String comment = '用户反馈'; 28 | static const String version_info = '版本信息'; 29 | static const String version = '1.0'; 30 | static const String submit = '提交'; 31 | } -------------------------------------------------------------------------------- /lib/resources/styles.dart: -------------------------------------------------------------------------------- 1 | 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | class StyleRes { 6 | static final TextStyle chooseBusButtonTextStyle = TextStyle( 7 | color: Colors.white, 8 | fontFamily: 'Roboto', 9 | letterSpacing: 0.5, 10 | ); 11 | 12 | static final TextStyle saveBusButtonTextStyle = TextStyle( 13 | color: Colors.blueAccent, 14 | fontFamily: 'Roboto', 15 | letterSpacing: 0.5, 16 | ); 17 | 18 | static final TextStyle LinkTextStyle = TextStyle( 19 | color: Colors.green, 20 | fontFamily: 'Roboto', 21 | ); 22 | 23 | static final TextStyle seprate_text = TextStyle( 24 | color: Colors.black, 25 | fontFamily: 'Roboto', 26 | letterSpacing: 0.5, 27 | fontSize: 16, 28 | fontWeight: FontWeight.bold 29 | ); 30 | } -------------------------------------------------------------------------------- /lib/resources/themes.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class CustomColorTheme { 4 | static Theme buildWhiteTheme(BuildContext context, Widget child) { 5 | return Theme( 6 | data: Theme.of(context).copyWith(accentColor: Colors.white), child: child); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /lib/route/CustomRoute.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class FadeRoute extends PageRouteBuilder{ 4 | final Widget widget; 5 | FadeRoute(this.widget) 6 | :super( 7 | transitionDuration:const Duration(seconds:1), 8 | pageBuilder:( 9 | BuildContext context, 10 | Animation animation1, 11 | Animation animation2){ 12 | return widget; 13 | }, 14 | transitionsBuilder:( 15 | BuildContext context, 16 | Animation animation1, 17 | Animation animation2, 18 | Widget child){ 19 | return FadeTransition( 20 | opacity: Tween(begin:0.0,end :1.0).animate(CurvedAnimation( 21 | parent:animation1, 22 | curve:Curves.fastOutSlowIn 23 | )), 24 | child: child, 25 | ); 26 | } 27 | ); 28 | } 29 | 30 | 31 | class SlideRoute extends PageRouteBuilder{ 32 | final Widget widget; 33 | final int direction; 34 | static const int LEFT = 0; 35 | static const int RIGHT = 1; 36 | static const int UP = 2; 37 | static const int DOWN = 3; 38 | SlideRoute(this.widget, this.direction) 39 | :super( 40 | transitionDuration:const Duration(seconds:1), 41 | pageBuilder:( 42 | BuildContext context, 43 | Animation animation1, 44 | Animation animation2){ 45 | return widget; 46 | }, 47 | transitionsBuilder:( 48 | BuildContext context, 49 | Animation animation1, 50 | Animation animation2, 51 | Widget child){ 52 | return SlideTransition( 53 | position: _getTween(direction) 54 | .animate(CurvedAnimation( 55 | parent: animation1, 56 | curve: Curves.fastOutSlowIn 57 | )), 58 | child: child, 59 | ); 60 | } 61 | ); 62 | 63 | static Tween _getTween(int dir) { 64 | switch (dir) { 65 | case RIGHT: 66 | return Tween( 67 | begin: Offset(-1.0, 0.0), 68 | end:Offset(0.0, 0.0) 69 | ); 70 | case UP: 71 | return Tween( 72 | begin: Offset(0.0, 1.0), 73 | end:Offset(0.0, 0.0) 74 | ); 75 | case DOWN: 76 | return Tween( 77 | begin: Offset(0.0, -1.0), 78 | end:Offset(0.0, 0.0) 79 | ); 80 | default: 81 | return Tween( 82 | begin: Offset(1.0, 0.0), 83 | end:Offset(0.0, 0.0) 84 | ); 85 | } 86 | } 87 | } 88 | 89 | -------------------------------------------------------------------------------- /lib/savebus/SaveBusIcon.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bingocode/manager/BusManager.dart'; 3 | import 'package:flutter_bingocode/util/ConstantUtil.dart'; 4 | 5 | class SaveBusIcon extends StatefulWidget { 6 | @override 7 | State createState() { 8 | // TODO: implement createState 9 | return SaveBusIconState(); 10 | } 11 | } 12 | 13 | class SaveBusIconState extends State { 14 | BusManager _busManager; 15 | bool hasSaved = false; 16 | 17 | @override 18 | void initState() { 19 | super.initState(); 20 | _busManager = BusManager(); 21 | _busManager.getSavedBusLine().then((Map savedMap) { 22 | if (savedMap[KeyConstant.keyBusLine] != null) { 23 | hasSaved = true; 24 | } 25 | setState(() {}); 26 | }); 27 | } 28 | 29 | @override 30 | Widget build(BuildContext context) { 31 | // TODO: implement build 32 | return new Theme( 33 | data: Theme.of(context) 34 | .copyWith(accentColor: hasSaved ? Colors.white : Colors.redAccent), 35 | child: FloatingActionButton( 36 | isExtended: true, 37 | onPressed: () { 38 | _busManager.saveBusLine(context); 39 | }, 40 | child: Icon( 41 | Icons.grade, 42 | color: hasSaved ? Colors.redAccent : Colors.white, 43 | size: 36, 44 | ))); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/showbus/ShowBusPage.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_bingocode/bean/StationInfo.dart'; 5 | import 'package:flutter_bingocode/manager/BusManager.dart'; 6 | import 'package:flutter_bingocode/resources/strings.dart'; 7 | import 'package:flutter_bingocode/showbus/StationItem.dart'; 8 | 9 | class ShowBusPage extends StatefulWidget { 10 | @override 11 | State createState() { 12 | return ShowBusState(); 13 | } 14 | } 15 | 16 | class ShowBusState extends State { 17 | static const UPDATE_TIME = 10; 18 | BusManager _busManager; 19 | Timer timer; 20 | UpdateCallBack> updateStationsCallBack; 21 | 22 | @override 23 | void initState() { 24 | super.initState(); 25 | updateStationsCallBack = (List dirinfos) { 26 | setState(() {}); 27 | }; 28 | _busManager = BusManager(); 29 | // 每隔10s更新界面 30 | timer = Timer.periodic(const Duration(seconds: UPDATE_TIME), (timer) { 31 | print('refreshData'); 32 | _busManager.getOnlineBusInfo(context).then(updateStationsCallBack); 33 | }); 34 | } 35 | 36 | @override 37 | Widget build(BuildContext context) { 38 | return MaterialApp( 39 | title: 'Flutter Demo', 40 | debugShowCheckedModeBanner: false, 41 | theme: ThemeData( 42 | backgroundColor: Colors.transparent, 43 | primarySwatch: Colors.blue, 44 | ), 45 | home: Scaffold( 46 | body: Container( 47 | decoration: BoxDecoration( 48 | image: DecorationImage( 49 | image: AssetImage('assets/show_bus_bg.jpg'), 50 | fit: BoxFit.fitHeight)), 51 | child: Column( 52 | mainAxisAlignment: MainAxisAlignment.center, 53 | children: [ 54 | Padding( 55 | padding: const EdgeInsets.only(top: 50, bottom: 20), 56 | child: Row( 57 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 58 | children: [ 59 | Text(StringRes.coming_bus, 60 | style: TextStyle(color: Colors.white)), 61 | Icon(Icons.directions_bus, color: Colors.blueAccent), 62 | Text(StringRes.arrived_bus, 63 | style: TextStyle(color: Colors.white)), 64 | Icon(Icons.airport_shuttle, color: Colors.greenAccent), 65 | ], 66 | ), 67 | ), 68 | Divider(), 69 | Expanded( 70 | child: ListView.separated( 71 | shrinkWrap: true, 72 | // 按需加载,适合加载长列表 73 | itemCount: _busManager.stationInfoList.length, 74 | separatorBuilder: (context, index) { 75 | return Divider( 76 | height: 1, 77 | indent: 15, 78 | ); 79 | }, 80 | itemBuilder: (context, index) { 81 | return _getListTitle(_busManager.stationInfoList[index]); 82 | }), 83 | ), 84 | ], 85 | ), 86 | ))); 87 | } 88 | 89 | Widget _getListTitle(StationInfo station) { 90 | BaseStationItem item = 91 | station.isSelfStop ? TargetStation(station) : NormalStation(station); 92 | return item.getWidget(); 93 | } 94 | 95 | @override 96 | void dispose() { 97 | timer.cancel(); 98 | super.dispose(); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /lib/showbus/StationItem.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bingocode/bean/StationInfo.dart'; 3 | abstract class BaseStationItem { 4 | static const STATE_NO_BUS = 0; 5 | static const STATE_COMING_BUS = 1; 6 | static const STATE_ARRIVED_BUS = 2; 7 | StationInfo station; 8 | ListTile getWidget(); 9 | 10 | _initState() { 11 | if(station.hasBus) { 12 | return STATE_ARRIVED_BUS; 13 | } else if (station.hasNextBus) { 14 | return STATE_COMING_BUS; 15 | } else { 16 | return STATE_NO_BUS; 17 | } 18 | } 19 | 20 | AnimatedOpacity buildIcon() { 21 | var state = _initState(); 22 | switch (state) { 23 | case STATE_ARRIVED_BUS: 24 | return AnimatedOpacity( 25 | child: Icon(Icons.airport_shuttle, color: Colors.greenAccent), 26 | duration: const Duration(seconds: 2), 27 | opacity: 1.0, 28 | ); 29 | case STATE_COMING_BUS: 30 | return AnimatedOpacity( 31 | child: Icon(Icons.directions_bus, color: Colors.blueAccent), 32 | duration: const Duration(seconds: 2), 33 | opacity: 1.0, 34 | ); 35 | case STATE_NO_BUS: 36 | return AnimatedOpacity( 37 | child: Icon(Icons.arrow_downward, color: Colors.white), 38 | duration: const Duration(seconds: 2), 39 | opacity: 1, 40 | ); 41 | } 42 | } 43 | } 44 | 45 | // 非目标站 46 | 47 | class NormalStation extends BaseStationItem{ 48 | 49 | NormalStation(StationInfo station) { 50 | this.station = station; 51 | } 52 | 53 | @override 54 | ListTile getWidget() { 55 | return ListTile( 56 | title: Text(station.name, style: TextStyle(color: Colors.white)), 57 | trailing: buildIcon()); 58 | } 59 | 60 | } 61 | 62 | 63 | // 目标站 64 | 65 | class TargetStation extends BaseStationItem{ 66 | 67 | TargetStation(StationInfo station) { 68 | this.station = station; 69 | } 70 | 71 | @override 72 | ListTile getWidget() { 73 | return ListTile( 74 | title: Text(station.name, style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold)), 75 | trailing: buildIcon()); 76 | } 77 | 78 | } 79 | 80 | 81 | -------------------------------------------------------------------------------- /lib/util/AnimationUtil.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/animation.dart'; 2 | import 'package:flutter/material.dart'; 3 | class TransitionAnimation extends StatelessWidget { 4 | final Widget child; 5 | final Animation animation; 6 | TransitionAnimation({this.child, this.animation}); 7 | 8 | Widget build(BuildContext context) { 9 | return new Center( 10 | child: new AnimatedBuilder( 11 | animation: animation, 12 | builder: (BuildContext context, Widget child) { 13 | return new Container( 14 | height: animation.value, width: animation.value, child: child); 15 | }, 16 | child: child), 17 | ); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /lib/util/CommonUtil.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:fluttertoast/fluttertoast.dart'; 3 | 4 | class CommonUtil { 5 | static toast(String msg) { 6 | Fluttertoast.showToast( 7 | msg: msg, 8 | toastLength: Toast.LENGTH_SHORT, 9 | gravity: ToastGravity.BOTTOM, 10 | timeInSecForIos: 1, 11 | backgroundColor: Colors.black, 12 | textColor: Colors.white); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /lib/util/ConstantUtil.dart: -------------------------------------------------------------------------------- 1 | 2 | class UrlConstant { 3 | static const baseUrl = 'http://www.bjbus.com/home/ajax_rtbus_data.php'; 4 | static const BingoUrl= 'http://39.107.71.82:8080'; 5 | 6 | static const getBusesUrl = 'http://www.bjbus.com/home/index.php'; 7 | static const getDirUrl = '$baseUrl?act=getLineDir'; 8 | static const getStationUrl = '$baseUrl?act=getDirStation'; 9 | static const getBusOnLineUrl = '$baseUrl?act=busTime'; 10 | static const commentUrl = '$BingoUrl/comment?comment='; 11 | } 12 | 13 | class KeyConstant { 14 | static const keyBusLine = "busLine"; 15 | static const keyBusDir = "busDir"; 16 | static const keyBusStation = "busStation"; 17 | } -------------------------------------------------------------------------------- /lib/util/FileUtil.dart: -------------------------------------------------------------------------------- 1 | import 'package:path_provider/path_provider.dart'; 2 | 3 | import 'dart:io'; 4 | 5 | class FileUtil { 6 | static Future getLocalBusesFile() async { 7 | // get the path to the document directory. 8 | String dir = (await getApplicationDocumentsDirectory()).path; 9 | return new File('$dir/buses.txt'); 10 | } 11 | 12 | static Future> readLocalBuses() async { 13 | try { 14 | File file = await getLocalBusesFile(); 15 | String contents = await file.readAsString(); 16 | return contents.substring(1, contents.length-1).split(', '); 17 | } on FileSystemException { 18 | print('file error'); 19 | return []; 20 | } 21 | } 22 | 23 | static Future saveBused(List buses) async { 24 | // write the variable as a string to the file 25 | try { 26 | File file = await getLocalBusesFile(); 27 | if(file.existsSync()) { 28 | file.deleteSync(); 29 | } 30 | file.writeAsString(buses.toString()); 31 | } on FileSystemException { 32 | print("file error"); 33 | } 34 | } 35 | 36 | 37 | } -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | archive: 5 | dependency: transitive 6 | description: 7 | name: archive 8 | url: "https://pub.flutter-io.cn" 9 | source: hosted 10 | version: "2.0.11" 11 | args: 12 | dependency: transitive 13 | description: 14 | name: args 15 | url: "https://pub.flutter-io.cn" 16 | source: hosted 17 | version: "1.5.2" 18 | async: 19 | dependency: transitive 20 | description: 21 | name: async 22 | url: "https://pub.flutter-io.cn" 23 | source: hosted 24 | version: "2.4.0" 25 | boolean_selector: 26 | dependency: transitive 27 | description: 28 | name: boolean_selector 29 | url: "https://pub.flutter-io.cn" 30 | source: hosted 31 | version: "1.0.5" 32 | charcode: 33 | dependency: transitive 34 | description: 35 | name: charcode 36 | url: "https://pub.flutter-io.cn" 37 | source: hosted 38 | version: "1.1.2" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.flutter-io.cn" 44 | source: hosted 45 | version: "1.14.11" 46 | convert: 47 | dependency: transitive 48 | description: 49 | name: convert 50 | url: "https://pub.flutter-io.cn" 51 | source: hosted 52 | version: "2.1.1" 53 | crypto: 54 | dependency: transitive 55 | description: 56 | name: crypto 57 | url: "https://pub.flutter-io.cn" 58 | source: hosted 59 | version: "2.1.3" 60 | csslib: 61 | dependency: transitive 62 | description: 63 | name: csslib 64 | url: "https://pub.flutter-io.cn" 65 | source: hosted 66 | version: "0.16.1" 67 | cupertino_icons: 68 | dependency: "direct main" 69 | description: 70 | name: cupertino_icons 71 | url: "https://pub.flutter-io.cn" 72 | source: hosted 73 | version: "0.1.3" 74 | flare_flutter: 75 | dependency: "direct main" 76 | description: 77 | name: flare_flutter 78 | url: "https://pub.flutter-io.cn" 79 | source: hosted 80 | version: "1.0.11" 81 | flutter: 82 | dependency: "direct main" 83 | description: flutter 84 | source: sdk 85 | version: "0.0.0" 86 | flutter_test: 87 | dependency: "direct dev" 88 | description: flutter 89 | source: sdk 90 | version: "0.0.0" 91 | fluttertoast: 92 | dependency: "direct main" 93 | description: 94 | name: fluttertoast 95 | url: "https://pub.flutter-io.cn" 96 | source: hosted 97 | version: "3.1.3" 98 | html: 99 | dependency: "direct main" 100 | description: 101 | name: html 102 | url: "https://pub.flutter-io.cn" 103 | source: hosted 104 | version: "0.14.0+3" 105 | http: 106 | dependency: "direct main" 107 | description: 108 | name: http 109 | url: "https://pub.flutter-io.cn" 110 | source: hosted 111 | version: "0.12.0+4" 112 | http_parser: 113 | dependency: transitive 114 | description: 115 | name: http_parser 116 | url: "https://pub.flutter-io.cn" 117 | source: hosted 118 | version: "3.1.3" 119 | image: 120 | dependency: transitive 121 | description: 122 | name: image 123 | url: "https://pub.flutter-io.cn" 124 | source: hosted 125 | version: "2.1.4" 126 | matcher: 127 | dependency: transitive 128 | description: 129 | name: matcher 130 | url: "https://pub.flutter-io.cn" 131 | source: hosted 132 | version: "0.12.6" 133 | meta: 134 | dependency: transitive 135 | description: 136 | name: meta 137 | url: "https://pub.flutter-io.cn" 138 | source: hosted 139 | version: "1.1.8" 140 | nima: 141 | dependency: "direct main" 142 | description: 143 | name: nima 144 | url: "https://pub.flutter-io.cn" 145 | source: hosted 146 | version: "1.0.5" 147 | path: 148 | dependency: transitive 149 | description: 150 | name: path 151 | url: "https://pub.flutter-io.cn" 152 | source: hosted 153 | version: "1.6.4" 154 | path_provider: 155 | dependency: "direct main" 156 | description: 157 | name: path_provider 158 | url: "https://pub.flutter-io.cn" 159 | source: hosted 160 | version: "1.5.0" 161 | pedantic: 162 | dependency: transitive 163 | description: 164 | name: pedantic 165 | url: "https://pub.flutter-io.cn" 166 | source: hosted 167 | version: "1.8.0+1" 168 | petitparser: 169 | dependency: transitive 170 | description: 171 | name: petitparser 172 | url: "https://pub.flutter-io.cn" 173 | source: hosted 174 | version: "2.4.0" 175 | platform: 176 | dependency: transitive 177 | description: 178 | name: platform 179 | url: "https://pub.flutter-io.cn" 180 | source: hosted 181 | version: "2.2.1" 182 | quiver: 183 | dependency: transitive 184 | description: 185 | name: quiver 186 | url: "https://pub.flutter-io.cn" 187 | source: hosted 188 | version: "2.0.5" 189 | shared_preferences: 190 | dependency: "direct main" 191 | description: 192 | name: shared_preferences 193 | url: "https://pub.flutter-io.cn" 194 | source: hosted 195 | version: "0.4.3" 196 | sky_engine: 197 | dependency: transitive 198 | description: flutter 199 | source: sdk 200 | version: "0.0.99" 201 | source_span: 202 | dependency: transitive 203 | description: 204 | name: source_span 205 | url: "https://pub.flutter-io.cn" 206 | source: hosted 207 | version: "1.5.5" 208 | stack_trace: 209 | dependency: transitive 210 | description: 211 | name: stack_trace 212 | url: "https://pub.flutter-io.cn" 213 | source: hosted 214 | version: "1.9.3" 215 | stream_channel: 216 | dependency: transitive 217 | description: 218 | name: stream_channel 219 | url: "https://pub.flutter-io.cn" 220 | source: hosted 221 | version: "2.0.0" 222 | string_scanner: 223 | dependency: transitive 224 | description: 225 | name: string_scanner 226 | url: "https://pub.flutter-io.cn" 227 | source: hosted 228 | version: "1.0.5" 229 | term_glyph: 230 | dependency: transitive 231 | description: 232 | name: term_glyph 233 | url: "https://pub.flutter-io.cn" 234 | source: hosted 235 | version: "1.1.0" 236 | test_api: 237 | dependency: transitive 238 | description: 239 | name: test_api 240 | url: "https://pub.flutter-io.cn" 241 | source: hosted 242 | version: "0.2.11" 243 | typed_data: 244 | dependency: transitive 245 | description: 246 | name: typed_data 247 | url: "https://pub.flutter-io.cn" 248 | source: hosted 249 | version: "1.1.6" 250 | url_launcher: 251 | dependency: "direct main" 252 | description: 253 | name: url_launcher 254 | url: "https://pub.flutter-io.cn" 255 | source: hosted 256 | version: "3.0.3" 257 | vector_math: 258 | dependency: transitive 259 | description: 260 | name: vector_math 261 | url: "https://pub.flutter-io.cn" 262 | source: hosted 263 | version: "2.0.8" 264 | xml: 265 | dependency: transitive 266 | description: 267 | name: xml 268 | url: "https://pub.flutter-io.cn" 269 | source: hosted 270 | version: "3.5.0" 271 | sdks: 272 | dart: ">=2.4.0 <3.0.0" 273 | flutter: ">=1.9.1+hotfix.5 <2.0.0" 274 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_bingocode 2 | description: A new Flutter application. 3 | 4 | dependencies: 5 | flutter: 6 | sdk: flutter 7 | 8 | # The following adds the Cupertino Icons font to your application. 9 | # Use with the CupertinoIcons class for iOS style icons. 10 | flare_flutter: 1.0.11 11 | nima: ^1.0.0 12 | cupertino_icons: ^0.1.2 13 | shared_preferences: ^0.4.2 14 | html: any 15 | http: any 16 | fluttertoast: ^3.1.0 17 | path_provider: 18 | url_launcher: ^3.0.3 19 | 20 | dev_dependencies: 21 | flutter_test: 22 | sdk: flutter 23 | 24 | 25 | # For information on the generic Dart part of this file, see the 26 | # following page: https://www.dartlang.org/tools/pub/pubspec 27 | 28 | # The following section is specific to Flutter. 29 | flutter: 30 | 31 | # The following line ensures that the Material Icons font is 32 | # included with your application, so that you can use the icons in 33 | # the material Icons class. 34 | uses-material-design: true 35 | assets: 36 | - ic_launcher.png 37 | - choose_bus_bg.jpg 38 | - choose_buses_bg.jpg 39 | - show_bus_bg.jpg 40 | - runLoading.nima 41 | - runLoading0.png 42 | - runLoading1.png 43 | - runLoading2.png 44 | - runLoading3.png 45 | - runLoading4.png 46 | - runLoading5.png 47 | - SpaceDemo.flr 48 | # To add assets to your application, add an assets section, like this: 49 | # assets: 50 | # - images/a_dot_burr.jpeg 51 | # - images/a_dot_ham.jpeg 52 | 53 | # An image asset can refer to one or more resolution-specific "variants", see 54 | # https://flutter.io/assets-and-images/#resolution-aware. 55 | 56 | # For details regarding adding assets from package dependencies, see 57 | # https://flutter.io/assets-and-images/#from-packages 58 | 59 | # To add custom fonts to your application, add a fonts section here, 60 | # in this "flutter" section. Each entry in this list should have a 61 | # "family" key with the font family name, and a "fonts" key with a 62 | # list giving the asset and other descriptors for the font. For 63 | # example: 64 | # fonts: 65 | # - family: Schyler 66 | # fonts: 67 | # - asset: fonts/Schyler-Regular.ttf 68 | # - asset: fonts/Schyler-Italic.ttf 69 | # style: italic 70 | # - family: Trajan Pro 71 | # fonts: 72 | # - asset: fonts/TrajanPro.ttf 73 | # - asset: fonts/TrajanPro_Bold.ttf 74 | # weight: 700 75 | # 76 | # For details regarding fonts from package dependencies, 77 | # see https://flutter.io/custom-fonts/#from-packages 78 | -------------------------------------------------------------------------------- /test/bingo_test.dart: -------------------------------------------------------------------------------- 1 | /// Dart 使用说明 2 | /// 1 Dart是强类型的,但类型声明是可选的,因为Dart可以推断类型,如果要明确说明不需要任何类型,则使用dynamic 3 | /// List 整数列表 4 | /// List 任何类型的对象列表 5 | /// 6 | /// 2 变量 7 | /// String name = "Bob"; 显式声明类型 8 | /// var name = "BOb"; name变量的类型被推断为String,但可以指定它来更改 9 | /// dynamic name = "Bob"; 若变量不限制于单一类型,则应声明对象为dynamic 10 | /// int line; 未初始化的变量初始值为null,变量中存放的所有东西都是对象,所有对象都继承自Object类 11 | /// final a; 最终变量,只能设置一次,最终顶级货类变量在第一次使用时被初始化 12 | /// const b; 编译时常量,注意实例变量可以是final,但不能是const 13 | /// var foo = const[]; const关键字不只是声明常量变量。您还可以使用它来创建常量值,以及声明创建常量值的构造函数 14 | /// foo = [1,2,3]; 可以更改一个非final的非const变量的值,即使它曾经有一个const值 15 | /// 16 | /// 3 内建类型 17 | /// 可以使用字面量初始化任何内建类型的对象,可以使用构造函数来初始化变量 18 | /// 数字num: 19 | /// int: 平台的不同,范围也不同。整数值不大于64位。在Dart VM上,值可以从-2^63到2^63 - 1 20 | /// double: 64位(双精度)浮点数 21 | /// 数字和字符串转换 int.parse('1') 3.14159.toStringAsFixed(2); 22 | /// 字符串String: 23 | /// 是UTF-16编码单元的序列,可以使用${expression}将表达式的值放入字符串中。如果表达式是一个标识符,可以不用{}, 24 | /// 可以用三重引号创建多行字符串,用r前缀创建一个原始字符串(不会因为有\n换行) 25 | /// 布尔型(bool):true, false 26 | /// 27 | /// 列表List: 28 | /// 数组即为列表对象, 29 | /// var list = [1,2,3]; 推断为List 类型,若添加非int对象,则会报错 30 | /// 映射Map: 31 | /// 可以通过map字面量直接创建,也可以通过Map()构造方法创建, 类型会自动推断 32 | /// var g = { 1: 'a', 2: 'b', 3: 'c'} 33 | /// var g1 = Map(); 34 | /// g1[1] = 'a1' 35 | /// final constantMap = const {2: 'b', 3: 'c'}; 36 | /// 字符Runes: 37 | /// 字符是字符串的UTF-32编码 38 | /// 符号Symbols: 39 | /// #bar 40 | /// 41 | /// 4 运算符 42 | /// 取摸 43 | /// assert(5 ~/ 2 == 2); 44 | /// 相等(==) 45 | /// 若两者都为空则返回true,若只有一空返回false;返回调用x.=(y) 的结果 46 | /// 需要知道两个对象是否完全相同的情况下,可以使用identical()函数) 47 | /// 类型测试 48 | /// 若obj 实现了T,则 obj is T 为真 49 | /// as操作符将对象转换为特定类型 50 | /// 赋值 51 | /// b ??= value; 仅仅在b为空的情况下b被赋值value否则b的值不变 52 | /// 条件表达式 53 | /// expr1 ?? expr2 如果expr1是非空的,则返回其值;否则,计算并返回expr2的值 54 | /// 级联 (..) 55 | /// 在同一个对象上创建一个操作序列,可以访问同一对象上的字段,调用函数,省去创建临时变量的步骤 56 | /// 不能再一个返回void结果上继续构建级联操作 57 | /// 其他 58 | /// ?. 根据条件访问成员,foo?.bar 如果foo为空则返回null 59 | /// 60 | /// 5 函数Function 61 | /// 函数也是对象,可以赋给函数,也可以赋给变量,甚至可以使函数的返回值。函数可以省略返回类型声明,所有函数都有返回一个值,默认返回null 62 | /// isBelowZero(int n) => n < 0; 只包含一个表达式的函数简写 63 | /// 命名参数: 64 | /// 在定义函数时,使用{param1, param2,…}来指定命名参数 65 | /// void enableFlags({bool bold, bool hidden}) {...} 66 | /// enableFlags(bold: true, hidden: false); 67 | /// 可选参数: 68 | /// 在普通的位置参数里,可以通过[]包装为一组可选参数,在命名参数里,可以通过@required标识必传参数,其他都是可选的。 69 | /// say(String from, String msg, [String device]) 70 | /// Scrollbar({Key key, @required Widget child}) 71 | /// 默认参数: 72 | /// 用 = 来定义参数的默认值。默认值必须是编译时常量。如果没有提供默认值,则默认值为null 73 | /// void enableFlags({bool bold = false, bool hidden = false}) 74 | /// main()函数: 75 | /// 应用程序的入口点。返回void,并有一个可选的列表参数作为参数 76 | /// void main(List arguments) { 77 | /// print(arguments); 78 | /// assert(arguments.length == 2); 79 | /// assert(int.parse(arguments[0]) == 1); 80 | /// assert(arguments[1] == 'test'); 81 | /// } 82 | /// 匿名函数: 83 | /// ([[Type] param1[, …]]) { 84 | /// codeBlock; 85 | /// }; 86 | /// 函数类型: 87 | /// typedef或function-type为函数提供一个类型别名 88 | /// typedef Compare = int Function(T a, T b); 89 | /// int sort(int a, int b) => a - b; 90 | /// void main() { 91 | /// assert(sort is Compare); // True! 92 | /// } 93 | /// 94 | /// 6 流程控制 95 | /// 若对象是可迭代的 96 | /// candidates.forEach((candidate) => candidate.interview()); 97 | /// List和Set等支持for in迭代 98 | /// for (var x in collection) { } 99 | /// 过滤器where 100 | /// 即使where筛选后为空也没问题,只是不会执行后面的forEach 101 | /// candidates 102 | /// .where((c) => c.yearsExperience >= 5) 103 | /// .forEach((c) => c.interview()); 104 | /// switch 105 | /// 每个非空的case子句以一个break语句结束,否则会报错,default 可以没有。 106 | /// 107 | /// 7 异常处理 108 | /// Dart的所有异常都是未检查异常,不要求去声明和捕获,异常有Exception和Error类型 109 | /// throw可以抛出异常或者其他非空对象(比如String) 110 | /// void distanceTo(Point other) => throw "OutOfLlamas" 111 | /// try { 112 | /// distanceTo(Point()); 113 | /// } on OutOfLlamasException catch(e){ 114 | /// print(e); 115 | /// } catch (e) { 116 | /// print(e); 117 | /// } 118 | /// rethrow 捕获处理异常后,再允许其传播 119 | /// 120 | /// 8 类 121 | /// 所有类都是Object子类,并且是单继承 122 | /// 泛型的使用(类型校验,减少代码冲怒) 123 | /// var nmae = List(); 124 | /// class Foo { 125 | /// 126 | /// } 127 | /// 导入库 128 | /// import 129 | /// import 'package:lib1/lib1.dart'; 130 | /// import 'package:lib2/lib2.dart' as lib2; 导入有冲突时指定前缀 131 | /// import 'package:lib1/lib1.dart' show foo; 只导入foo 132 | /// import 'package:lib2/lib2.dart' hide foo; 除了foo其他导入 133 | /// import 'package:greetings/hello.dart' deferred as hello; 延时加载 134 | /// Future greet() async { 135 | /// await hello.loadLibrary(); 需要时加载,可以在库上多次调用loadLibrary()。该库只加载一次 136 | /// hello.printGreeting(); 137 | /// } 138 | /// 可调用类 139 | /// 类实现call方法,则可以通过类对象直接调用函数 140 | /// 141 | /// 9 异步 142 | /// await必须是在一个使用async标注的异步函数使用,await表达式会让程序执行挂起,直到返回的对象可用 143 | /// 在await表达式中,表达式的值通常是一个Future对象。如果不是,那么这个值将被自动包装成Future 144 | /// Future checkVersion() async { 145 | /// var version = await lookUpVersion(); 146 | /// Do something with version 147 | /// } 148 | /// 声明异步函数 149 | /// 函数体用async修饰符标记,将使其返回一个Future,如果您的函数没有返回一个有用的值,那么将其返回Future类型 150 | /// String lookUpVersion() => '1.0.0' 同步函数 151 | /// Future lookUpVersion() async => '1.0.0'; 异步函数 152 | /// 流处理 153 | /// Future main() async { 154 | /// // ... 155 | /// await for (var request in requestServer) { 156 | /// handleRequest(request); 157 | /// } 158 | /// // ... 159 | /// } 160 | /// 隔离器 161 | /// 不同于线程,所有Dart代码都运行在隔离器内部,而不是线程。每个隔离都有它自己的内存堆,确保任何其他隔离器都不能访问隔离状态 162 | /// 163 | /// 10 生成器 164 | /// 同步生成器:将函数体标记为sync*,并使用yield语句传递值。返回Iterable对象 165 | /// Iterable naturalsTo(int n) sync* { 166 | /// int k = 0; 167 | /// while (k < n) yield k++; 168 | /// } 169 | /// 异步生成器:将函数体标记为async*,并使用yield语句传递值,返回Iterable对象 170 | /// Stream asynchronousNaturalsTo(int n) async* { 171 | /// int k = 0; 172 | /// while (k < n) yield k++; 173 | /// } 174 | /// 175 | /// 176 | /// 177 | /// 178 | 179 | class WannabeFunction { 180 | call(String a, String b, String c) => '$a $b $c!'; 181 | } 182 | 183 | printInteger(int n) { 184 | print('the number is $n'); 185 | } 186 | 187 | // 只包含一个表达式的函数简写 188 | isBelowZero(int n) => n < 0; 189 | 190 | // 返回一个加上addBy的函数 191 | Function makeAdder(num addBy) { 192 | // 返回一个匿名函数 193 | return (num i) => addBy + i; 194 | } 195 | 196 | main() { 197 | var number = 26; 198 | print(isBelowZero(number)); 199 | printInteger(number); 200 | // 原始字符串 201 | var s = r'In a raw string, not even \n gets special treatment.'; 202 | print(s); 203 | // 符号类型 204 | print(#bar); 205 | // 匿名函数 206 | var list = ['apples', 'bananas', 'oranges']; 207 | list.forEach((item) { 208 | print('${list.indexOf(item)}: $item'); 209 | }); 210 | // 函数作为函数的返回值 211 | var add2 = makeAdder(2); 212 | var add4 = makeAdder(4); 213 | print(add2(3)); 214 | print(add4(3)); 215 | var wf = new WannabeFunction(); 216 | var out = wf("Hi", "there,", "gang"); 217 | print('$out'); 218 | } 219 | -------------------------------------------------------------------------------- /test/bus_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:html/dom.dart' as dom; 4 | import 'package:html/parser.dart' show parse; 5 | import 'package:http/http.dart' as http; 6 | 7 | //http://www.bjbus.com/home/ajax_rtbus_data.php?act=getLineDir&selBLine=140 8 | //http://www.bjbus.com/home/ajax_rtbus_data.php?act=getDirStation&selBLine=140&selBDir=4817620473575672470 9 | //http://www.bjbus.com/home/ajax_rtbus_data.php?act=busTime&selBLine=10&selBDir=5582831127904445311&selBStop=3 10 | const baseUrl = 'http://www.bjbus.com/home/ajax_rtbus_data.php'; 11 | 12 | const getBusesUrl = 'http://www.bjbus.com/home/index.php'; 13 | const getDirUrl = '$baseUrl?act=getLineDir'; 14 | const getStationUrl = '$baseUrl?act=getDirStation'; 15 | const getBusOLineUrl = '$baseUrl?act=busTime'; 16 | var busLine = '963'; 17 | var busDir; 18 | var busSelfStop = '5'; 19 | var buses = []; 20 | 21 | class BusStation { 22 | int index; 23 | String name; 24 | } 25 | 26 | main() async { 27 | // 拉取所有的公交路线 28 | var responseAllBus = await http.get(getBusesUrl); 29 | Utf8Decoder decoder = new Utf8Decoder(); 30 | var data = decoder.convert(responseAllBus.bodyBytes); 31 | if (responseAllBus.statusCode == 200) { 32 | dom.Document document = parse(data); 33 | List aEliments = 34 | document.getElementsByTagName("dd").where((dom.Element e) { 35 | return e.attributes["id"] == 'selBLine'; 36 | }).toList(); 37 | for (dom.Element e in aEliments) { 38 | for (dom.Element child in e.children) { 39 | print(child.text); 40 | buses.add(child.text); 41 | } 42 | } 43 | } else { 44 | print('fetch buses list error ${responseAllBus.statusCode.toString()}'); 45 | } 46 | 47 | //获取交通路线,直接默认963 48 | var busDirUrl = '$getDirUrl&selBLine=$busLine'; 49 | var responseBusDir = await http.get(busDirUrl); 50 | data = decoder.convert(responseBusDir.bodyBytes); 51 | if (responseBusDir.statusCode == 200) { 52 | dom.Document document = parse(data); 53 | List aEliments = document.getElementsByTagName("a"); 54 | for (dom.Element e in aEliments) { 55 | print(e.text); 56 | print(e.attributes["data-uuid"]); 57 | busDir = e.attributes["data-uuid"]; 58 | } 59 | } else { 60 | print('request busdir error ${responseBusDir.statusCode.toString()}'); 61 | } 62 | 63 | // 选择路线和方向获取公交的所有站点 64 | var busStationUrl = '$getStationUrl&selBLine=$busLine&selBDir=$busDir'; 65 | var responseBusStation = await http.get(busStationUrl); 66 | data = decoder.convert(responseBusStation.bodyBytes); 67 | if (responseBusStation.statusCode == 200) { 68 | dom.Document document = parse(data); 69 | List aEliments = document.getElementsByTagName("a"); 70 | for (dom.Element e in aEliments) { 71 | print(e.text); 72 | print(e.attributes["data-seq"]); 73 | } 74 | } 75 | 76 | // 根据路线,方向,所在站点 获取实时公交情况 77 | var busOnlineUrl = 78 | '$getBusOLineUrl&selBLine=$busLine&selBDir=$busDir&selBStop=$busSelfStop'; 79 | var responseBusOnline = await http.get(busOnlineUrl); 80 | data = decoder.convert(responseBusOnline.bodyBytes); 81 | var buscList = []; //途中车辆 82 | var bussList = []; // 到站车辆 83 | if (responseBusOnline.statusCode == 200) { 84 | Map dataMap = json.decode(data); 85 | String htmlStr = dataMap['html']; 86 | dom.Document document = parse(htmlStr); 87 | var aEliments = document.getElementsByTagName("i"); 88 | for (dom.Element e in aEliments) { 89 | var classValue = e.attributes['class']; 90 | if (classValue != null) { 91 | if (classValue == 'busc') { 92 | //途中车辆 93 | dom.Element parent = e.parent; 94 | String parentId = parent.attributes['id']; 95 | parentId = parentId.substring(0, parentId.length - 1); 96 | buscList.add(int.parse(parentId)); 97 | } else if (classValue == 'buss') { 98 | // 到站车辆 99 | dom.Element parent = e.parent; 100 | bussList.add(int.parse(parent.attributes['id'])); 101 | } 102 | } 103 | } 104 | print("途中车辆buscList"); 105 | for (int index in buscList) { 106 | print(index); 107 | } 108 | print("到站车辆bussList"); 109 | for (int index in bussList) { 110 | print(index); 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // To perform an interaction with a widget in your test, use the WidgetTester utility that Flutter 3 | // provides. For example, you can send tap and scroll gestures. You can also use WidgetTester to 4 | // find child widgets in the widget tree, read text, and verify that the values of widget properties 5 | // are correct. 6 | 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter_test/flutter_test.dart'; 9 | 10 | import 'package:flutter_bingocode/main.dart'; 11 | 12 | void main() { 13 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 14 | // Build our app and trigger a frame. 15 | await tester.pumpWidget(new MyApp()); 16 | 17 | // Verify that our counter starts at 0. 18 | expect(find.text('0'), findsOneWidget); 19 | expect(find.text('1'), findsNothing); 20 | 21 | // Tap the '+' icon and trigger a frame. 22 | await tester.tap(find.byIcon(Icons.add)); 23 | await tester.pump(); 24 | 25 | // Verify that our counter has incremented. 26 | expect(find.text('0'), findsNothing); 27 | expect(find.text('1'), findsOneWidget); 28 | }); 29 | } 30 | --------------------------------------------------------------------------------