panhui 7 жил өмнө
commit
23aa526164
99 өөрчлөгдсөн 5206 нэмэгдсэн , 0 устгасан
  1. 71 0
      .gitignore
  2. 10 0
      .metadata
  3. 16 0
      README.md
  4. 61 0
      android/app/build.gradle
  5. 39 0
      android/app/src/main/AndroidManifest.xml
  6. 13 0
      android/app/src/main/java/com/example/electriccontest/MainActivity.java
  7. 12 0
      android/app/src/main/res/drawable/launch_background.xml
  8. BIN
      android/app/src/main/res/mipmap-hdpi/ic_launcher.png
  9. BIN
      android/app/src/main/res/mipmap-mdpi/ic_launcher.png
  10. BIN
      android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
  11. BIN
      android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
  12. BIN
      android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
  13. 8 0
      android/app/src/main/res/values/styles.xml
  14. 29 0
      android/build.gradle
  15. 1 0
      android/gradle.properties
  16. 6 0
      android/gradle/wrapper/gradle-wrapper.properties
  17. 15 0
      android/settings.gradle
  18. BIN
      images/dengji_icon_baiyin.png
  19. BIN
      images/dengji_icon_huangjin.png
  20. BIN
      images/dengji_icon_qingtong.png
  21. BIN
      images/home_icon_fangjian.png
  22. BIN
      images/home_icon_kuaisu.png
  23. BIN
      images/home_icon_shezhi.png
  24. BIN
      images/home_icon_sousuo.png
  25. BIN
      images/home_icon_wode.png
  26. BIN
      images/home_icon_youjian.png
  27. BIN
      images/home_icon_yuan.png
  28. BIN
      images/icon_bangding.png
  29. BIN
      images/icon_fenxiang.png
  30. BIN
      images/icon_inter.png
  31. BIN
      images/icon_jinbi_da_bai.png
  32. BIN
      images/icon_jinbi_da_hong.png
  33. BIN
      images/icon_jinbi_xiao_hong.png
  34. BIN
      images/icon_qianbao.png
  35. BIN
      images/icon_renshu.png
  36. BIN
      images/icon_zhanji.png
  37. BIN
      images/icon_zhankai_baise.png
  38. BIN
      images/icon_zhankai_hongse.png
  39. BIN
      images/img_wodeshouyi.png
  40. BIN
      images/list_icon_del.png
  41. BIN
      images/list_icon_shouji.png
  42. BIN
      images/list_icon_yanzhengma.png
  43. BIN
      images/nav_return_baise.png
  44. 26 0
      ios/Flutter/AppFrameworkInfo.plist
  45. 1 0
      ios/Flutter/Debug.xcconfig
  46. 1 0
      ios/Flutter/Release.xcconfig
  47. 510 0
      ios/Runner.xcodeproj/project.pbxproj
  48. 7 0
      ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  49. 93 0
      ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
  50. 7 0
      ios/Runner.xcworkspace/contents.xcworkspacedata
  51. 6 0
      ios/Runner/AppDelegate.h
  52. 13 0
      ios/Runner/AppDelegate.m
  53. 122 0
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
  54. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
  55. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
  56. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
  57. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
  58. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
  59. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
  60. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
  61. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
  62. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
  63. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
  64. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
  65. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
  66. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
  67. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
  68. BIN
      ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
  69. 23 0
      ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
  70. BIN
      ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
  71. BIN
      ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
  72. BIN
      ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
  73. 5 0
      ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
  74. 37 0
      ios/Runner/Base.lproj/LaunchScreen.storyboard
  75. 26 0
      ios/Runner/Base.lproj/Main.storyboard
  76. 45 0
      ios/Runner/Info.plist
  77. 9 0
      ios/Runner/main.m
  78. 89 0
      lib/gridview_demo.dart
  79. 29 0
      lib/main.dart
  80. 42 0
      lib/pages/Example.dart
  81. 533 0
      lib/pages/home.dart
  82. 123 0
      lib/pages/loginFirst.dart
  83. 200 0
      lib/pages/loginSecond.dart
  84. 324 0
      lib/pages/myWallet.dart
  85. 45 0
      lib/pages/openRoom.dart
  86. 198 0
      lib/pages/recharge.dart
  87. 388 0
      lib/pages/roomInfo.dart
  88. 195 0
      lib/pages/roomList.dart
  89. 194 0
      lib/pages/setting.dart
  90. 17 0
      lib/state.dart
  91. 18 0
      lib/styles/api.dart
  92. 14 0
      lib/styles/colors.dart
  93. 214 0
      lib/styles/totast.dart
  94. 153 0
      lib/widget/ITextInput.dart
  95. 50 0
      lib/widget/indicator_factory.dart
  96. 944 0
      lib/widget/popupButton_my.dart
  97. 138 0
      lib/widget/room_item.dart
  98. 56 0
      pubspec.yaml
  99. 30 0
      test/widget_test.dart

+ 71 - 0
.gitignore

@@ -0,0 +1,71 @@
+# Miscellaneous
+*.class
+*.lock
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# Visual Studio Code related
+.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+.dart_tool/
+.flutter-plugins
+.packages
+.pub-cache/
+.pub/
+build/
+
+# Android related
+**/android/**/gradle-wrapper.jar
+**/android/.gradle
+**/android/captures/
+**/android/gradlew
+**/android/gradlew.bat
+**/android/local.properties
+**/android/**/GeneratedPluginRegistrant.java
+
+# iOS/XCode related
+**/ios/**/*.mode1v3
+**/ios/**/*.mode2v3
+**/ios/**/*.moved-aside
+**/ios/**/*.pbxuser
+**/ios/**/*.perspectivev3
+**/ios/**/*sync/
+**/ios/**/.sconsign.dblite
+**/ios/**/.tags*
+**/ios/**/.vagrant/
+**/ios/**/DerivedData/
+**/ios/**/Icon?
+**/ios/**/Pods/
+**/ios/**/.symlinks/
+**/ios/**/profile
+**/ios/**/xcuserdata
+**/ios/.generated/
+**/ios/Flutter/App.framework
+**/ios/Flutter/Flutter.framework
+**/ios/Flutter/Generated.xcconfig
+**/ios/Flutter/app.flx
+**/ios/Flutter/app.zip
+**/ios/Flutter/flutter_assets/
+**/ios/ServiceDefinitions.json
+**/ios/Runner/GeneratedPluginRegistrant.*
+
+# Exceptions to above rules.
+!**/ios/**/default.mode1v3
+!**/ios/**/default.mode2v3
+!**/ios/**/default.pbxuser
+!**/ios/**/default.perspectivev3
+!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages

+ 10 - 0
.metadata

@@ -0,0 +1,10 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+  revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b
+  channel: beta
+
+project_type: app

+ 16 - 0
README.md

@@ -0,0 +1,16 @@
+# electric_contest
+
+A new Flutter project.
+
+## Getting Started
+
+This project is a starting point for a Flutter application.
+
+A few resources to get you started if this is your first Flutter project:
+
+- [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab)
+- [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook)
+
+For help getting started with Flutter, view our 
+[online documentation](https://flutter.io/docs), which offers tutorials, 
+samples, guidance on mobile development, and a full API reference.

+ 61 - 0
android/app/build.gradle

@@ -0,0 +1,61 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+    localPropertiesFile.withReader('UTF-8') { reader ->
+        localProperties.load(reader)
+    }
+}
+
+def flutterRoot = localProperties.getProperty('flutter.sdk')
+if (flutterRoot == null) {
+    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+    flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+    flutterVersionName = '1.0'
+}
+
+apply plugin: 'com.android.application'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+    compileSdkVersion 27
+
+    lintOptions {
+        disable 'InvalidPackage'
+    }
+
+    defaultConfig {
+        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+        applicationId "com.example.electriccontest"
+        minSdkVersion 16
+        targetSdkVersion 27
+        versionCode flutterVersionCode.toInteger()
+        versionName flutterVersionName
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+    }
+
+    buildTypes {
+        release {
+            // TODO: Add your own signing config for the release build.
+            // Signing with the debug keys for now, so `flutter run --release` works.
+            signingConfig signingConfigs.debug
+        }
+    }
+}
+
+flutter {
+    source '../..'
+}
+
+dependencies {
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'com.android.support.test:runner:1.0.2'
+    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+}

+ 39 - 0
android/app/src/main/AndroidManifest.xml

@@ -0,0 +1,39 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.electriccontest">
+
+    <!-- The INTERNET permission is required for development. Specifically,
+         flutter needs it to communicate with the running application
+         to allow setting breakpoints, to provide hot reload, etc.
+    -->
+    <uses-permission android:name="android.permission.INTERNET"/>
+
+    <!-- io.flutter.app.FlutterApplication is an android.app.Application that
+         calls FlutterMain.startInitialization(this); in its onCreate method.
+         In most cases you can leave this as-is, but you if you want to provide
+         additional functionality it is fine to subclass or reimplement
+         FlutterApplication and put your custom class here. -->
+    <application
+        android:name="io.flutter.app.FlutterApplication"
+        android:label="electric_contest"
+        android:icon="@mipmap/ic_launcher">
+        <activity
+            android:name=".MainActivity"
+            android:launchMode="singleTop"
+            android:theme="@style/LaunchTheme"
+            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
+            android:hardwareAccelerated="true"
+            android:windowSoftInputMode="adjustResize">
+            <!-- This keeps the window background of the activity showing
+                 until Flutter renders its first frame. It can be removed if
+                 there is no splash screen (such as the default splash screen
+                 defined in @style/LaunchTheme). -->
+            <meta-data
+                android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
+                android:value="true" />
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>

+ 13 - 0
android/app/src/main/java/com/example/electriccontest/MainActivity.java

@@ -0,0 +1,13 @@
+package com.example.electriccontest;
+
+import android.os.Bundle;
+import io.flutter.app.FlutterActivity;
+import io.flutter.plugins.GeneratedPluginRegistrant;
+
+public class MainActivity extends FlutterActivity {
+  @Override
+  protected void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    GeneratedPluginRegistrant.registerWith(this);
+  }
+}

+ 12 - 0
android/app/src/main/res/drawable/launch_background.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@android:color/white" />
+
+    <!-- You can insert your own image assets here -->
+    <!-- <item>
+        <bitmap
+            android:gravity="center"
+            android:src="@mipmap/launch_image" />
+    </item> -->
+</layer-list>

BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher.png


BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher.png


BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher.png


BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png


BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png


+ 8 - 0
android/app/src/main/res/values/styles.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
+        <!-- Show a splash screen on the activity. Automatically removed when
+             Flutter draws its first frame -->
+        <item name="android:windowBackground">@drawable/launch_background</item>
+    </style>
+</resources>

+ 29 - 0
android/build.gradle

@@ -0,0 +1,29 @@
+buildscript {
+    repositories {
+        google()
+        jcenter()
+    }
+
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.2.1'
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        jcenter()
+    }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+    project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+    project.evaluationDependsOn(':app')
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}

+ 1 - 0
android/gradle.properties

@@ -0,0 +1 @@
+org.gradle.jvmargs=-Xmx1536M

+ 6 - 0
android/gradle/wrapper/gradle-wrapper.properties

@@ -0,0 +1,6 @@
+#Fri Jun 23 08:50:38 CEST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip

+ 15 - 0
android/settings.gradle

@@ -0,0 +1,15 @@
+include ':app'
+
+def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
+
+def plugins = new Properties()
+def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
+if (pluginsFile.exists()) {
+    pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
+}
+
+plugins.each { name, path ->
+    def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
+    include ":$name"
+    project(":$name").projectDir = pluginDirectory
+}

BIN
images/dengji_icon_baiyin.png


BIN
images/dengji_icon_huangjin.png


BIN
images/dengji_icon_qingtong.png


BIN
images/home_icon_fangjian.png


BIN
images/home_icon_kuaisu.png


BIN
images/home_icon_shezhi.png


BIN
images/home_icon_sousuo.png


BIN
images/home_icon_wode.png


BIN
images/home_icon_youjian.png


BIN
images/home_icon_yuan.png


BIN
images/icon_bangding.png


BIN
images/icon_fenxiang.png


BIN
images/icon_inter.png


BIN
images/icon_jinbi_da_bai.png


BIN
images/icon_jinbi_da_hong.png


BIN
images/icon_jinbi_xiao_hong.png


BIN
images/icon_qianbao.png


BIN
images/icon_renshu.png


BIN
images/icon_zhanji.png


BIN
images/icon_zhankai_baise.png


BIN
images/icon_zhankai_hongse.png


BIN
images/img_wodeshouyi.png


BIN
images/list_icon_del.png


BIN
images/list_icon_shouji.png


BIN
images/list_icon_yanzhengma.png


BIN
images/nav_return_baise.png


+ 26 - 0
ios/Flutter/AppFrameworkInfo.plist

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>en</string>
+  <key>CFBundleExecutable</key>
+  <string>App</string>
+  <key>CFBundleIdentifier</key>
+  <string>io.flutter.flutter.app</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>App</string>
+  <key>CFBundlePackageType</key>
+  <string>FMWK</string>
+  <key>CFBundleShortVersionString</key>
+  <string>1.0</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>1.0</string>
+  <key>MinimumOSVersion</key>
+  <string>8.0</string>
+</dict>
+</plist>

+ 1 - 0
ios/Flutter/Debug.xcconfig

@@ -0,0 +1 @@
+#include "Generated.xcconfig"

+ 1 - 0
ios/Flutter/Release.xcconfig

@@ -0,0 +1 @@
+#include "Generated.xcconfig"

+ 510 - 0
ios/Runner.xcodeproj/project.pbxproj

@@ -0,0 +1,510 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
+		2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; };
+		3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
+		3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
+		3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+		9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
+		9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+		9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
+		978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
+		97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
+		97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
+		97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
+		97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		9705A1C41CF9048500538489 /* Embed Frameworks */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 10;
+			files = (
+				3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
+				9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
+			);
+			name = "Embed Frameworks";
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+		1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
+		1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
+		2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; };
+		3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
+		3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
+		7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
+		7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
+		7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
+		9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
+		9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
+		9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = "<group>"; };
+		97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+		97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
+		97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+		97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
+		97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		97C146EB1CF9000F007C117D /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
+				3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		9740EEB11CF90186004384FC /* Flutter */ = {
+			isa = PBXGroup;
+			children = (
+				2D5378251FAA1A9400D5DBA9 /* flutter_assets */,
+				3B80C3931E831B6300D905FE /* App.framework */,
+				3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
+				9740EEBA1CF902C7004384FC /* Flutter.framework */,
+				9740EEB21CF90195004384FC /* Debug.xcconfig */,
+				7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
+				9740EEB31CF90195004384FC /* Generated.xcconfig */,
+			);
+			name = Flutter;
+			sourceTree = "<group>";
+		};
+		97C146E51CF9000F007C117D = {
+			isa = PBXGroup;
+			children = (
+				9740EEB11CF90186004384FC /* Flutter */,
+				97C146F01CF9000F007C117D /* Runner */,
+				97C146EF1CF9000F007C117D /* Products */,
+				CF3B75C9A7D2FA2A4C99F110 /* Frameworks */,
+			);
+			sourceTree = "<group>";
+		};
+		97C146EF1CF9000F007C117D /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				97C146EE1CF9000F007C117D /* Runner.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		97C146F01CF9000F007C117D /* Runner */ = {
+			isa = PBXGroup;
+			children = (
+				7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
+				7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
+				97C146FA1CF9000F007C117D /* Main.storyboard */,
+				97C146FD1CF9000F007C117D /* Assets.xcassets */,
+				97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
+				97C147021CF9000F007C117D /* Info.plist */,
+				97C146F11CF9000F007C117D /* Supporting Files */,
+				1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
+				1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
+			);
+			path = Runner;
+			sourceTree = "<group>";
+		};
+		97C146F11CF9000F007C117D /* Supporting Files */ = {
+			isa = PBXGroup;
+			children = (
+				97C146F21CF9000F007C117D /* main.m */,
+			);
+			name = "Supporting Files";
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		97C146ED1CF9000F007C117D /* Runner */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
+			buildPhases = (
+				9740EEB61CF901F6004384FC /* Run Script */,
+				97C146EA1CF9000F007C117D /* Sources */,
+				97C146EB1CF9000F007C117D /* Frameworks */,
+				97C146EC1CF9000F007C117D /* Resources */,
+				9705A1C41CF9048500538489 /* Embed Frameworks */,
+				3B06AD1E1E4923F5004D2608 /* Thin Binary */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = Runner;
+			productName = Runner;
+			productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		97C146E61CF9000F007C117D /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0910;
+				ORGANIZATIONNAME = "The Chromium Authors";
+				TargetAttributes = {
+					97C146ED1CF9000F007C117D = {
+						CreatedOnToolsVersion = 7.3.1;
+					};
+				};
+			};
+			buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = 97C146E51CF9000F007C117D;
+			productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				97C146ED1CF9000F007C117D /* Runner */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		97C146EC1CF9000F007C117D /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
+				3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
+				9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
+				97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
+				2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */,
+				97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "Thin Binary";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
+		};
+		9740EEB61CF901F6004384FC /* Run Script */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "Run Script";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		97C146EA1CF9000F007C117D /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
+				97C146F31CF9000F007C117D /* main.m in Sources */,
+				1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		97C146FA1CF9000F007C117D /* Main.storyboard */ = {
+			isa = PBXVariantGroup;
+			children = (
+				97C146FB1CF9000F007C117D /* Base */,
+			);
+			name = Main.storyboard;
+			sourceTree = "<group>";
+		};
+		97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
+			isa = PBXVariantGroup;
+			children = (
+				97C147001CF9000F007C117D /* Base */,
+			);
+			name = LaunchScreen.storyboard;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		249021D3217E4FDB00AE95B9 /* Profile */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				SDKROOT = iphoneos;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Profile;
+		};
+		249021D4217E4FDB00AE95B9 /* Profile */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+				DEVELOPMENT_TEAM = S8QB4VV633;
+				ENABLE_BITCODE = NO;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(PROJECT_DIR)/Flutter",
+				);
+				INFOPLIST_FILE = Runner/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(PROJECT_DIR)/Flutter",
+				);
+				PRODUCT_BUNDLE_IDENTIFIER = com.example.electricContest;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				VERSIONING_SYSTEM = "apple-generic";
+			};
+			name = Profile;
+		};
+		97C147031CF9000F007C117D /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = iphoneos;
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Debug;
+		};
+		97C147041CF9000F007C117D /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				SDKROOT = iphoneos;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		97C147061CF9000F007C117D /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+				ENABLE_BITCODE = NO;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(PROJECT_DIR)/Flutter",
+				);
+				INFOPLIST_FILE = Runner/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(PROJECT_DIR)/Flutter",
+				);
+				PRODUCT_BUNDLE_IDENTIFIER = com.example.electricContest;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				VERSIONING_SYSTEM = "apple-generic";
+			};
+			name = Debug;
+		};
+		97C147071CF9000F007C117D /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+				ENABLE_BITCODE = NO;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(PROJECT_DIR)/Flutter",
+				);
+				INFOPLIST_FILE = Runner/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(PROJECT_DIR)/Flutter",
+				);
+				PRODUCT_BUNDLE_IDENTIFIER = com.example.electricContest;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				VERSIONING_SYSTEM = "apple-generic";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				97C147031CF9000F007C117D /* Debug */,
+				97C147041CF9000F007C117D /* Release */,
+				249021D3217E4FDB00AE95B9 /* Profile */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				97C147061CF9000F007C117D /* Debug */,
+				97C147071CF9000F007C117D /* Release */,
+				249021D4217E4FDB00AE95B9 /* Profile */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 97C146E61CF9000F007C117D /* Project object */;
+}

+ 7 - 0
ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "group:Runner.xcodeproj">
+   </FileRef>
+</Workspace>

+ 93 - 0
ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme

@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0910"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "97C146ED1CF9000F007C117D"
+               BuildableName = "Runner.app"
+               BlueprintName = "Runner"
+               ReferencedContainer = "container:Runner.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      language = ""
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
+            BuildableName = "Runner.app"
+            BlueprintName = "Runner"
+            ReferencedContainer = "container:Runner.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      language = ""
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
+            BuildableName = "Runner.app"
+            BlueprintName = "Runner"
+            ReferencedContainer = "container:Runner.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Profile"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
+            BuildableName = "Runner.app"
+            BlueprintName = "Runner"
+            ReferencedContainer = "container:Runner.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 7 - 0
ios/Runner.xcworkspace/contents.xcworkspacedata

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "group:Runner.xcodeproj">
+   </FileRef>
+</Workspace>

+ 6 - 0
ios/Runner/AppDelegate.h

@@ -0,0 +1,6 @@
+#import <Flutter/Flutter.h>
+#import <UIKit/UIKit.h>
+
+@interface AppDelegate : FlutterAppDelegate
+
+@end

+ 13 - 0
ios/Runner/AppDelegate.m

@@ -0,0 +1,13 @@
+#include "AppDelegate.h"
+#include "GeneratedPluginRegistrant.h"
+
+@implementation AppDelegate
+
+- (BOOL)application:(UIApplication *)application
+    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+  [GeneratedPluginRegistrant registerWithRegistry:self];
+  // Override point for customization after application launch.
+  return [super application:application didFinishLaunchingWithOptions:launchOptions];
+}
+
+@end

+ 122 - 0
ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json

@@ -0,0 +1,122 @@
+{
+  "images" : [
+    {
+      "size" : "20x20",
+      "idiom" : "iphone",
+      "filename" : "Icon-App-20x20@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "20x20",
+      "idiom" : "iphone",
+      "filename" : "Icon-App-20x20@3x.png",
+      "scale" : "3x"
+    },
+    {
+      "size" : "29x29",
+      "idiom" : "iphone",
+      "filename" : "Icon-App-29x29@1x.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "29x29",
+      "idiom" : "iphone",
+      "filename" : "Icon-App-29x29@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "29x29",
+      "idiom" : "iphone",
+      "filename" : "Icon-App-29x29@3x.png",
+      "scale" : "3x"
+    },
+    {
+      "size" : "40x40",
+      "idiom" : "iphone",
+      "filename" : "Icon-App-40x40@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "40x40",
+      "idiom" : "iphone",
+      "filename" : "Icon-App-40x40@3x.png",
+      "scale" : "3x"
+    },
+    {
+      "size" : "60x60",
+      "idiom" : "iphone",
+      "filename" : "Icon-App-60x60@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "60x60",
+      "idiom" : "iphone",
+      "filename" : "Icon-App-60x60@3x.png",
+      "scale" : "3x"
+    },
+    {
+      "size" : "20x20",
+      "idiom" : "ipad",
+      "filename" : "Icon-App-20x20@1x.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "20x20",
+      "idiom" : "ipad",
+      "filename" : "Icon-App-20x20@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "29x29",
+      "idiom" : "ipad",
+      "filename" : "Icon-App-29x29@1x.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "29x29",
+      "idiom" : "ipad",
+      "filename" : "Icon-App-29x29@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "40x40",
+      "idiom" : "ipad",
+      "filename" : "Icon-App-40x40@1x.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "40x40",
+      "idiom" : "ipad",
+      "filename" : "Icon-App-40x40@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "76x76",
+      "idiom" : "ipad",
+      "filename" : "Icon-App-76x76@1x.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "76x76",
+      "idiom" : "ipad",
+      "filename" : "Icon-App-76x76@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "83.5x83.5",
+      "idiom" : "ipad",
+      "filename" : "Icon-App-83.5x83.5@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "1024x1024",
+      "idiom" : "ios-marketing",
+      "filename" : "Icon-App-1024x1024@1x.png",
+      "scale" : "1x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png


BIN
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png


+ 23 - 0
ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json

@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "LaunchImage.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "LaunchImage@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "LaunchImage@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

BIN
ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png


BIN
ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png


BIN
ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png


+ 5 - 0
ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md

@@ -0,0 +1,5 @@
+# Launch Screen Assets
+
+You can customize the launch screen with your own desired assets by replacing the image files in this directory.
+
+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.

+ 37 - 0
ios/Runner/Base.lproj/LaunchScreen.storyboard

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="EHf-IW-A2E">
+            <objects>
+                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
+                        <viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
+                            </imageView>
+                        </subviews>
+                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                        <constraints>
+                            <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
+                            <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
+                        </constraints>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="53" y="375"/>
+        </scene>
+    </scenes>
+    <resources>
+        <image name="LaunchImage" width="168" height="185"/>
+    </resources>
+</document>

+ 26 - 0
ios/Runner/Base.lproj/Main.storyboard

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
+    </dependencies>
+    <scenes>
+        <!--Flutter View Controller-->
+        <scene sceneID="tne-QT-ifu">
+            <objects>
+                <viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
+                        <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
+                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
+            </objects>
+        </scene>
+    </scenes>
+</document>

+ 45 - 0
ios/Runner/Info.plist

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>electric_contest</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>$(FLUTTER_BUILD_NAME)</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>$(FLUTTER_BUILD_NUMBER)</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+	<key>UILaunchStoryboardName</key>
+	<string>LaunchScreen</string>
+	<key>UIMainStoryboardFile</key>
+	<string>Main</string>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+	<key>UISupportedInterfaceOrientations~ipad</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+	<key>UIViewControllerBasedStatusBarAppearance</key>
+	<false/>
+</dict>
+</plist>

+ 9 - 0
ios/Runner/main.m

@@ -0,0 +1,9 @@
+#import <Flutter/Flutter.h>
+#import <UIKit/UIKit.h>
+#import "AppDelegate.h"
+
+int main(int argc, char* argv[]) {
+  @autoreleasepool {
+    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+  }
+}

+ 89 - 0
lib/gridview_demo.dart

@@ -0,0 +1,89 @@
+import 'package:flutter/material.dart';
+
+import 'package:http/http.dart' as http;
+import 'dart:convert';
+import 'dart:async';
+
+class MyHomePage extends StatefulWidget {
+  @override
+  _MyHomePageState createState() => _MyHomePageState();
+}
+
+class _MyHomePageState extends State<MyHomePage> {
+  ScrollController _controller;
+  List<String> images;
+
+  @override
+  void initState() {
+    super.initState();
+    images = List();
+    _controller = ScrollController();
+    fetchTen();
+    _controller.addListener(() {
+      if (_controller.position.pixels == _controller.position.maxScrollExtent) {
+        fetchTen();
+      }
+    });
+  }
+
+  @override
+  void dispose() {
+    super.dispose();
+    _controller.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(
+        title: Text('pull to loading demo'),
+      ),
+      body: RefreshIndicator(
+        onRefresh: () async {
+          await new Future.delayed(const Duration(seconds: 1));
+          images.clear();
+          fetchTen();
+        },
+        child: GridView.builder(
+          gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
+              crossAxisCount: 2,
+              mainAxisSpacing: 10.0,
+              crossAxisSpacing: 10.0,
+              childAspectRatio: 1.0),
+          controller: _controller,
+          itemCount: images.length,
+          itemBuilder: (BuildContext context, int index){
+            return _buildItem(images[index]);
+          },
+        ),
+      ),
+    );
+  }
+
+  Widget _buildItem(String url){
+    return Container(
+      constraints: BoxConstraints.tightFor(height: 150.0),
+      child: Image.network(
+        url,
+        fit: BoxFit.cover,
+      ),
+    );
+  }
+
+  fetch() async {
+    final response = await http.get('http://dog.ceo/api/breeds/image/random');
+    if (response.statusCode == 200) {
+      setState(() {
+        images.add(json.decode(response.body)['message'],);
+      });
+    } else {
+      throw Exception('Failed to load images');
+    }
+  }
+
+  fetchTen() {
+    for (int i = 0; i < 10; i++) {
+      fetch();
+    }
+  }
+}

+ 29 - 0
lib/main.dart

@@ -0,0 +1,29 @@
+/**
+ * 分别通过切换import中的注释来查看三个页面。
+ * 建议分开阅读,下拉刷新和上拉加载的实现方式
+ */
+import 'package:flutter/material.dart';
+import 'package:flutter_redux/flutter_redux.dart';
+import 'package:redux/redux.dart';
+import 'pages/home.dart';
+import 'state.dart';
+
+
+
+CountState updateState(CountState state, dynamic value){
+  print(value);
+ if(value.action==Actions.updateToken){
+  return CountState(state.usetoken=value);
+ }
+ else if(value.action==Actions.updateUser){
+   return CountState(state.userInfo=value);
+ }
+ return state;
+
+}
+
+void main(){
+   final store =
+      Store<CountState>(updateState, initialState: CountState.initState());
+   runApp(new MyApp(store));
+}

+ 42 - 0
lib/pages/Example.dart

@@ -0,0 +1,42 @@
+import 'package:flutter/material.dart';
+import '../styles/colors.dart';
+import 'dart:ui';
+import '../styles/totast.dart';
+
+class Rechrage extends StatefulWidget {
+  @override
+  RechrageState createState() => RechrageState();
+}
+
+class RechrageState extends State<Rechrage> {
+  @override
+  Widget build(BuildContext context) {
+
+
+    return new WillPopScope(
+        child: Scaffold(
+        appBar: AppBar(
+          backgroundColor: PRIMARY_COLOR,
+          title: Text('充值'),
+          centerTitle: true,
+          elevation:0,
+        ),
+        body: RefreshIndicator(
+          color: PRIMARY_COLOR,
+          backgroundColor: BG_COLOR,
+          onRefresh: () async {
+            await new Future.delayed(const Duration(seconds: 1));
+            
+          },
+          child: Container(
+            color: BG_COLOR,
+          ),
+        )),
+        onWillPop: () {
+          Toast.hide();
+          print("返回键点击了");
+          Navigator.pop(context);
+        });
+ 
+  }
+}

+ 533 - 0
lib/pages/home.dart

@@ -0,0 +1,533 @@
+import 'package:flutter/material.dart';
+import '../styles/colors.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:dio/dio.dart';
+import '../styles/api.dart';
+import 'dart:convert';
+import 'dart:async';
+import 'dart:ui';
+import 'loginFirst.dart'; //登录
+import 'myWallet.dart'; //我的钱包
+import 'roomList.dart'; //房间列表
+import 'openRoom.dart'; //创建房间
+import 'setting.dart'; //系统设置
+import 'package:flutter_swiper/flutter_swiper.dart';
+import 'package:redux/redux.dart';
+import 'package:flutter_redux/flutter_redux.dart';
+import '../state.dart';
+
+class MyApp extends StatelessWidget {
+  final Store<CountState> store;
+
+  MyApp(this.store);
+  @override
+  Widget build(BuildContext context) {
+    return StoreProvider<CountState>(
+      store: store,
+      child: new MaterialApp(
+        title: '全民电竞',
+        theme: ThemeData(
+          primaryColor: Color(0xFFC2524D),
+          buttonColor: Color(0xFFC2524D),
+          highlightColor: Color(0xFF933E3E),
+          accentColor: Color(0xFFC2524D),
+        ),
+        home: WillPopScope(
+            child: new MyHomePage(),
+            onWillPop: () {
+              print("返回键点击了");
+              // Navigator.pop(context);
+            }),
+      ),
+    );
+  }
+}
+
+bool showBox = false;
+
+class MyHomePage extends StatefulWidget {
+  @override
+  _MyHomePageState createState() => _MyHomePageState();
+}
+
+class _MyHomePageState extends State<MyHomePage> {
+  List<Map> tabList = [
+    {"title": "创建房间", "icon": "images/home_icon_fangjian.png", "isDown": false},
+    {"title": "快速进入", "icon": "images/home_icon_kuaisu.png", "isDown": false},
+    {"title": "搜索", "icon": "images/home_icon_sousuo.png", "isDown": false},
+    {"title": "邮件", "icon": "images/home_icon_youjian.png", "isDown": false}
+  ];
+  Map userInfo;
+  String allToken = '';
+
+  @override
+  void initState() {
+    super.initState();
+    userInfo = {};
+   Future.delayed(Duration(seconds: 1),(){
+     print('开始');
+       allToken = StoreProvider.of<CountState>(context).state.usetoken;
+    getUserInfo();
+   });
+  }
+
+ 
+
+  @override
+  void dispose() {
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    ScreenUtil.instance = ScreenUtil(width: 375, height: 667)..init(context);
+    return Scaffold(
+        drawer: _userPage(context),
+        body: Stack(
+          children: <Widget>[
+            RefreshIndicator(
+              color: PRIMARY_COLOR,
+              backgroundColor: BG_COLOR,
+              onRefresh: () async {
+                await new Future.delayed(const Duration(seconds: 1));
+                print(StoreProvider.of<CountState>(context).state.usetoken);
+                allToken = StoreProvider.of<CountState>(context).state.usetoken;
+                getUserInfo();
+              },
+              child: Container(
+                color: BG_COLOR,
+                child: CustomScrollView(
+                  slivers: <Widget>[
+                    _sliverAppBar(context),
+                    _sliverToBoxAdapter(),
+                    _myGride()
+                  ],
+                ),
+              ),
+            ),
+            _popupBox(context)
+          ],
+        ));
+  }
+
+  Widget _sliverAppBar(BuildContext context) {
+    return Builder(builder: (BuildContext context) {
+      return SliverAppBar(
+        backgroundColor: PRIMARY_COLOR,
+        pinned: true,
+        leading: Container(
+          width: 24,
+          height: 24,
+          margin: EdgeInsets.all(15),
+          child: GestureDetector(
+            onTap: () {
+              Scaffold.of(context).openDrawer();
+            },
+            child: Image(
+              image: AssetImage("images/home_icon_wode.png"),
+              width: 24,
+            ),
+          ),
+        ),
+        actions: <Widget>[
+          GestureDetector(
+            child: Container(
+                margin: EdgeInsets.only(right: 15),
+                child: Image(
+                  image: AssetImage("images/home_icon_shezhi.png"),
+                  width: 24,
+                )),
+            onTap: () {
+              print('系统设置');
+              Navigator.push(context,
+                  new CupertinoPageRoute(builder: (context) => new Setting()));
+            },
+          )
+        ],
+      );
+    });
+  }
+
+  Widget _sliverToBoxAdapter() {
+    return SliverToBoxAdapter(
+      child: _myTop(),
+    );
+  }
+
+  Widget _myTop() {
+    var _topHeight = window.physicalSize.height / window.devicePixelRatio -
+        56 -
+        ScreenUtil().setWidth(167) * 2 -
+        MediaQueryData.fromWindow(window).padding.top;
+    if (_topHeight < 248) {
+      _topHeight = 248;
+    }
+    const subTitleStyle = TextStyle(
+      color: Colors.white,
+      fontSize: 14,
+    );
+    return Container(
+        height: _topHeight,
+        decoration: BoxDecoration(
+            //背景装饰
+            gradient: LinearGradient(
+          begin: Alignment.bottomRight,
+          colors: [SUB_COLOR, PRIMARY_COLOR],
+        )),
+        child: Swiper(
+          itemBuilder: (BuildContext context, int index) {
+            return Column(
+              mainAxisAlignment: MainAxisAlignment.center,
+              children: <Widget>[
+                Container(
+                    width: 214,
+                    height: 214,
+                    decoration: BoxDecoration(
+                        image: DecorationImage(
+                            image: AssetImage("images/home_icon_yuan.png"),
+                            fit: BoxFit.contain)),
+                    child: Container(
+                        padding: EdgeInsets.only(top: 20),
+                        child: Column(
+                          mainAxisAlignment: MainAxisAlignment.center,
+                          children: <Widget>[
+                            Row(
+                              mainAxisAlignment: MainAxisAlignment.center,
+                              crossAxisAlignment: CrossAxisAlignment.end,
+                              children: <Widget>[
+                                Text('568',
+                                    style: TextStyle(
+                                        color: Colors.white,
+                                        fontSize: 68,
+                                        fontWeight: FontWeight.w700,
+                                        letterSpacing: 0.2)),
+                                Container(
+                                  padding: EdgeInsets.only(bottom: 10),
+                                  child: Text('K',
+                                      style: TextStyle(
+                                          color: Colors.white,
+                                          fontSize: 36,
+                                          fontWeight: FontWeight.w700)),
+                                )
+                              ],
+                            ),
+                            Container(
+                                margin: EdgeInsets.only(bottom: 2),
+                                child: Text('当前排名',
+                                    style: TextStyle(
+                                        color: Colors.white, fontSize: 13))),
+                            Text('98686',
+                                style: TextStyle(
+                                    color: Colors.white, fontSize: 13))
+                          ],
+                        ))),
+                Text('赛季奖金', style: subTitleStyle),
+                Container(
+                  padding: EdgeInsets.only(bottom: 20),
+                  child: Text('刺激战场之大逃杀$index', style: subTitleStyle),
+                ),
+              ],
+            );
+          },
+          itemCount: 3,
+          scrollDirection: Axis.horizontal,
+          loop: false,
+          onTap: (index) => print('点击了第$index个'),
+        ));
+  }
+
+  Widget _myGride() {
+    return SliverGrid(
+      gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
+        maxCrossAxisExtent: 180,
+        childAspectRatio: 1.12,
+        crossAxisSpacing: 2,
+      ),
+      delegate: SliverChildBuilderDelegate(
+        (BuildContext context, int index) {
+          return GestureDetector(
+            child: Container(
+              alignment: Alignment.center,
+              decoration: BoxDecoration(
+                  //背景装饰
+                  gradient: LinearGradient(
+                begin: Alignment.bottomRight,
+                colors: tabList[index]["isDown"]
+                    ? [
+                        Color(0xFF3D3E6C).withOpacity(0.3),
+                        Color(0xFF626C85).withOpacity(0.3)
+                      ]
+                    : [Color(0xFF3D3E6C), Color(0xFF555B75)],
+              )),
+              child: Column(
+                mainAxisAlignment: MainAxisAlignment.center,
+                children: <Widget>[
+                  Image(
+                    image: AssetImage(tabList[index]["icon"]),
+                    width: 44,
+                  ),
+                  Text(tabList[index]["title"],
+                      style: TextStyle(
+                        color: Colors.white,
+                        fontSize: 14,
+                        fontWeight: FontWeight.w400,
+                      )),
+                ],
+              ),
+            ),
+            onLongPress: null,
+            onTap: () {
+              print(tabList[index]["title"]);
+              if (tabList[index]["title"] == '快速进入') {
+                Navigator.push(
+                    context,
+                    new CupertinoPageRoute(
+                        builder: (context) => new RoomList()));
+              } else if (tabList[index]["title"] == '创建房间') {
+                setState(() {
+                  showBox = true;
+                });
+              }
+            },
+            onTapDown: (e) {
+              setState(() {
+                tabList[index]["isDown"] = true;
+              });
+            },
+            onTapUp: (e) {
+              setState(() {
+                tabList[index]["isDown"] = false;
+              });
+            },
+          );
+        },
+        childCount: 4,
+      ),
+    );
+  }
+
+  Widget _userPage(BuildContext context) {
+    return Builder(builder: (BuildContext context) {
+      return Drawer(
+        child: Container(
+          width: ScreenUtil().setWidth(280),
+          decoration: BoxDecoration(
+              //背景装饰
+              gradient: LinearGradient(
+            begin: Alignment.bottomRight,
+            colors: [Color(0xFF3D3E6C), Color(0xFF626C85)],
+          )),
+          child: Column(
+            children: <Widget>[
+              Container(
+                padding: EdgeInsets.only(
+                    left: 35,
+                    bottom: 50,
+                    top: 50 + MediaQueryData.fromWindow(window).padding.top),
+                margin: EdgeInsets.only(bottom: 10),
+                decoration: BoxDecoration(
+                  color: Color(0xFF303341),
+                ),
+                child: Row(
+                  children: <Widget>[
+                    Container(
+                      margin: EdgeInsets.only(right: 8),
+                      width: 86.0,
+                      height: 86.0,
+                      child: CircleAvatar(
+                        backgroundImage: NetworkImage(
+                            'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=2884107401,3797902000&fm=27&gp=0.jpg'),
+                      ),
+                    ),
+                    Column(
+                      mainAxisAlignment: MainAxisAlignment.center,
+                      crossAxisAlignment: CrossAxisAlignment.center,
+                      children: <Widget>[
+                        Container(
+                          padding: EdgeInsets.only(bottom: 3),
+                          child: Text('粉条',
+                              style: TextStyle(
+                                  fontSize: 27,
+                                  fontWeight: FontWeight.w500,
+                                  color: Colors.white)),
+                        ),
+                        Row(
+                          children: <Widget>[
+                            Container(
+                              padding: EdgeInsets.only(right: 4, left: 10),
+                              child: Image(
+                                image:
+                                    AssetImage('images/icon_jinbi_da_bai.png'),
+                                width: 20,
+                              ),
+                            ),
+                            Text('5324',
+                                style: TextStyle(
+                                    fontSize: 16,
+                                    fontWeight: FontWeight.w900,
+                                    color: Colors.white))
+                          ],
+                        )
+                      ],
+                    )
+                  ],
+                ),
+              ),
+              Container(
+                padding: EdgeInsets.only(left: 30, right: 30),
+                child: Column(
+                  children: <Widget>[
+                    _userListItem(context, "我的钱包", true,
+                        'images/icon_qianbao.png', 'wallet'),
+                    _userListItem(context, "我的战绩", true,
+                        'images/icon_zhanji.png', 'score'),
+                    _userListItem(context, "游戏绑定", false,
+                        'images/icon_bangding.png', 'bind'),
+                  ],
+                ),
+              )
+            ],
+          ),
+        ),
+      );
+    });
+  }
+
+  Widget _userListItem(BuildContext context, String title, bool hasBorder,
+      String icon, String myType) {
+    return Builder(builder: (BuildContext context) {
+      return GestureDetector(
+          child: Container(
+            decoration: hasBorder
+                ? BoxDecoration(
+                    border: BorderDirectional(
+                        bottom: BorderSide(
+                            color: BG_COLOR,
+                            width: 1,
+                            style: BorderStyle.solid)))
+                : BoxDecoration(),
+            height: 70,
+            child: Row(
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: <Widget>[
+                Image(
+                  image: AssetImage(icon),
+                  width: 24,
+                ),
+                Expanded(
+                  child: Container(
+                    child: Text(title,
+                        style: TextStyle(
+                            color: Colors.white,
+                            fontSize: 15,
+                            fontWeight: FontWeight.w500)),
+                    margin: EdgeInsets.only(left: 16),
+                  ),
+                  flex: 1,
+                ),
+                Image(
+                  image: AssetImage('images/icon_inter.png'),
+                  width: 24,
+                )
+              ],
+            ),
+          ),
+          onTap: () {
+            print(title);
+            if (myType == 'wallet') {
+              Navigator.push(context,
+                  new CupertinoPageRoute(builder: (context) => new MyWallet()));
+            }
+          });
+    });
+  }
+
+  Widget _popupBox(BuildContext context) {
+    return showBox
+        ? GestureDetector(
+            child: Container(
+              width: ScreenUtil().setWidth(375),
+              color: Colors.black.withOpacity(0.8),
+              child: Column(
+                mainAxisAlignment: MainAxisAlignment.center,
+                crossAxisAlignment: CrossAxisAlignment.center,
+                children: <Widget>[
+                  Container(
+                    width: 250,
+                    height: 96,
+                    decoration: BoxDecoration(
+                        //背景装饰
+                        gradient: LinearGradient(
+                      begin: Alignment.bottomRight,
+                      colors: [BG_SUB_COLOR, BG_COLOR],
+                    )),
+                    child: FlatButton(
+                      highlightColor: BG_SUB_COLOR,
+                      child: Text(
+                        '创建普通房间',
+                        style: TextStyle(
+                          color: Colors.white,
+                          fontSize: 22,
+                        ),
+                      ),
+                      onPressed: () {
+                        Navigator.push(
+                            context,
+                            new CupertinoPageRoute(
+                                builder: (context) => new OpenRoom()));
+                      },
+                    ),
+                  ),
+                  Container(
+                    width: 250,
+                    height: 96,
+                    margin: EdgeInsets.only(top: 36),
+                    decoration: BoxDecoration(
+                        //背景装饰
+                        gradient: LinearGradient(
+                      begin: Alignment.bottomRight,
+                      colors: [BG_SUB_COLOR, BG_COLOR],
+                    )),
+                    child: FlatButton(
+                      highlightColor: BG_SUB_COLOR,
+                      child: Text(
+                        '创建官方房间',
+                        style: TextStyle(
+                          color: Colors.white,
+                          fontSize: 22,
+                        ),
+                      ),
+                      onPressed: () {},
+                    ),
+                  )
+                ],
+              ),
+            ),
+            onTap: () {
+              setState(() {
+                showBox = false;
+              });
+            },
+          )
+        : Container();
+  }
+
+  void getUserInfo() async {
+    print('检查登录');
+    print(allToken);
+    final response = await Dio().get(domain + 'userInfo/getUserInfo',
+        options: Options(headers: {"token": allToken}));
+    final res = json.decode(response.toString());
+    print(res);
+    if (res['success']) {
+      print(res['data']);
+      setState(() {
+        userInfo = res['data'];
+      });
+    } else {
+      Navigator.push(context,
+          new MaterialPageRoute(builder: (context) => new LoginFirst()));
+    }
+  }
+}

+ 123 - 0
lib/pages/loginFirst.dart

@@ -0,0 +1,123 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/cupertino.dart';
+import '../styles/colors.dart';
+import 'dart:ui';
+import '../styles/totast.dart';
+import '../styles/api.dart';
+import 'loginSecond.dart'; //登录第二页面
+
+class LoginFirst extends StatefulWidget {
+  @override
+  LoginFirstState createState() => LoginFirstState();
+}
+
+class LoginFirstState extends State<LoginFirst> {
+  String inputVal;
+
+  @override
+  Widget build(BuildContext context) {
+    return new WillPopScope(
+        child: Scaffold(
+          appBar: AppBar(
+            backgroundColor: BG_SUB_COLOR,
+            centerTitle: true,
+            elevation: 0,
+            leading: Container(),
+          ),
+          body: Container(
+            width: double.infinity,
+            padding: EdgeInsets.symmetric(vertical: 20, horizontal: 15),
+            color: BG_SUB_COLOR,
+            child: Column(
+              crossAxisAlignment: CrossAxisAlignment.start,
+              children: <Widget>[
+                Text(
+                  'LOGO',
+                  style: TextStyle(
+                    color: Colors.white,
+                    fontSize: 64,
+                  ),
+                ),
+                Container(
+                  margin: EdgeInsets.only(top: 30),
+                  child: Text('手机快捷登录',
+                      style: TextStyle(
+                          color: Colors.white,
+                          fontSize: 28,
+                          fontWeight: FontWeight.w500)),
+                ),
+                Container(
+                    margin: EdgeInsets.only(top: 20),
+                    child: TextField(
+                        autofocus: true,
+                        keyboardType: TextInputType.phone,
+                        maxLength: 11,
+                        style: TextStyle(
+                            color: Colors.white,
+                            fontSize: 18,
+                            fontWeight: FontWeight.w500),
+                        decoration: InputDecoration(
+                            hintText: "输入手机号",
+                            hintStyle: TextStyle(
+                              fontSize: 16,
+                              color: Color(0xFF727785),
+                            ),
+                            prefixIcon: Container(
+                              padding: EdgeInsets.all(10),
+                              // color: PRIMARY_COLOR,
+                              child: Image.asset(
+                                'images/list_icon_shouji.png',
+                                width: 20,
+                              ),
+                            ),
+                            // suffixIcon:Container(
+                            //   padding: EdgeInsets.all(10),
+                            //   // color: PRIMARY_COLOR,
+                            //   child: Image.asset(
+                            //     'images/list_icon_shouji.png',
+                            //     width: 20,
+                            //   ),
+                            // ),
+                            counterStyle:
+                                TextStyle(color: BG_SUB_COLOR, fontSize: 0)),
+                        onChanged: (value) {
+                          inputVal = value;
+                        })),
+                Text('未注册的手机号验证后自动创建账户',
+                    style: TextStyle(color: Color(0xFF727785), fontSize: 13)),
+                Container(
+                  margin: EdgeInsets.symmetric(vertical: 22),
+                  width: double.infinity,
+                  height: 48,
+                  child: FlatButton(
+                    textColor: Colors.white,
+                    color: PRIMARY_COLOR,
+                    highlightColor: Color(0xFFC2524D),
+                    child: Text("下一步"),
+                    onPressed: () {
+                      print(inputVal);
+                      if (!checkPhone(inputVal)) {
+                        Toast.show(context, '手机号格式错误', 1500, 'info');
+                      } else {
+                        Navigator.push(
+                          context,
+                          new CupertinoPageRoute(
+                            builder: (context) =>
+                                new LoginSecond(phone: inputVal),
+                          ),
+                        );
+                      }
+                    },
+                  ),
+                )
+              ],
+            ),
+          ),
+        ),
+        onWillPop: () {
+          Toast.hide();
+          print("返回键点击了");
+          // Navigator.pop(context);
+        });
+  }
+}

+ 200 - 0
lib/pages/loginSecond.dart

@@ -0,0 +1,200 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/cupertino.dart';
+import '../styles/colors.dart';
+import 'dart:ui';
+import '../styles/totast.dart';
+import 'package:dio/dio.dart';
+import '../styles/api.dart';
+import 'dart:convert';
+import '../widget/ITextInput.dart';
+import 'home.dart';
+import 'package:flutter_redux/flutter_redux.dart';
+import '../state.dart';
+
+class LoginSecond extends StatefulWidget {
+  LoginSecond({Key key, this.phone}) : super(key: key);
+  final String phone; // 用来储存传递过来的值
+  @override
+  LoginSecondState createState() => LoginSecondState();
+}
+
+class LoginSecondState extends State<LoginSecond> {
+  String _sessionID;
+  bool isSend = false; //是否发送
+  int sendTime = 0;
+  String inputCode;
+  String useToken;
+
+  @override
+  void initState() {
+    // TODO: implement initState
+    super.initState();
+    Future.delayed(Duration(milliseconds: 100), () {
+      print('发送');
+      sendMsg();
+    });
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return new WillPopScope(
+        child: Scaffold(
+          appBar: AppBar(
+            backgroundColor: BG_SUB_COLOR,
+            centerTitle: true,
+            elevation: 0,
+          ),
+          body: Container(
+            color: BG_SUB_COLOR,
+            padding: EdgeInsets.symmetric(vertical: 30, horizontal: 15),
+            child: Column(
+              crossAxisAlignment: CrossAxisAlignment.start,
+              children: <Widget>[
+                Text(
+                  '验证码已发送至',
+                  style: TextStyle(
+                      color: Colors.white,
+                      fontSize: 28,
+                      fontWeight: FontWeight.w600),
+                ),
+                Container(
+                  margin: EdgeInsets.only(top: 45),
+                  child: Row(
+                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                    children: <Widget>[
+                      Text(widget.phone,
+                          style: TextStyle(
+                              color: Color(0xFFF15436),
+                              fontSize: 20,
+                              fontWeight: FontWeight.w500)),
+                      FlatButton(
+                        highlightColor: BG_SUB_COLOR,
+                        textColor: PRIMARY_COLOR,
+                        child: Text(isSend ? '(' + '$sendTime' + '秒)' : '重新发送'),
+                        disabledTextColor: Color(0xFF8D8E9C),
+                        onPressed: isSend
+                            ? null
+                            : () {
+                                sendMsg();
+                              },
+                      )
+                    ],
+                  ),
+                ),
+                Container(
+                  margin: EdgeInsets.only(top: 10),
+                  child: ITextField(
+                    maxLength: 6,
+                    keyboardType: ITextInputType.number,
+                    prefixIcon: Container(
+                      padding: EdgeInsets.all(10),
+                      // color: PRIMARY_COLOR,
+                      child: Image.asset(
+                        'images/list_icon_yanzhengma.png',
+                        width: 20,
+                      ),
+                    ),
+                    hintText: '输入短信验证码',
+                    hintStyle: TextStyle(
+                      fontSize: 16,
+                      color: Color(0xFF727785),
+                    ),
+                    textStyle: TextStyle(color: Colors.white),
+                    fieldCallBack: (content) {
+                      setState(() {
+                        inputCode = content;
+                      });
+                    },
+                    counterStyle: TextStyle(color: BG_SUB_COLOR, fontSize: 0),
+                  ),
+                ),
+                Container(
+                    margin: EdgeInsets.only(top: 63, bottom: 20),
+                    width: double.infinity,
+                    height: 48,
+                    child: FlatButton(
+                      textColor: Colors.white,
+                      color: PRIMARY_COLOR,
+                      highlightColor: Color(0xFFC2524D),
+                      child: Text("注册/登录"),
+                      onPressed: () async {
+                        if (_sessionID == null) {
+                          Toast.show(context, '请发送验证码', 1500, 'info');
+                        } else if (inputCode.length != 6) {
+                          Toast.show(context, '请输入验证码', 1500, 'info');
+                        } else {
+                          FormData formdata = FormData.from({
+                            "phone": widget.phone,
+                            "code": inputCode,
+                            "sessionId": _sessionID,
+                            "requireToken": true
+                          });
+                          Toast.show(context, '加载中', -1, 'loading');
+                          final response = await Dio()
+                              .post(domain + 'auth/loginSms', data: formdata);
+                          final res = json.decode(response.toString());
+                          Toast.hide();
+                          print(res);
+                          if (res['success']) {
+                            StoreProvider.of<CountState>(context)
+                                .dispatch(res['token']);
+                            Toast.show(context, '登录成功', 1500, 'success');
+                            Navigator.push(
+                              context,
+                              new CupertinoPageRoute(
+                                builder: (context) => new MyHomePage(),
+                              ),
+                            );
+                          } else {
+                            Toast.show(context, res['error'], 1500, 'info');
+                          }
+                        }
+                      },
+                    ))
+              ],
+            ),
+          ),
+        ),
+        onWillPop: () {
+          Toast.hide();
+          print("返回键点击了");
+          Navigator.pop(context);
+        });
+  }
+
+  void sendMsg() async {
+    print('发送验证码');
+
+    Toast.show(context, '加载中', -1, 'loading');
+    final response = await Dio()
+        .get(domain + 'rong/sendCode', data: {"phone": widget.phone});
+    final res = json.decode(response.toString());
+    Toast.hide();
+    if (res['success']) {
+      Toast.show(context, '发送成功', 1500, 'success');
+      _sessionID = res['data'];
+      setState(() {
+        isSend = true;
+      });
+      sendTime = 61;
+      getTime();
+    } else {
+      Toast.show(context, res['error'], 1500, 'info');
+    }
+  }
+
+  void getTime() {
+    if (sendTime == 0) {
+      setState(() {
+        isSend = false;
+      });
+    } else {
+      sendTime = sendTime - 1;
+      Future.delayed(Duration(milliseconds: 1000), () {
+        setState(() {
+          getTime();
+        });
+      });
+    }
+  }
+}

+ 324 - 0
lib/pages/myWallet.dart

@@ -0,0 +1,324 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import '../styles/colors.dart';
+import 'dart:ui';
+
+import 'recharge.dart';
+
+class MyWallet extends StatefulWidget {
+  @override
+  MyWalletState createState() => MyWalletState();
+}
+
+class MyWalletState extends State<MyWallet> {
+  ScrollController _controller;
+  List<Map> walletList;
+  bool isShow = false;
+  num _topHeight;
+  @override
+  void initState() {
+    super.initState();
+    walletList = List<Map>();
+    _controller = ScrollController();
+    isShow = false;
+    fetchTen();
+    _controller.addListener(() {
+      if (_controller.position.pixels == _controller.position.maxScrollExtent) {
+        fetchTen();
+      }
+
+      if (_controller.position.pixels >= _topHeight + 82) {
+        setState(() {
+          isShow = true;
+        });
+      } else {
+        setState(() {
+          isShow = false;
+        });
+      }
+    });
+  }
+
+  @override
+  void dispose() {
+    super.dispose();
+    _controller.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    ScreenUtil.instance = ScreenUtil(width: 375, height: 667)..init(context);
+    return new Scaffold(
+        body: RefreshIndicator(
+      color: PRIMARY_COLOR,
+      backgroundColor: BG_COLOR,
+      onRefresh: () async {
+        await new Future.delayed(const Duration(seconds: 1));
+        setState(() {
+          walletList = List<Map>();
+          isShow = false;
+        });
+        fetchTen();
+      },
+      child: Container(
+        color: BG_COLOR,
+        child: Stack(
+          children: <Widget>[
+            CustomScrollView(
+              controller: _controller,
+              slivers: <Widget>[
+                SliverAppBar(
+                  backgroundColor: PRIMARY_COLOR,
+                  title: Text(isShow ? "余额明细" : ""),
+                  centerTitle: true,
+                  pinned: true,
+                ),
+                _sliverToBoxAdapter(context),
+                _sliverList(context),
+              ],
+            ),
+            _floatTab(context)
+          ],
+        ),
+      ),
+    ));
+  }
+
+//浮块
+  Widget _floatTab(BuildContext context) {
+    _topHeight = 56 + MediaQueryData.fromWindow(window).padding.top;
+    return Positioned(
+      top: isShow ? _topHeight : -46,
+      child: Container(
+        width: window.physicalSize.width / window.devicePixelRatio,
+        height: 46,
+        color: PRIMARY_COLOR,
+        child: _newRouterTab(context),
+      ),
+    );
+  }
+
+  Widget _sliverToBoxAdapter(BuildContext context) {
+    return SliverToBoxAdapter(
+        child: Column(
+      children: <Widget>[
+        Container(
+          alignment: Alignment.center,
+          width: double.infinity,
+          height: 194,
+          decoration: BoxDecoration(
+              //背景装饰
+              gradient: LinearGradient(
+            begin: Alignment.bottomRight,
+            colors: [Color(0xFFFFA6A2), PRIMARY_COLOR],
+          )),
+          child: Stack(
+            overflow: Overflow.visible,
+            children: <Widget>[
+              Container(
+                width: 216,
+                height: 192,
+                decoration: BoxDecoration(
+                    image: DecorationImage(
+                  image: AssetImage('images/img_wodeshouyi.png'),
+                  fit: BoxFit.contain,
+                )),
+                child: Column(
+                  mainAxisAlignment: MainAxisAlignment.center,
+                  children: <Widget>[
+                    Container(
+                      child: Text('156',
+                          style: TextStyle(
+                            color: PRIMARY_COLOR,
+                            fontSize: 51,
+                            fontWeight: FontWeight.w900,
+                          )),
+                      padding: EdgeInsets.only(top: 10),
+                    ),
+                    Row(
+                      mainAxisAlignment: MainAxisAlignment.center,
+                      children: <Widget>[
+                        Image(
+                          image: AssetImage('images/icon_jinbi_xiao_hong.png'),
+                          width: 20,
+                        ),
+                        Text('我的金币',
+                            style: TextStyle(
+                              color: PRIMARY_COLOR,
+                              fontSize: 14,
+                            ))
+                      ],
+                    )
+                  ],
+                ),
+              ),
+              Positioned(
+                bottom: -23,
+                left: -(ScreenUtil().setWidth(345) - 216) / 2,
+                child: Container(
+                  width: ScreenUtil().setWidth(345),
+                  height: 46,
+                  color: PRIMARY_COLOR,
+                  child: _newRouterTab(context),
+                ),
+              )
+            ],
+          ),
+        ),
+        Container(
+          width: double.infinity,
+          child: Text(
+            '余额明细',
+            style: TextStyle(
+                color: Colors.white, fontSize: 16, fontWeight: FontWeight.w500),
+          ),
+          padding: EdgeInsets.only(
+            left: 15,
+            top: 53,
+            bottom: 15,
+          ),
+        )
+      ],
+    ));
+  }
+
+  //充值,提现
+  Widget _newRouterTab(BuildContext context) {
+    return Row(
+      children: <Widget>[
+        Expanded(
+          flex: 1,
+          child: GestureDetector(
+            child: Container(
+              padding: EdgeInsets.all(10),
+              child: Text(
+              '提现',
+              textAlign: TextAlign.center,
+              style: TextStyle(
+                  color: Colors.white,
+                  fontSize: 16,
+                  fontWeight: FontWeight.w500),
+            ),
+            ),
+            onTap: () {
+              print('提现');
+            },
+          ),
+        ),
+        Container(
+          width: 1,
+          height: 20,
+          color: Color(0x2E000000),
+        ),
+        Expanded(
+          flex: 1,
+          child: GestureDetector(
+            child:  Container(
+              padding: EdgeInsets.all(10),
+              child:Text(
+              '充值',
+              textAlign: TextAlign.center,
+              style: TextStyle(
+                  color: Colors.white,
+                  fontSize: 16,
+                  fontWeight: FontWeight.w500),
+            )
+            ),
+            onTap: () {
+              print("充值");
+               Navigator.push(
+                  context,
+                  new CupertinoPageRoute(
+                      builder: (context) => new Rechrage()));
+            },
+          ),
+        )
+      ],
+    );
+  }
+
+  Widget _sliverList(BuildContext context) {
+    return SliverFixedExtentList(
+      itemExtent: 66,
+      delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
+        if (index < walletList.length) {
+          return Container(
+            padding: EdgeInsets.all(15),
+            decoration: BoxDecoration(
+              border: BorderDirectional(
+                  top: BorderSide(
+                      width: 1,
+                      color: Color(0x2E000000),
+                      style: BorderStyle.solid)),
+              color: BG_COLOR,
+            ),
+            child: Row(
+              mainAxisAlignment: MainAxisAlignment.center,
+              children: <Widget>[
+                Container(
+                    width: 53,
+                    child: Text(
+                      walletList[index]['money'],
+                      style: TextStyle(
+                          color: Colors.white,
+                          fontSize: 20,
+                          fontWeight: FontWeight.w500),
+                    )),
+                Expanded(
+                  flex: 1,
+                  child: Column(
+                    crossAxisAlignment: CrossAxisAlignment.start,
+                    children: <Widget>[
+                      Text(
+                        walletList[index]['name'],
+                        maxLines: 1,
+                        overflow: TextOverflow.ellipsis,
+                        style: TextStyle(
+                            color: Colors.white,
+                            fontSize: 14,
+                            fontWeight: FontWeight.w500),
+                      ),
+                      Text(
+                        walletList[index]['time'],
+                        style: TextStyle(
+                            color: Color(0xFF727785),
+                            fontSize: 12,
+                            fontWeight: FontWeight.w400),
+                      )
+                    ],
+                  ),
+                )
+              ],
+            ),
+          );
+        } else {
+          return Center(
+            child: Text(
+              '没有更多了',
+              style: TextStyle(
+                  color: Color(0xFF727785),
+                  fontSize: 12,
+                  fontWeight: FontWeight.w400),
+            ),
+          );
+        }
+      }, childCount: walletList.length + 1),
+    );
+  }
+
+  fetch() async {
+    Map jsonp = {"money": '+90', "name": "竞赛奖励", "time": "2018.05.02 15:36"};
+    setState(() {
+      walletList.add(jsonp);
+    });
+  }
+
+  fetchTen() {
+    if (walletList.length < 100) {
+      for (int i = 0; i < 20; i++) {
+        fetch();
+      }
+    }
+  }
+}

+ 45 - 0
lib/pages/openRoom.dart

@@ -0,0 +1,45 @@
+import 'package:flutter/material.dart';
+import '../styles/colors.dart';
+import 'dart:ui';
+
+class OpenRoom extends StatefulWidget {
+  @override
+  OpenRoomState createState() => OpenRoomState();
+}
+
+class OpenRoomState extends State<OpenRoom> {
+  @override
+  Widget build(BuildContext context) {
+    // TODO: implement build
+    return new Scaffold(
+        appBar: AppBar(
+          backgroundColor: PRIMARY_COLOR,
+          title: Text('创建官方房间'),
+          centerTitle: true,
+          elevation: 0,
+          actions: <Widget>[
+            Container(
+              width: 60,
+              child: FlatButton(
+              highlightColor: PRIMARY_COLOR,
+              padding: EdgeInsets.only(right: 0),
+              child: Text('规则',
+                  style: TextStyle(color: Colors.white, fontSize: 13)),
+              onPressed: () {},
+            ),
+            )
+          ],
+        ),
+        body: RefreshIndicator(
+          color: PRIMARY_COLOR,
+          backgroundColor: BG_COLOR,
+          onRefresh: () async {
+            await new Future.delayed(const Duration(seconds: 1));
+          },
+          child: Container(
+            color: BG_COLOR,
+          ),
+        ));
+  }
+  
+}

+ 198 - 0
lib/pages/recharge.dart

@@ -0,0 +1,198 @@
+import 'package:flutter/material.dart';
+import '../styles/colors.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'dart:ui';
+
+class Rechrage extends StatefulWidget {
+  @override
+  RechrageState createState() => RechrageState();
+}
+
+class RechrageState extends State<Rechrage> {
+  List<Map> moenyList = [
+    {
+      "title": "10金币",
+      "money": 10,
+    },
+    {
+      "title": "50金币",
+      "money": 50,
+    },
+    {
+      "title": "100金币",
+      "money": 100,
+    },
+    {
+      "title": "300金币",
+      "money": 300,
+    },
+    {
+      "title": "500金币",
+      "money": 500,
+    }
+  ];
+
+  bool isInput = false;
+
+  int choosemoeny = 0;
+
+  bool autoChoose = false;
+
+  FocusNode _focusNode = new FocusNode();
+
+  @override
+  void initState() {
+    super.initState();
+    _focusNode.addListener(_focusNodeListener);
+  }
+
+  Future<Null> _focusNodeListener() async {
+    if (_focusNode.hasFocus) {
+      print('获取焦点');
+      setState(() {
+        if (!autoChoose) {
+          autoChoose = true;
+          choosemoeny = 0;
+        }
+        isInput = true;
+      });
+    } else {
+      print('失去焦点');
+      setState(() {
+        isInput = false;
+      });
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    ScreenUtil.instance = ScreenUtil(width: 375, height: 667)..init(context);
+    // TODO: implement build
+    return new Scaffold(
+        appBar: AppBar(
+          backgroundColor: PRIMARY_COLOR,
+          title: Text('充值'),
+          centerTitle: true,
+          elevation: 0,
+        ),
+        body: GestureDetector(
+
+            ///透明也响应处理
+            behavior: HitTestBehavior.translucent,
+            onTap: () {
+              ///触摸手气键盘
+              FocusScope.of(context).requestFocus(new FocusNode());
+            },
+            child: RefreshIndicator(
+              color: PRIMARY_COLOR,
+              backgroundColor: BG_COLOR,
+              onRefresh: () async {
+                await new Future.delayed(const Duration(seconds: 1));
+              },
+              child: Container(
+                color: BG_COLOR,
+                child: Column(
+                  children: <Widget>[_useGride(context)],
+                ),
+              ),
+            )));
+  }
+
+  Widget _useGride(BuildContext context) {
+    return Container(
+      padding: EdgeInsets.all(ScreenUtil().setWidth(15)),
+      width: double.infinity,
+      child: Wrap(
+        alignment: WrapAlignment.spaceBetween,
+        children: _allChooseBtn(context),
+      ),
+    );
+  }
+
+  List<Widget> _allChooseBtn(BuildContext context) {
+    List<Widget> allWidget =
+        new List<Widget>.generate(moenyList.length, (int index) {
+      return _chooseBtn(context, index);
+    });
+
+    Widget _input() {
+      return Container(
+          padding: EdgeInsets.only(left: 30, right: 5),
+          color: autoChoose ? PRIMARY_COLOR : BG_SUB_COLOR,
+          margin: EdgeInsets.only(bottom: ScreenUtil().setWidth(5)),
+          width: ScreenUtil().setWidth(170),
+          height: ScreenUtil().setWidth(60),
+          child: TextField(
+              focusNode: _focusNode,
+              textAlign: TextAlign.center,
+              keyboardType: TextInputType.number,
+              style: TextStyle(
+                fontSize: 16,
+                fontWeight: FontWeight.w500,
+                color: Colors.white,
+              ),
+              decoration: InputDecoration(
+                hintText: isInput ? "请输入金额" : "其他金额",
+                hintStyle: TextStyle(
+                    color: Colors.white,
+                    fontSize: 14,
+                    fontWeight: isInput?FontWeight.w500:FontWeight.w400),
+                suffixText: '金币',
+                suffixStyle: TextStyle(
+                    fontSize: 13,
+                    fontWeight: FontWeight.w400,
+                    color: Colors.white),
+                border: OutlineInputBorder(borderSide: BorderSide.none),
+              ),
+              onChanged: (String str) {
+                //输入监听
+                choosemoeny = int.parse(str);
+              }));
+    }
+
+    allWidget.add(_input());
+    return allWidget;
+  }
+
+  Widget _chooseBtn(BuildContext context, int index) {
+    bool isChoose = false;
+    if (!autoChoose && moenyList[index]["money"] == choosemoeny) {
+      isChoose = true;
+    }
+    return Container(
+      margin: EdgeInsets.only(bottom: ScreenUtil().setWidth(5)),
+      width: ScreenUtil().setWidth(170),
+      height: ScreenUtil().setWidth(60),
+      child: FlatButton(
+        color: isChoose ? PRIMARY_COLOR : BG_SUB_COLOR,
+        highlightColor: isChoose
+            ? PRIMARY_COLOR.withOpacity(0.3)
+            : BG_COLOR.withOpacity(0.3),
+        child: Column(
+          mainAxisAlignment: MainAxisAlignment.center,
+          children: <Widget>[
+            Text(moenyList[index]["title"],
+                style: TextStyle(
+                    color: Colors.white,
+                    fontSize: 14,
+                    fontWeight: FontWeight.w500,
+                    height: 1)),
+            Text('¥' + moenyList[index]["money"].toString(),
+                style: TextStyle(
+                    color: isChoose ? Colors.white : Color(0xFF727785),
+                    fontSize: 13,
+                    fontWeight: FontWeight.w400,
+                    height: 18 / 13)),
+          ],
+        ),
+        onPressed: () {
+          setState(() {
+            autoChoose = false;
+            choosemoeny = moenyList[index]["money"];
+            FocusScope.of(context).requestFocus(new FocusNode());
+          });
+        },
+      ),
+    );
+  }
+}

+ 388 - 0
lib/pages/roomInfo.dart

@@ -0,0 +1,388 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import '../styles/colors.dart';
+import 'package:dio/dio.dart';
+import '../styles/api.dart';
+import 'dart:ui';
+import 'dart:convert';
+
+class RoomInfo extends StatefulWidget {
+  RoomInfo({Key key, this.roomId}) : super(key: key);
+  final String roomId; // 用来储存传递过来的值
+
+  @override
+  RoomInfoState createState() => RoomInfoState();
+}
+
+class RoomInfoState extends State<RoomInfo>
+    with SingleTickerProviderStateMixin {
+  List<Map> tabList;
+
+  TabController mController;
+  ScrollController _perController;
+  Map roomInfo;
+  Map colorInfo;
+  List joinList = [];
+  @override
+  void initState() {
+    super.initState();
+    tabList = [
+      {"title": "房间信息", "value": 1},
+      {"title": "人员列表", "value": 2}
+    ];
+    mController = TabController(
+      length: tabList.length,
+      vsync: this,
+    );
+    roomInfo = {};
+
+    colorInfo = {
+      "黄金": Color(0xFFF9D881),
+      "白银": Color(0xFFAFCAD8),
+      "青铜": Color(0xFFE18D50),
+    };
+    _perController = ScrollController();
+    getRoomInfo();
+  }
+
+  @override
+  void dispose() {
+    super.dispose();
+    mController.dispose();
+    _perController.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    ScreenUtil.instance = ScreenUtil(width: 375, height: 667)..init(context);
+    // TODO: implement build
+    return new Scaffold(
+      appBar: AppBar(
+        backgroundColor: PRIMARY_COLOR,
+        title: Container(
+          child: TabBar(
+            controller: mController,
+            labelColor: Colors.white,
+            unselectedLabelColor: Colors.white.withOpacity(0.5),
+            labelStyle: TextStyle(fontSize: 16.0),
+            indicatorColor: Colors.white,
+            indicatorWeight: 3,
+            indicatorSize: TabBarIndicatorSize.label,
+            tabs: tabList.map((item) {
+              return Tab(
+                text: item['title'],
+              );
+            }).toList(),
+          ),
+        ),
+        centerTitle: true,
+        elevation: 0,
+        actions: <Widget>[
+          Container(
+            padding: EdgeInsets.only(right: 30, left: 20),
+            child: Image.asset(
+              'images/icon_fenxiang.png',
+              width: 24,
+            ),
+          )
+        ],
+      ),
+      body: Container(
+          color: BG_SUB_COLOR,
+          child: Stack(
+            children: <Widget>[
+              TabBarView(
+                controller: mController,
+                children: [_firstPage(), _secondPage(context)],
+              ),
+              _joinBtn()
+            ],
+          )),
+    );
+  }
+
+  Widget _firstPage() {
+    Map houseLevelInfo = roomInfo.isNotEmpty ? roomInfo["houseLevelInfo"] : {};
+
+    String levelName = houseLevelInfo.containsKey("levelName")
+        ? houseLevelInfo["levelName"]
+        : '黄金';
+
+    int joinMoney =
+        houseLevelInfo.containsKey('feeRatio') && roomInfo.containsKey("bonus")
+            ? houseLevelInfo["feeRatio"] * roomInfo["bonus"]
+            : 0;
+
+    return Container(
+      child: RefreshIndicator(
+          color: PRIMARY_COLOR,
+          backgroundColor: BG_SUB_COLOR,
+          displacement: 10,
+          onRefresh: () async {
+            await new Future.delayed(const Duration(seconds: 1));
+          },
+          child: SingleChildScrollView(
+            physics: AlwaysScrollableScrollPhysics(),
+            child: Container(
+              child: Column(
+                children: <Widget>[
+                  Image.network(
+                      'http://bpic.588ku.com/illus_pic/18/12/10/3678774e601145684677d48e17bb3486.jpg',
+                      width: double.infinity),
+                  Container(
+                      padding: EdgeInsets.only(top: 10),
+                      child: Row(
+                        mainAxisAlignment: MainAxisAlignment.center,
+                        children: <Widget>[
+                          Container(
+                            margin: EdgeInsets.only(left: 30, right: 8),
+                            child: Text(
+                              roomInfo.containsKey("houseName")
+                                  ? roomInfo["houseName"]
+                                  : '',
+                              style: TextStyle(
+                                  color: Colors.white,
+                                  fontSize: 16,
+                                  fontWeight: FontWeight.w500),
+                            ),
+                          ),
+                          Image.network(
+                            houseLevelInfo.containsKey("icon")
+                                ? houseLevelInfo["icon"]
+                                : '',
+                            width: 14,
+                          ),
+                          Text(
+                            houseLevelInfo.containsKey("levelName")
+                                ? houseLevelInfo["levelName"]
+                                : '',
+                            style: TextStyle(color: colorInfo[levelName]),
+                          )
+                        ],
+                      )),
+                  Container(
+                    margin: EdgeInsets.only(top: 6),
+                    child: Text(
+                      roomInfo.containsKey('houseAbstract')
+                          ? roomInfo["houseAbstract"]
+                          : "",
+                      style: TextStyle(color: Color(0xFF9BA0AE), fontSize: 12),
+                    ),
+                  ),
+                  Row(
+                    mainAxisAlignment: MainAxisAlignment.center,
+                    children: <Widget>[
+                      Image.asset(
+                        'images/icon_renshu.png',
+                        width: 20,
+                      ),
+                      Text(
+                        houseLevelInfo['minNumber'].toString() +
+                            '/' +
+                            houseLevelInfo['maxNumber'].toString(),
+                        style: TextStyle(
+                            fontSize: 14,
+                            fontWeight: FontWeight.w500,
+                            color: Color(0xFFB1B2C0)),
+                      )
+                    ],
+                  ),
+                  Container(
+                    margin: EdgeInsets.only(top: 14),
+                    width: 200,
+                    height: 40,
+                    decoration: BoxDecoration(
+                      border: Border.all(
+                          width: 1,
+                          color: PRIMARY_COLOR,
+                          style: BorderStyle.solid),
+                      borderRadius: BorderRadius.all(Radius.circular(2)),
+                    ),
+                    child: Row(
+                      mainAxisAlignment: MainAxisAlignment.center,
+                      children: <Widget>[
+                        Text(
+                          '奖金',
+                          style: TextStyle(
+                            color: PRIMARY_COLOR,
+                            fontSize: 13,
+                            fontWeight: FontWeight.w500,
+                          ),
+                        ),
+                        Container(
+                          padding: EdgeInsets.only(left: 10, right: 6),
+                          child: Image.asset(
+                            "images/icon_jinbi_da_hong.png",
+                            width: 20,
+                          ),
+                        ),
+                        Text(
+                          'X' +
+                              (roomInfo.containsKey("bonus")
+                                  ? roomInfo["bonus"].toString()
+                                  : '0'),
+                          style: TextStyle(
+                            color: PRIMARY_COLOR,
+                            fontSize: 22,
+                            fontWeight: FontWeight.w900,
+                          ),
+                        )
+                      ],
+                    ),
+                  ),
+                  Container(
+                    width: double.infinity,
+                    margin: EdgeInsets.only(top: 25, left: 15, right: 15),
+                    padding: EdgeInsets.only(
+                        top: 15, left: 15, right: 10, bottom: 15),
+                    decoration: BoxDecoration(
+                        borderRadius: BorderRadius.only(
+                            topLeft: Radius.circular(0),
+                            topRight: Radius.circular(8),
+                            bottomLeft: Radius.circular(8),
+                            bottomRight: Radius.circular(8)),
+                        gradient: LinearGradient(
+                          begin: Alignment.topRight,
+                          colors: [Color(0xFF464B6A), Color(0xFF35395E)],
+                        )),
+                    child: Text(
+                      '加入房间后,请在此页面耐心等待,竞赛即将开始时,玩家有10秒的时间进行确认,点击确认方可正式进入竞赛,若没有点击,则视为自动放弃此次竞赛,已支付金币概不退换',
+                      style: TextStyle(color: Colors.white, fontSize: 13),
+                    ),
+                  ),
+                  Container(
+                    width: double.infinity,
+                    height: 48 + ScreenUtil().setHeight(40),
+                  )
+                ],
+              ),
+            ),
+          )),
+    );
+  }
+
+  Widget _joinBtn() {
+    Map houseLevelInfo = roomInfo.isNotEmpty ? roomInfo["houseLevelInfo"] : {};
+
+    int joinMoney =
+        houseLevelInfo.containsKey('feeRatio') && roomInfo.containsKey("bonus")
+            ? houseLevelInfo["feeRatio"] * roomInfo["bonus"]
+            : 0;
+    return Positioned(
+      bottom: 0,
+      child: Container(
+        width: ScreenUtil().setWidth(375),
+        height: 48 + ScreenUtil().setHeight(40),
+        padding: EdgeInsets.only(
+            top: ScreenUtil().setHeight(20),
+            bottom: ScreenUtil().setHeight(20),
+            left: 15,
+            right: 15),
+        child: RaisedButton(
+          textColor: Colors.white,
+          child: Row(
+            mainAxisAlignment: MainAxisAlignment.center,
+            children: <Widget>[
+              Image.asset(
+                'images/icon_jinbi_da_bai.png',
+                width: 20,
+              ),
+              Container(
+                margin: EdgeInsets.only(left: 6),
+                child: Text(
+                  'X' + joinMoney.toString(),
+                  style: TextStyle(
+                      color: Colors.white,
+                      fontSize: 16,
+                      fontWeight: FontWeight.w500),
+                ),
+              ),
+              Container(
+                  margin: EdgeInsets.only(left: 20),
+                  child: Text(
+                    '加入房间',
+                    style: TextStyle(
+                        color: Colors.white,
+                        fontSize: 16,
+                        fontWeight: FontWeight.w500),
+                  ))
+            ],
+          ),
+          onPressed: () => {},
+        ),
+      ),
+    );
+  }
+
+  Widget _secondPage(BuildContext context) {
+    return RefreshIndicator(
+      color: PRIMARY_COLOR,
+      backgroundColor: BG_SUB_COLOR,
+      displacement: 10,
+      onRefresh: () async {
+        await new Future.delayed(const Duration(seconds: 1));
+      },
+      child: ListView.builder(
+          physics: AlwaysScrollableScrollPhysics(),
+          controller: _perController,
+          itemCount: 3,
+          itemBuilder: (BuildContext context, int index) {
+            return person_item({},index);
+          }),
+    );
+  }
+
+
+  Widget person_item(Map info,int  index){
+    return Container(
+      width: double.infinity,
+      height:60,
+      color: Color(0xFF2B2B42),
+      margin: EdgeInsets.only(top:index==0?10:0),
+      padding:EdgeInsets.only(left: 15,right: 15),
+      child: Container(
+        decoration:BoxDecoration(
+          border: Border(bottom: BorderSide(
+            width: 1,
+            color: BG_SUB_COLOR,
+            style: BorderStyle.solid
+          ))
+        ),
+        child: Row(
+          children: <Widget>[
+           Container(
+             margin: EdgeInsets.only(right: 12),
+             width: 36,
+             height: 36,
+             child:  CircleAvatar(
+              backgroundImage:NetworkImage('http://bpic.588ku.com/original_pic/19/01/10/c21f0c83a0029a820d47e4828559353f.jpg'),
+            ),
+           ),
+           Expanded(
+             flex: 1,
+             child: Text('邱好好',style: TextStyle(
+               color: Colors.white,
+               fontSize: 14,
+             ),
+              maxLines:1,
+              overflow: TextOverflow.ellipsis,
+             ),
+           )
+          ],
+        ),
+      ),
+    );
+  }
+
+  void getRoomInfo() async {
+    final response = await Dio()
+        .get(domain + 'houseInfo/getOne', data: {"id": widget.roomId});
+    final res = json.decode(response.toString());
+    if (res['success']) {
+      setState(() {
+        roomInfo = res["data"];
+      });
+      print(roomInfo);
+    }
+  }
+}

+ 195 - 0
lib/pages/roomList.dart

@@ -0,0 +1,195 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:dio/dio.dart';
+import '../styles/colors.dart';
+import '../styles/api.dart';
+import 'dart:convert';
+import '../widget/room_item.dart';
+import '../widget/popupButton_my.dart';
+import 'dart:ui';
+
+class RoomList extends StatefulWidget {
+  @override
+  RoomListState createState() => RoomListState();
+}
+
+class RoomListState extends State<RoomList> {
+  List<Map> roomList = [];
+  int currentPage = 1;
+  ScrollController _controller;
+  bool scrollFlag = true;
+
+  @override
+  void initState() {
+    super.initState();
+    getRoomInfo();
+    _controller = ScrollController();
+    _controller.addListener(() {
+      if (_controller.position.pixels == _controller.position.maxScrollExtent) {
+        if (scrollFlag) {
+          setState(() {
+            currentPage++;
+          });
+          getRoomInfo();
+        }
+        
+      }
+    });
+  }
+
+  @override
+  void dispose() {
+    super.dispose();
+    _controller.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    ScreenUtil.instance = ScreenUtil(width: 375, height: 667)..init(context);
+
+    // TODO: implement build
+    return new Scaffold(
+        appBar: AppBar(
+          backgroundColor: PRIMARY_COLOR,
+          title: Text('房间列表'),
+          centerTitle: true,
+          elevation: 0,
+        ),
+        body: RefreshIndicator(
+          color: PRIMARY_COLOR,
+          backgroundColor: BG_COLOR,
+          onRefresh: () async {
+            await new Future.delayed(const Duration(seconds: 1));
+            setState(() {
+              currentPage = 1;
+            });
+            getRoomInfo();
+          },
+          child: Container(
+            color: BG_COLOR,
+            child: Stack(
+              children: <Widget>[
+                CustomScrollView(
+                  controller: _controller,
+                  physics: AlwaysScrollableScrollPhysics(),
+                  slivers: <Widget>[
+                    SliverToBoxAdapter(
+                      child: Container(
+                        height: 44,
+                      ),
+                    ),
+                    SliverFixedExtentList(
+                      itemExtent: ScreenUtil().setWidth(78),
+                      delegate: SliverChildBuilderDelegate(
+                          (BuildContext context, int index) {
+                        return RommItem(
+                          roomInfo: roomList[index],
+                          hasBorder: true,
+                          isRage: false,
+                        );
+                      }, childCount: roomList.length),
+                    )
+                  ],
+                ),
+                _topWidget()
+              ],
+            ),
+          ),
+        ));
+  }
+
+  Widget _topWidget() {
+    return Positioned(
+      width: ScreenUtil().setWidth(375),
+      height: 44,
+      child: Container(
+        padding: EdgeInsets.all(14),
+        color: Color(0xFF3A3D5C),
+        child: Row(
+          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+          children: <Widget>[
+            _chooseItem(),
+            _chooseItem(),
+            _chooseItem(),
+            _chooseItem()
+          ],
+        ),
+      ),
+    );
+  }
+
+  Widget _chooseItem() {
+    return Expanded(
+      flex: 1,
+      child: MyPopupMenuButton(
+        initialValue:'刺激战场',
+        padding: EdgeInsets.all(0.0),
+          child: Row(
+            crossAxisAlignment: CrossAxisAlignment.center,
+            mainAxisAlignment: MainAxisAlignment.center,
+            children: <Widget>[
+              Text(
+                '全部游戏',
+                style: TextStyle(
+                    color: Colors.white,
+                    fontSize: 12,
+                    fontWeight: FontWeight.w500),
+              ),
+              Image.asset(
+                'images/icon_zhankai_baise.png',
+                width: 20,
+              )
+            ],
+          ),
+          onSelected: (String value) {
+            print('******');
+          },
+          itemBuilder: (BuildContext context) => <MyPopupMenuEntry<String>>[
+                MyPopupMenuItem(
+                  child: Container(
+                    height: 30,
+                    child: Text('刺激战场',style: TextStyle(
+                      fontSize: 14,
+                    )),
+                  ),
+                  value: '刺激战场',
+                ),
+                MyPopupMenuItem(
+                  child: Container(
+                    child: Text('11',style: TextStyle(
+                      fontSize: 14
+                    )),
+                  ),
+                  value: '这是增加',
+                ),
+              ]),
+    );
+  }
+
+  void getRoomInfo() async {
+    print('getInfo');
+    if (currentPage == 1) {
+      setState(() {
+        roomList = [];
+      });
+    }
+    final response = await Dio().get(domain + 'houseInfo/page', data: {
+      "currentPage": currentPage,
+      "pageNumber": 20,
+    });
+    final res = json.decode(response.toString());
+    if (res['success']) {
+      for (var item in res['data']['pp']) {
+        setState(() {
+          roomList.add(item);
+        });
+      }
+      if (res['data']['page']['currentPage'] <
+          res['data']['page']['totalPage']) {
+        scrollFlag = true;
+      } else {
+        scrollFlag = false;
+      }
+    }
+  }
+}

+ 194 - 0
lib/pages/setting.dart

@@ -0,0 +1,194 @@
+import 'package:flutter/material.dart';
+import "package:image_picker/image_picker.dart";
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:dio/dio.dart';
+import '../styles/colors.dart';
+import '../styles/api.dart';
+import 'dart:io';
+import 'dart:async';
+import 'dart:typed_data';
+import 'dart:convert';
+import 'dart:ui';
+import '../styles/totast.dart';
+
+class Setting extends StatefulWidget {
+  @override
+  SettingState createState() => SettingState();
+}
+
+class SettingState extends State<Setting> {
+  File _image;
+  Map userInfo = {};
+
+  Future getImage() async {
+    var image = await ImagePicker.pickImage(source: ImageSource.gallery);
+    image.readAsBytes().then((bytes) async {
+      String encoded1 = 'data:image/jpeg;base64,' + base64Encode(bytes);
+      print(encoded1);
+      FormData formData = new FormData.from({"base64": encoded1});
+      Toast.show(context, '加载中', -1, 'loading');
+      final response =
+          await Dio().post(domain + 'assets/uploadImg', data: formData);
+      final res = json.decode(response.toString());
+      if (res['success']) {
+        updateUserInfo(res['data'], 'icon');
+      }
+    });
+
+    setState(() {
+      _image = image;
+    });
+  }
+
+  @override
+  void initState() {
+    // TODO: implement initState
+    super.initState();
+
+    getUserInfo(false);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    ScreenUtil.instance = ScreenUtil(width: 375, height: 667)..init(context);
+    // TODO: implement build
+    return new WillPopScope(
+        child: Scaffold(
+            appBar: AppBar(
+              backgroundColor: PRIMARY_COLOR,
+              title: Text('系统设置'),
+              centerTitle: true,
+              elevation: 0,
+            ),
+            body: RefreshIndicator(
+                color: PRIMARY_COLOR,
+                backgroundColor: BG_SUB_COLOR,
+                displacement: 10,
+                onRefresh: () async {
+                  await new Future.delayed(const Duration(seconds: 1));
+                  getUserInfo(false);
+                },
+                child: SingleChildScrollView(
+                    physics: AlwaysScrollableScrollPhysics(),
+                    child: ConstrainedBox(
+                      constraints: BoxConstraints(
+                          minHeight: window.physicalSize.height /
+                                  window.devicePixelRatio -
+                              56 -
+                              MediaQueryData.fromWindow(window).padding.top),
+                      child: Container(
+                        color: BG_COLOR,
+                        child: Column(
+                          children: <Widget>[
+                            Container(
+                              color: BG_SUB_COLOR,
+                              padding: EdgeInsets.only(top: 10),
+                              child: Column(
+                                children: <Widget>[_settingItem('头像')],
+                              ),
+                            )
+                          ],
+                        ),
+                      ),
+                    ))),
+            floatingActionButton: FloatingActionButton(
+              onPressed: () {
+                print('点击照片');
+                Toast.show(context, '加载中', -1, 'loading');
+              },
+              tooltip: 'Pick Image',
+              child: Icon(Icons.add_a_photo),
+            )),
+        onWillPop: () {
+          Toast.hide();
+          print("返回键点击了");
+          Navigator.pop(context);
+        });
+  }
+
+  Widget _settingItem(name) {
+    return Container(
+      padding: EdgeInsets.only(left: 15, right: 15),
+      height: 60,
+      color: BG_COLOR,
+      child: GestureDetector(
+        child: Row(
+          children: <Widget>[
+            Text(name,
+                style: TextStyle(
+                    color: Colors.white,
+                    fontSize: 14,
+                    fontWeight: FontWeight.w400)),
+            Expanded(flex: 1, child: _centerWidget('头像')),
+            Image.asset(
+              'images/icon_inter.png',
+              width: 24,
+            )
+          ],
+        ),
+        onTap: () {
+          if (name == '头像') {
+            getImage();
+          }
+        },
+      ),
+    );
+  }
+
+  Widget _centerWidget(name) {
+    Widget _wiget;
+    print(name);
+    if (name == '头像') {
+      _wiget = UnconstrainedBox(
+        alignment: Alignment.centerRight,
+        child: SizedBox(
+          width: 36,
+          height: 36,
+          child: CircleAvatar(
+              backgroundImage: NetworkImage(
+                  userInfo.containsKey('icon') ? userInfo['icon'] : '')),
+        ),
+      );
+    }
+
+    return _wiget;
+  }
+
+  void updateUserInfo(value, key) async {
+    print(value);
+    print(key);
+    FormData formdata =
+        new FormData.from({key: value, "id": isDebug ? debugID : ''});
+    print(formdata);
+    final response =
+        await Dio().post(domain + 'userInfo/update', data: formdata);
+        print(response);
+    final res = json.decode(response.toString());
+    if (res['success']) {
+      Toast.hide();
+      getUserInfo(false);
+      Toast.show(context, '修改成功', 1500, 'success');
+    }
+  }
+
+  void getUserInfo(isFreash) async {
+    Future.delayed(Duration(seconds: 1000), () {
+      if (!userInfo.containsKey('nickname')) {
+        Toast.show(context, '加载中', -1, 'loading');
+        isFreash = true;
+      }
+    });
+    final response = await Dio().get(domain + 'userInfo/getUserInfo',
+        data: {"id": isDebug ? debugID : ''});
+    final res = json.decode(response.toString());
+    if (isFreash) {
+      Toast.hide();
+    }
+    if (res['success']) {
+      print(res['data']);
+      setState(() {
+        userInfo = res['data'];
+      });
+    }
+  }
+}

+ 17 - 0
lib/state.dart

@@ -0,0 +1,17 @@
+import 'package:meta/meta.dart';
+
+enum Actions { updateToken,updateUser }
+
+@immutable
+class CountState {
+  String usetoken;
+  Map userInfo;
+  get _usetoken => usetoken;
+  get _userInfo => userInfo;
+
+  CountState(this.usetoken);
+  CountState.initState() {
+    usetoken = '';
+    userInfo={};
+  }
+}

+ 18 - 0
lib/styles/api.dart

@@ -0,0 +1,18 @@
+import 'package:flutter/material.dart';
+
+
+String domain='http://49.4.66.233:8201/';
+// String domain='http://192.168.50.226:8080/'; //本地ip
+
+String debugID='84671';//测试id
+
+bool isDebug=false;//是否测试(未链接登录需要该值获取测试id)
+
+bool checkPhone (phone){
+    bool result = false;
+    RegExp exp=new RegExp(r"^1[3|4|5|8|7|6|9][0-9]\d{8}$");
+    if (exp.hasMatch(phone)) {
+        result = true;
+    }
+    return result;
+}

+ 14 - 0
lib/styles/colors.dart

@@ -0,0 +1,14 @@
+import 'package:flutter/material.dart';
+
+//主颜色
+const PRIMARY_COLOR=const Color(0xFFC2524D);
+
+//辅助色
+const SUB_COLOR=const Color(0xFFA6554F);
+
+//背景色
+const BG_COLOR=const Color(0xFF2B2B42);
+
+
+//辅助背景色
+const BG_SUB_COLOR=const Color(0xFF222335);

+ 214 - 0
lib/styles/totast.dart

@@ -0,0 +1,214 @@
+import 'package:flutter/material.dart';
+
+class Toast {
+  static ToastView preToast;
+  static show(BuildContext context, String msg, int seconds, String toastType) {
+    var overlayState = Overlay.of(context);
+    var controllerShowAnim = new AnimationController(
+      vsync: overlayState,
+      duration: Duration(milliseconds: 250),
+    );
+    var controllerShowOffset = new AnimationController(
+      vsync: overlayState,
+      duration: Duration(milliseconds: 350),
+    );
+    var controllerHide = new AnimationController(
+      vsync: overlayState,
+      duration: Duration(milliseconds: 250),
+    );
+    var opacityAnim1 =
+        new Tween(begin: 0.0, end: 1.0).animate(controllerShowAnim);
+    var controllerCurvedShowOffset = new CurvedAnimation(
+        parent: controllerShowOffset, curve: _BounceOutCurve._());
+    var offsetAnim =
+        new Tween(begin: 30.0, end: 0.0).animate(controllerCurvedShowOffset);
+    var opacityAnim2 = new Tween(begin: 1.0, end: 0.0).animate(controllerHide);
+
+    OverlayEntry overlayEntry;
+    overlayEntry = new OverlayEntry(builder: (context) {
+      return ToastWidget(
+        opacityAnim1: opacityAnim1,
+        opacityAnim2: opacityAnim2,
+        offsetAnim: offsetAnim,
+        child: buildToastLayout(msg, toastType),
+      );
+    });
+    var toastView = ToastView();
+    if (seconds != null) {
+      toastView.seconds = seconds;
+    }
+
+    toastView.overlayEntry = overlayEntry;
+    toastView.controllerShowAnim = controllerShowAnim;
+    toastView.controllerShowOffset = controllerShowOffset;
+    toastView.controllerHide = controllerHide;
+    toastView.overlayState = overlayState;
+    preToast = toastView;
+
+
+    
+    toastView._show();
+  }
+
+  static hide() {
+    print(preToast);
+    if (preToast != null) {
+      preToast.dismiss();
+      preToast = ToastView();
+    }
+  }
+
+  static LayoutBuilder buildToastLayout(String msg, String toastType) {
+    return LayoutBuilder(builder: (context, constraints) {
+      return Container(
+        color: Colors.white.withOpacity(0),
+        child: IgnorePointer(
+          ignoring: true,
+          child: Container(
+            child: Material(
+                color: Colors.white.withOpacity(0),
+                child: new Container(
+                  padding: EdgeInsets.symmetric(
+                      horizontal: toastType == 'info' ? 15 : 36),
+                  height: toastType == 'info' ? 40 : 120,
+                  decoration: ShapeDecoration(
+                    color: Colors.black.withOpacity(0.4),
+                    shape: RoundedRectangleBorder(
+                      borderRadius: BorderRadius.all(
+                        Radius.circular(8.0),
+                      ),
+                    ),
+                  ),
+                  child: new Column(
+                    mainAxisAlignment: MainAxisAlignment.center,
+                    crossAxisAlignment: CrossAxisAlignment.center,
+                    children: _contentWidget(toastType, msg),
+                  ),
+                )),
+            alignment: Alignment.center,
+          ),
+        ),
+      );
+    });
+  }
+}
+
+List<Widget> _contentWidget(toastType, msg) {
+  List<Widget> widgetList = [];
+  if (toastType == 'loading') {
+    widgetList = [
+      new CircularProgressIndicator(),
+      new Padding(
+        padding: const EdgeInsets.only(
+          top: 20.0,
+        ),
+        child: new Text(
+          msg,
+          style: new TextStyle(fontSize: 14.0, color: Colors.white),
+        ),
+      ),
+    ];
+  } else if (toastType == 'success') {
+    widgetList = [
+      Icon(Icons.done, color: Colors.green, size: 50),
+      new Padding(
+        padding: const EdgeInsets.only(
+          top: 10.0,
+        ),
+        child: new Text(
+          msg,
+          style: new TextStyle(fontSize: 14.0, color: Colors.white),
+        ),
+      ),
+    ];
+  } else {
+    widgetList = [
+      Text(
+        msg,
+        style: new TextStyle(fontSize: 14.0, color: Colors.white),
+      ),
+    ];
+  }
+
+  return widgetList;
+}
+
+class ToastView {
+  OverlayEntry overlayEntry;
+  AnimationController controllerShowAnim;
+  AnimationController controllerShowOffset;
+  AnimationController controllerHide;
+  OverlayState overlayState;
+  bool dismissed = false;
+  int seconds = 3500;
+
+  _show() async {
+    overlayState.insert(overlayEntry);
+    controllerShowAnim.forward();
+    controllerShowOffset.forward();
+    if (seconds != -1) {
+      await Future.delayed(Duration(milliseconds: seconds));
+      this.dismiss();
+    }
+  }
+
+  dismiss() async {
+    if (dismissed) {
+      return;
+    }
+    this.dismissed = true;
+    controllerHide.forward();
+    await Future.delayed(Duration(milliseconds: 250));
+    overlayEntry?.remove();
+  }
+}
+
+class ToastWidget extends StatelessWidget {
+  final Widget child;
+  final Animation<double> opacityAnim1;
+  final Animation<double> opacityAnim2;
+  final Animation<double> offsetAnim;
+
+  ToastWidget(
+      {this.child, this.offsetAnim, this.opacityAnim1, this.opacityAnim2});
+
+  @override
+  Widget build(BuildContext context) {
+    return AnimatedBuilder(
+      animation: opacityAnim1,
+      child: child,
+      builder: (context, child_to_build) {
+        return Opacity(
+          opacity: opacityAnim1.value,
+          child: AnimatedBuilder(
+            animation: offsetAnim,
+            builder: (context, _) {
+              return Transform.translate(
+                offset: Offset(0, offsetAnim.value),
+                child: AnimatedBuilder(
+                  animation: opacityAnim2,
+                  builder: (context, _) {
+                    return Opacity(
+                      opacity: opacityAnim2.value,
+                      child: child_to_build,
+                    );
+                  },
+                ),
+              );
+            },
+          ),
+        );
+      },
+    );
+  }
+}
+
+class _BounceOutCurve extends Curve {
+  const _BounceOutCurve._();
+
+  @override
+  double transform(double t) {
+    t -= 1.0;
+    return t * t * ((2 + 1) * t + 2) + 1.0;
+  }
+}

+ 153 - 0
lib/widget/ITextInput.dart

@@ -0,0 +1,153 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+
+///自带删除的ITextField
+typedef void ITextFieldCallBack(String content);
+
+enum ITextInputType {
+  text,
+  multiline,
+  number,
+  phone,
+  datetime,
+  emailAddress,
+  url,
+  password
+}
+
+class ITextField extends StatefulWidget {
+  final ITextInputType keyboardType;
+  final int maxLines;
+  final int maxLength;
+  final String hintText;
+  final TextStyle hintStyle;
+  final ITextFieldCallBack fieldCallBack;
+  final Icon deleteIcon;
+  final InputBorder inputBorder;
+  final Widget prefixIcon;
+  final TextStyle textStyle;
+  final FormFieldValidator<String> validator;
+  final TextStyle counterStyle;
+
+  ITextField(
+      {Key key,
+      ITextInputType keyboardType: ITextInputType.text,
+      this.maxLines = 1,
+      this.maxLength,
+      this.hintText,
+      this.hintStyle,
+      this.fieldCallBack,
+      this.deleteIcon,
+      this.inputBorder,
+      this.textStyle,
+      this.prefixIcon,
+      this.validator,
+      this.counterStyle})
+      : assert(maxLines == null || maxLines > 0),
+        assert(maxLength == null || maxLength > 0),
+        keyboardType = maxLines == 1 ? keyboardType : ITextInputType.multiline,
+        super(key: key);
+
+  @override
+  State<StatefulWidget> createState() => _ITextFieldState();
+}
+
+class _ITextFieldState extends State<ITextField> {
+  String _inputText = "";
+  bool _hasdeleteIcon = false;
+  bool _isNumber = false;
+  bool _isPassword = false;
+
+  ///输入类型
+  TextInputType _getTextInputType() {
+    switch (widget.keyboardType) {
+      case ITextInputType.text:
+        return TextInputType.text;
+      case ITextInputType.multiline:
+        return TextInputType.multiline;
+      case ITextInputType.number:
+        _isNumber = true;
+        return TextInputType.number;
+      case ITextInputType.phone:
+        _isNumber = true;
+        return TextInputType.phone;
+      case ITextInputType.datetime:
+        return TextInputType.datetime;
+      case ITextInputType.emailAddress:
+        return TextInputType.emailAddress;
+      case ITextInputType.url:
+        return TextInputType.url;
+      case ITextInputType.password:
+        _isPassword = true;
+        return TextInputType.text;
+    }
+  }
+
+  ///输入范围
+  List<TextInputFormatter> _getTextInputFormatter() {
+    return _isNumber
+        ? <TextInputFormatter>[
+            WhitelistingTextInputFormatter.digitsOnly,
+          ]
+        : null;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    TextEditingController _controller = new TextEditingController.fromValue(
+        TextEditingValue(
+            text: _inputText,
+            selection: new TextSelection.fromPosition(TextPosition(
+                affinity: TextAffinity.downstream,
+                offset: _inputText.length))));
+    TextField textField = new TextField(
+      controller: _controller,
+      decoration: InputDecoration(
+        counterStyle: widget.counterStyle,
+        hintStyle: widget.hintStyle,
+        hintText: widget.hintText,
+        border: widget.inputBorder != null
+            ? widget.inputBorder
+            : UnderlineInputBorder(),
+        fillColor: Colors.transparent,
+        filled: true,
+        prefixIcon: widget.prefixIcon,
+        suffixIcon: _hasdeleteIcon
+            ? new Container(
+                width: 20.0,
+                height: 20.0,
+                child: new IconButton(
+                  alignment: Alignment.center,
+                  padding: const EdgeInsets.all(0.0),
+                  iconSize: 18.0,
+                  icon: widget.deleteIcon != null
+                      ? widget.deleteIcon
+                      : Icon(Icons.cancel),
+                  onPressed: () {
+                    setState(() {
+                      _inputText = "";
+                      _hasdeleteIcon = (_inputText.isNotEmpty);
+                      widget.fieldCallBack(_inputText);
+                    });
+                  },
+                ),
+              )
+            : new Text(""),
+      ),
+      onChanged: (str) {
+        setState(() {
+          _inputText = str;
+          _hasdeleteIcon = (_inputText.isNotEmpty);
+          widget.fieldCallBack(_inputText);
+        });
+      },
+      keyboardType: _getTextInputType(),
+      maxLength: widget.maxLength,
+      maxLines: widget.maxLines,
+      inputFormatters: _getTextInputFormatter(),
+      style: widget.textStyle,
+      obscureText: _isPassword,
+    );
+    return textField;
+  }
+}

+ 50 - 0
lib/widget/indicator_factory.dart

@@ -0,0 +1,50 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:pull_to_refresh/pull_to_refresh.dart';
+
+/*
+ * Author: Jpeng
+ * Email: peng8350@gmail.com
+ * Time: 2018/5/30 上午10:25
+ */
+
+Widget buildDefaultHeader(BuildContext context, int mode) {
+  return new ClassicIndicator(
+    failedText: '刷新失败!',
+    completeText: '刷新完成!',
+    releaseText: '释放可以刷新',
+    idleText: '下拉刷新哦!',
+    failedIcon: new Icon(Icons.clear, color: Colors.black),
+    completeIcon: new Icon(Icons.done, color: Colors.black),
+    idleIcon: new Icon(Icons.arrow_downward, color: Colors.black),
+    releaseIcon: new Icon(Icons.arrow_upward, color: Colors.black),
+    refreshingText: '正在刷新...',
+    textStyle: Theme.of(context).textTheme.body2,
+    mode: mode,
+  );
+}
+
+Widget buildDefaultFooter(BuildContext context, int mode,
+    [Function requestLoad]) {
+  if (mode == RefreshStatus.failed || mode == RefreshStatus.idle) {
+    return new InkWell(
+      child: new ClassicIndicator(
+          mode: mode,
+          idleIcon: new Icon(Icons.arrow_upward, color: Colors.black),
+          textStyle: Theme.of(context).textTheme.body2,
+          refreshingText: '正在加载中...',
+          idleText: '上拉加载',
+          failedText: '网络异常',
+          noDataText: '没有更多数据'),
+      onTap: requestLoad,
+    );
+  } else
+    return new ClassicIndicator(
+        mode: mode,
+        idleIcon: new Icon(Icons.arrow_upward, color: Colors.black),
+        textStyle: Theme.of(context).textTheme.body2,
+        refreshingText: '正在加载中...',
+        idleText: '上拉加载',
+        failedText: '网络异常',
+        noDataText: '没有更多数据');
+}

+ 944 - 0
lib/widget/popupButton_my.dart

@@ -0,0 +1,944 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+import 'package:flutter/material.dart';
+import 'dart:async';
+
+import 'package:flutter/foundation.dart';
+import 'package:flutter/widgets.dart';
+
+
+
+// Examples can assume:
+// enum Commands { heroAndScholar, hurricaneCame }
+// dynamic _heroAndScholar;
+// dynamic _selection;
+// BuildContext context;
+// void setState(VoidCallback fn) { }
+
+const Duration _kMenuDuration = Duration(milliseconds: 300);
+const double _kBaselineOffsetFromBottom = 20.0;
+const double _kMenuCloseIntervalEnd = 2.0 / 3.0;
+const double _kMenuHorizontalPadding = 16.0;
+const double _kMenuItemHeight = 48.0;
+const double _kMenuDividerHeight = 16.0;
+const double _kMenuMaxWidth = 5.0 * _kMenuWidthStep;
+const double _kMenuMinWidth = 2.0 * _kMenuWidthStep;
+const double _kMenuVerticalPadding = 8.0;
+const double _kMenuWidthStep = 56.0;
+const double _kMenuScreenPadding = 8.0;
+
+/// A base class for entries in a material design popup menu.
+///
+/// The popup menu widget uses this interface to interact with the menu items.
+/// To show a popup menu, use the [showMenu] function. To create a button that
+/// shows a popup menu, consider using [MyPopupMenuButton].
+///
+/// The type `T` is the type of the value(s) the entry represents. All the
+/// entries in a given menu must represent values with consistent types.
+///
+/// A [MyPopupMenuEntry] may represent multiple values, for example a row with
+/// several icons, or a single entry, for example a menu item with an icon (see
+/// [MyPopupMenuItem]), or no value at all (for example, [MyPopupMenuDivider]).
+///
+/// See also:
+///
+///  * [MyPopupMenuItem], a popup menu entry for a single value.
+///  * [MyPopupMenuDivider], a popup menu entry that is just a horizontal line.
+///  * [CheckedMyPopupMenuItem], a popup menu item with a checkmark.
+///  * [showMenu], a method to dynamically show a popup menu at a given location.
+///  * [MyPopupMenuButton], an [IconButton] that automatically shows a menu when
+///    it is tapped.
+abstract class MyPopupMenuEntry<T> extends StatefulWidget {
+  /// Abstract const constructor. This constructor enables subclasses to provide
+  /// const constructors so that they can be used in const expressions.
+  const MyPopupMenuEntry({ Key key }) : super(key: key);
+
+  /// The amount of vertical space occupied by this entry.
+  ///
+  /// This value is used at the time the [showMenu] method is called, if the
+  /// `initialValue` argument is provided, to determine the position of this
+  /// entry when aligning the selected entry over the given `position`. It is
+  /// otherwise ignored.
+  double get height;
+
+  /// Whether this entry represents a particular value.
+  ///
+  /// This method is used by [showMenu], when it is called, to align the entry
+  /// representing the `initialValue`, if any, to the given `position`, and then
+  /// later is called on each entry to determine if it should be highlighted (if
+  /// the method returns true, the entry will have its background color set to
+  /// the ambient [ThemeData.highlightColor]). If `initialValue` is null, then
+  /// this method is not called.
+  ///
+  /// If the [MyPopupMenuEntry] represents a single value, this should return true
+  /// if the argument matches that value. If it represents multiple values, it
+  /// should return true if the argument matches any of them.
+  bool represents(T value);
+}
+
+/// A horizontal divider in a material design popup menu.
+///
+/// This widget adapts the [Divider] for use in popup menus.
+///
+/// See also:
+///
+///  * [MyPopupMenuItem], for the kinds of items that this widget divides.
+///  * [showMenu], a method to dynamically show a popup menu at a given location.
+///  * [MyPopupMenuButton], an [IconButton] that automatically shows a menu when
+///    it is tapped.
+// ignore: prefer_void_to_null, https://github.com/dart-lang/sdk/issues/34416
+class MyPopupMenuDivider extends MyPopupMenuEntry<Null> {
+  /// Creates a horizontal divider for a popup menu.
+  ///
+  /// By default, the divider has a height of 16 logical pixels.
+  const MyPopupMenuDivider({ Key key, this.height = _kMenuDividerHeight }) : super(key: key);
+
+  /// The height of the divider entry.
+  ///
+  /// Defaults to 16 pixels.
+  @override
+  final double height;
+
+  @override
+  // ignore: prefer_void_to_null, https://github.com/dart-lang/sdk/issues/34416
+  bool represents(Null value) => false;
+
+  @override
+  _MyPopupMenuDividerState createState() => _MyPopupMenuDividerState();
+}
+
+class _MyPopupMenuDividerState extends State<MyPopupMenuDivider> {
+  @override
+  Widget build(BuildContext context) => Divider(height: widget.height);
+}
+
+/// An item in a material design popup menu.
+///
+/// To show a popup menu, use the [showMenu] function. To create a button that
+/// shows a popup menu, consider using [MyPopupMenuButton].
+///
+/// To show a checkmark next to a popup menu item, consider using
+/// [CheckedMyPopupMenuItem].
+///
+/// Typically the [child] of a [MyPopupMenuItem] is a [Text] widget. More
+/// elaborate menus with icons can use a [ListTile]. By default, a
+/// [MyPopupMenuItem] is 48 pixels high. If you use a widget with a different
+/// height, it must be specified in the [height] property.
+///
+/// {@tool sample}
+///
+/// Here, a [Text] widget is used with a popup menu item. The `WhyFarther` type
+/// is an enum, not shown here.
+///
+/// ```dart
+/// const MyPopupMenuItem<WhyFarther>(
+///   value: WhyFarther.harder,
+///   child: Text('Working a lot harder'),
+/// )
+/// ```
+/// {@end-tool}
+///
+/// See the example at [MyPopupMenuButton] for how this example could be used in a
+/// complete menu, and see the example at [CheckedMyPopupMenuItem] for one way to
+/// keep the text of [MyPopupMenuItem]s that use [Text] widgets in their [child]
+/// slot aligned with the text of [CheckedMyPopupMenuItem]s or of [MyPopupMenuItem]
+/// that use a [ListTile] in their [child] slot.
+///
+/// See also:
+///
+///  * [MyPopupMenuDivider], which can be used to divide items from each other.
+///  * [CheckedMyPopupMenuItem], a variant of [MyPopupMenuItem] with a checkmark.
+///  * [showMenu], a method to dynamically show a popup menu at a given location.
+///  * [MyPopupMenuButton], an [IconButton] that automatically shows a menu when
+///    it is tapped.
+class MyPopupMenuItem<T> extends MyPopupMenuEntry<T> {
+  /// Creates an item for a popup menu.
+  ///
+  /// By default, the item is [enabled].
+  ///
+  /// The `height` and `enabled` arguments must not be null.
+  const MyPopupMenuItem({
+    Key key,
+    this.value,
+    this.enabled = true,
+    this.height = _kMenuItemHeight,
+    @required this.child,
+  }) : assert(enabled != null),
+       assert(height != null),
+       super(key: key);
+
+  /// The value that will be returned by [showMenu] if this entry is selected.
+  final T value;
+
+  /// Whether the user is permitted to select this entry.
+  ///
+  /// Defaults to true. If this is false, then the item will not react to
+  /// touches.
+  final bool enabled;
+
+  /// The height of the entry.
+  ///
+  /// Defaults to 48 pixels.
+  @override
+  final double height;
+
+  /// The widget below this widget in the tree.
+  ///
+  /// Typically a single-line [ListTile] (for menus with icons) or a [Text]. An
+  /// appropriate [DefaultTextStyle] is put in scope for the child. In either
+  /// case, the text should be short enough that it won't wrap.
+  final Widget child;
+
+  @override
+  bool represents(T value) => value == this.value;
+
+  @override
+  MyPopupMenuItemState<T, MyPopupMenuItem<T>> createState() => MyPopupMenuItemState<T, MyPopupMenuItem<T>>();
+}
+
+/// The [State] for [MyPopupMenuItem] subclasses.
+///
+/// By default this implements the basic styling and layout of Material Design
+/// popup menu items.
+///
+/// The [buildChild] method can be overridden to adjust exactly what gets placed
+/// in the menu. By default it returns [MyPopupMenuItem.child].
+///
+/// The [handleTap] method can be overridden to adjust exactly what happens when
+/// the item is tapped. By default, it uses [Navigator.pop] to return the
+/// [MyPopupMenuItem.value] from the menu route.
+///
+/// This class takes two type arguments. The second, `W`, is the exact type of
+/// the [Widget] that is using this [State]. It must be a subclass of
+/// [MyPopupMenuItem]. The first, `T`, must match the type argument of that widget
+/// class, and is the type of values returned from this menu.
+class MyPopupMenuItemState<T, W extends MyPopupMenuItem<T>> extends State<W> {
+  /// The menu item contents.
+  ///
+  /// Used by the [build] method.
+  ///
+  /// By default, this returns [MyPopupMenuItem.child]. Override this to put
+  /// something else in the menu entry.
+  @protected
+  Widget buildChild() => widget.child;
+
+  /// The handler for when the user selects the menu item.
+  ///
+  /// Used by the [InkWell] inserted by the [build] method.
+  ///
+  /// By default, uses [Navigator.pop] to return the [MyPopupMenuItem.value] from
+  /// the menu route.
+  @protected
+  void handleTap() {
+    Navigator.pop<T>(context, widget.value);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final ThemeData theme = Theme.of(context);
+    TextStyle style = theme.textTheme.subhead;
+    if (!widget.enabled)
+      style = style.copyWith(color: theme.disabledColor);
+
+    Widget item = AnimatedDefaultTextStyle(
+      style: style,
+      duration: kThemeChangeDuration,
+      child: Baseline(
+        baseline: widget.height - _kBaselineOffsetFromBottom,
+        baselineType: style.textBaseline,
+        child: buildChild(),
+      )
+    );
+    if (!widget.enabled) {
+      final bool isDark = theme.brightness == Brightness.dark;
+      item = IconTheme.merge(
+        data: IconThemeData(color:Theme.of(context).highlightColor,opacity: isDark ? 0.5 : 0.38),
+        child: item,
+
+      );
+    }
+
+    return InkWell(
+      onTap: widget.enabled ? handleTap : null,
+      child: Container(
+        // color: Color(0xFF3A3D5C),
+        height: widget.height,
+        padding: const EdgeInsets.symmetric(horizontal: _kMenuHorizontalPadding),
+        child: item,
+      ),
+    );
+  }
+}
+
+/// An item with a checkmark in a material design popup menu.
+///
+/// To show a popup menu, use the [showMenu] function. To create a button that
+/// shows a popup menu, consider using [MyPopupMenuButton].
+///
+/// A [CheckedMyPopupMenuItem] is 48 pixels high, which matches the default height
+/// of a [MyPopupMenuItem]. The horizontal layout uses a [ListTile]; the checkmark
+/// is an [Icons.done] icon, shown in the [ListTile.leading] position.
+///
+/// {@tool sample}
+/// 
+/// 
+///
+/// Suppose a `Commands` enum exists that lists the possible commands from a
+/// particular popup menu, including `Commands.heroAndScholar` and
+/// `Commands.hurricaneCame`, and further suppose that there is a
+/// `_heroAndScholar` member field which is a boolean. The example below shows a
+/// menu with one menu item with a checkmark that can toggle the boolean, and
+/// one menu item without a checkmark for selecting the second option. (It also
+/// shows a divider placed between the two menu items.)
+///
+/// ```dart
+/// MyPopupMenuButton<Commands>(
+///   onSelected: (Commands result) {
+///     switch (result) {
+///       case Commands.heroAndScholar:
+///         setState(() { _heroAndScholar = !_heroAndScholar; });
+///         break;
+///       case Commands.hurricaneCame:
+///         // ...handle hurricane option
+///         break;
+///       // ...other items handled here
+/// 
+///     }
+///   },
+///   itemBuilder: (BuildContext context) => <MyPopupMenuEntry<Commands>>[
+///     CheckedMyPopupMenuItem<Commands>(
+///       checked: _heroAndScholar,
+///       value: Commands.heroAndScholar,
+///       child: const Text('Hero and scholar'),
+///     ),
+///     const MyPopupMenuDivider(),
+///     const MyPopupMenuItem<Commands>(
+///       value: Commands.hurricaneCame,
+///       child: ListTile(leading: Icon(null), title: Text('Bring hurricane')),
+///     ),
+///     // ...other items listed here
+///   ],
+/// )
+/// ```
+/// {@end-tool}
+///
+/// In particular, observe how the second menu item uses a [ListTile] with a
+/// blank [Icon] in the [ListTile.leading] position to get the same alignment as
+/// the item with the checkmark.
+///
+/// See also:
+///
+///  * [MyPopupMenuItem], a popup menu entry for picking a command (as opposed to
+///    toggling a value).
+///  * [MyPopupMenuDivider], a popup menu entry that is just a horizontal line.
+///  * [showMenu], a method to dynamically show a popup menu at a given location.
+///  * [MyPopupMenuButton], an [IconButton] that automatically shows a menu when
+///    it is tapped.
+class CheckedMyPopupMenuItem<T> extends MyPopupMenuItem<T> {
+  /// Creates a popup menu item with a checkmark.
+  ///
+  /// By default, the menu item is [enabled] but unchecked. To mark the item as
+  /// checked, set [checked] to true.
+  ///
+  /// The `checked` and `enabled` arguments must not be null.
+  const CheckedMyPopupMenuItem({
+    Key key,
+    T value,
+    this.checked = false,
+    bool enabled = true,
+    Widget child,
+  }) : assert(checked != null),
+       super(
+    key: key,
+    value: value,
+    enabled: enabled,
+    child: child,
+  );
+
+  /// Whether to display a checkmark next to the menu item.
+  ///
+  /// Defaults to false.
+  ///
+  /// When true, an [Icons.done] checkmark is displayed.
+  ///
+  /// When this popup menu item is selected, the checkmark will fade in or out
+  /// as appropriate to represent the implied new state.
+  final bool checked;
+
+  /// The widget below this widget in the tree.
+  ///
+  /// Typically a [Text]. An appropriate [DefaultTextStyle] is put in scope for
+  /// the child. The text should be short enough that it won't wrap.
+  ///
+  /// This widget is placed in the [ListTile.title] slot of a [ListTile] whose
+  /// [ListTile.leading] slot is an [Icons.done] icon.
+  @override
+  Widget get child => super.child;
+
+  @override
+  _CheckedMyPopupMenuItemState<T> createState() => _CheckedMyPopupMenuItemState<T>();
+}
+
+class _CheckedMyPopupMenuItemState<T> extends MyPopupMenuItemState<T, CheckedMyPopupMenuItem<T>> with SingleTickerProviderStateMixin {
+  static const Duration _fadeDuration = Duration(milliseconds: 150);
+  AnimationController _controller;
+  Animation<double> get _opacity => _controller.view;
+
+  @override
+  void initState() {
+    super.initState();
+    _controller = AnimationController(duration: _fadeDuration, vsync: this)
+      ..value = widget.checked ? 1.0 : 0.0
+      ..addListener(() => setState(() { /* animation changed */ }));
+  }
+
+  @override
+  void handleTap() {
+    // This fades the checkmark in or out when tapped.
+    if (widget.checked)
+      _controller.reverse();
+    else
+      _controller.forward();
+    super.handleTap();
+  }
+
+  @override
+  Widget buildChild() {
+    return ListTile(
+      enabled: widget.enabled,
+      leading: FadeTransition(
+        opacity: _opacity,
+        child: Icon(_controller.isDismissed ? null : Icons.done)
+      ),
+      title: widget.child,
+    );
+  }
+}
+
+class _MyPopupMenu<T> extends StatelessWidget {
+  const _MyPopupMenu({
+    Key key,
+    this.route,
+    this.semanticLabel,
+  }) : super(key: key);
+
+  final _MyPopupMenuRoute<T> route;
+  final String semanticLabel;
+
+  @override
+  Widget build(BuildContext context) {
+    final double unit = 1.0 / (route.items.length + 1.5); // 1.0 for the width and 0.5 for the last item's fade.
+    final List<Widget> children = <Widget>[];
+
+    for (int i = 0; i < route.items.length; i += 1) {
+      final double start = (i + 1) * unit;
+      final double end = (start + 1.5 * unit).clamp(0.0, 1.0);
+      final CurvedAnimation opacity = CurvedAnimation(
+        parent: route.animation,
+        curve: Interval(start, end)
+      );
+      Widget item = route.items[i];
+      if (route.initialValue != null && route.items[i].represents(route.initialValue)) {
+        item = Container(
+          color: Theme.of(context).highlightColor,
+          child: item,
+        );
+      }
+      children.add(FadeTransition(
+        opacity: opacity,
+        child: item,
+      ));
+    }
+
+    final CurveTween opacity = CurveTween(curve: const Interval(0.0, 1.0 / 3.0));
+    final CurveTween width = CurveTween(curve: Interval(0.0, unit));
+    final CurveTween height = CurveTween(curve: Interval(0.0, unit * route.items.length));
+
+    final Widget child = ConstrainedBox(
+      constraints: const BoxConstraints(
+        minWidth: _kMenuMinWidth,
+        maxWidth: _kMenuMaxWidth,
+      ),
+      child: IntrinsicWidth(
+        stepWidth: _kMenuWidthStep,
+        child: Semantics(
+          scopesRoute: true,
+          namesRoute: true,
+          explicitChildNodes: true,
+          label: semanticLabel,
+          child: Container(
+            color: Color(0xFF3A3D5C),
+            child: SingleChildScrollView(
+            padding: const EdgeInsets.symmetric(
+              vertical: _kMenuVerticalPadding
+            ),
+            child: ListBody(children: children),
+          ),
+          ),
+        ),
+      ),
+    );
+
+    return AnimatedBuilder(
+      animation: route.animation,
+      builder: (BuildContext context, Widget child) {
+        return Opacity(
+          opacity: opacity.evaluate(route.animation),
+          child: Material(
+            type: MaterialType.card,
+            elevation: route.elevation,
+            child: Align(
+              alignment: AlignmentDirectional.topEnd,
+              widthFactor: width.evaluate(route.animation),
+              heightFactor: height.evaluate(route.animation),
+              child: child,
+            ),
+          ),
+        );
+      },
+      child: child,
+    );
+  }
+}
+
+// Positioning of the menu on the screen.
+class _MyPopupMenuRouteLayout extends SingleChildLayoutDelegate {
+  _MyPopupMenuRouteLayout(this.position, this.selectedItemOffset, this.textDirection);
+
+  // Rectangle of underlying button, relative to the overlay's dimensions.
+  final RelativeRect position;
+
+  // The distance from the top of the menu to the middle of selected item.
+  //
+  // This will be null if there's no item to position in this way.
+  final double selectedItemOffset;
+
+  // Whether to prefer going to the left or to the right.
+  final TextDirection textDirection;
+
+  // We put the child wherever position specifies, so long as it will fit within
+  // the specified parent size padded (inset) by 8. If necessary, we adjust the
+  // child's position so that it fits.
+
+  @override
+  BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
+    // The menu can be at most the size of the overlay minus 8.0 pixels in each
+    // direction.
+    return BoxConstraints.loose(constraints.biggest - const Offset(_kMenuScreenPadding * 2.0, _kMenuScreenPadding * 2.0));
+  }
+
+  @override
+  Offset getPositionForChild(Size size, Size childSize) {
+    // size: The size of the overlay.
+    // childSize: The size of the menu, when fully open, as determined by
+    // getConstraintsForChild.
+
+    // Find the ideal vertical position.
+    double y;
+    if (selectedItemOffset == null) {
+      y = position.top;
+    } else {
+      y = position.top + (size.height - position.top - position.bottom) / 2.0 - selectedItemOffset;
+    }
+
+    // Find the ideal horizontal position.
+    double x;
+    if (position.left > position.right) {
+      // Menu button is closer to the right edge, so grow to the left, aligned to the right edge.
+      x = size.width - position.right - childSize.width;
+    } else if (position.left < position.right) {
+      // Menu button is closer to the left edge, so grow to the right, aligned to the left edge.
+      x = position.left;
+    } else {
+      // Menu button is equidistant from both edges, so grow in reading direction.
+      assert(textDirection != null);
+      switch (textDirection) {
+        case TextDirection.rtl:
+          x = size.width - position.right - childSize.width;
+          break;
+        case TextDirection.ltr:
+          x = position.left;
+          break;
+      }
+    }
+
+    // Avoid going outside an area defined as the rectangle 8.0 pixels from the
+    // edge of the screen in every direction.
+    if (x < _kMenuScreenPadding)
+      x = _kMenuScreenPadding;
+    else if (x + childSize.width > size.width - _kMenuScreenPadding)
+      x = size.width - childSize.width - _kMenuScreenPadding;
+    if (y < _kMenuScreenPadding)
+      y = _kMenuScreenPadding;
+    else if (y + childSize.height > size.height - _kMenuScreenPadding)
+      y = size.height - childSize.height - _kMenuScreenPadding;
+    return Offset(x, y);
+  }
+
+  @override
+  bool shouldRelayout(_MyPopupMenuRouteLayout oldDelegate) {
+    return position != oldDelegate.position;
+  }
+}
+
+class _MyPopupMenuRoute<T> extends PopupRoute<T> {
+  _MyPopupMenuRoute({
+    this.position,
+    this.items,
+    this.initialValue,
+    this.elevation,
+    this.theme,
+    this.barrierLabel,
+    this.semanticLabel,
+  });
+
+  final RelativeRect position;
+  final List<MyPopupMenuEntry<T>> items;
+  final dynamic initialValue;
+  final double elevation;
+  final ThemeData theme;
+  final String semanticLabel;
+
+  @override
+  Animation<double> createAnimation() {
+    return CurvedAnimation(
+      parent: super.createAnimation(),
+      curve: Curves.linear,
+      reverseCurve: const Interval(0.0, _kMenuCloseIntervalEnd)
+    );
+  }
+
+  @override
+  Duration get transitionDuration => _kMenuDuration;
+
+  @override
+  bool get barrierDismissible => true;
+
+  @override
+  Color get barrierColor => null;
+
+  @override
+  final String barrierLabel;
+
+  @override
+  Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
+    double selectedItemOffset;
+    if (initialValue != null) {
+      double y = _kMenuVerticalPadding;
+      for (MyPopupMenuEntry<T> entry in items) {
+        if (entry.represents(initialValue)) {
+          selectedItemOffset = y + entry.height / 2.0-54;
+          break;
+        }
+        y += entry.height;
+      }
+    }
+
+    Widget menu = _MyPopupMenu<T>(route: this, semanticLabel: semanticLabel);
+    if (theme != null)
+      menu = Theme(data: theme, child: menu);
+
+    return MediaQuery.removePadding(
+      context: context,
+      removeTop: true,
+      removeBottom: true,
+      removeLeft: true,
+      removeRight: true,
+      child: Builder(
+        builder: (BuildContext context) {
+          return CustomSingleChildLayout(
+            delegate: _MyPopupMenuRouteLayout(
+              position,
+              selectedItemOffset,
+              Directionality.of(context),
+            ),
+            child: menu,
+          );
+        },
+      ),
+    );
+  }
+}
+
+/// Show a popup menu that contains the `items` at `position`.
+///
+/// If `initialValue` is specified then the first item with a matching value
+/// will be highlighted and the value of `position` gives the rectangle whose
+/// vertical center will be aligned with the vertical center of the highlighted
+/// item (when possible).
+///
+/// If `initialValue` is not specified then the top of the menu will be aligned
+/// with the top of the `position` rectangle.
+///
+/// In both cases, the menu position will be adjusted if necessary to fit on the
+/// screen.
+///
+/// Horizontally, the menu is positioned so that it grows in the direction that
+/// has the most room. For example, if the `position` describes a rectangle on
+/// the left edge of the screen, then the left edge of the menu is aligned with
+/// the left edge of the `position`, and the menu grows to the right. If both
+/// edges of the `position` are equidistant from the opposite edge of the
+/// screen, then the ambient [Directionality] is used as a tie-breaker,
+/// preferring to grow in the reading direction.
+///
+/// The positioning of the `initialValue` at the `position` is implemented by
+/// iterating over the `items` to find the first whose
+/// [MyPopupMenuEntry.represents] method returns true for `initialValue`, and then
+/// summing the values of [MyPopupMenuEntry.height] for all the preceding widgets
+/// in the list.
+///
+/// The `elevation` argument specifies the z-coordinate at which to place the
+/// menu. The elevation defaults to 8, the appropriate elevation for popup
+/// menus.
+///
+/// The `context` argument is used to look up the [Navigator] and [Theme] for
+/// the menu. It is only used when the method is called. Its corresponding
+/// widget can be safely removed from the tree before the popup menu is closed.
+///
+/// The `semanticLabel` argument is used by accessibility frameworks to
+/// announce screen transitions when the menu is opened and closed. If this
+/// label is not provided, it will default to
+/// [MaterialLocalizations.MyPopupMenuLabel].
+///
+/// See also:
+///
+///  * [MyPopupMenuItem], a popup menu entry for a single value.
+///  * [MyPopupMenuDivider], a popup menu entry that is just a horizontal line.
+///  * [CheckedMyPopupMenuItem], a popup menu item with a checkmark.
+///  * [MyPopupMenuButton], which provides an [IconButton] that shows a menu by
+///    calling this method automatically.
+///  * [SemanticsConfiguration.namesRoute], for a description of edge triggered
+///    semantics.
+Future<T> showMenu<T>({
+  @required BuildContext context,
+  RelativeRect position,
+  @required List<MyPopupMenuEntry<T>> items,
+  T initialValue,
+  double elevation = 8.0,
+  String semanticLabel,
+}) {
+  assert(context != null);
+  assert(items != null && items.isNotEmpty);
+  assert(debugCheckHasMaterialLocalizations(context));
+  String label = semanticLabel;
+  switch (defaultTargetPlatform) {
+    case TargetPlatform.iOS:
+      label = semanticLabel;
+      break;
+    case TargetPlatform.android:
+    case TargetPlatform.fuchsia:
+      // label = semanticLabel ?? MaterialLocalizations.of(context)?.MyPopupMenuLabel;
+  }
+
+  return Navigator.push(context, _MyPopupMenuRoute<T>(
+    position: position,
+    items: items,
+    initialValue: initialValue,
+    elevation: elevation,
+    semanticLabel: label,
+    theme: Theme.of(context, shadowThemeOnly: true),
+    barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
+  ));
+}
+
+/// Signature for the callback invoked when a menu item is selected. The
+/// argument is the value of the [MyPopupMenuItem] that caused its menu to be
+/// dismissed.
+///
+/// Used by [MyPopupMenuButton.onSelected].
+typedef MyPopupMenuItemSelected<T> = void Function(T value);
+
+/// Signature for the callback invoked when a [MyPopupMenuButton] is dismissed
+/// without selecting an item.
+///
+/// Used by [MyPopupMenuButton.onCanceled].
+typedef MyPopupMenuCanceled = void Function();
+
+/// Signature used by [MyPopupMenuButton] to lazily construct the items shown when
+/// the button is pressed.
+///
+/// Used by [MyPopupMenuButton.itemBuilder].
+typedef MyPopupMenuItemBuilder<T> = List<MyPopupMenuEntry<T>> Function(BuildContext context);
+
+/// Displays a menu when pressed and calls [onSelected] when the menu is dismissed
+/// because an item was selected. The value passed to [onSelected] is the value of
+/// the selected menu item.
+///
+/// One of [child] or [icon] may be provided, but not both. If [icon] is provided,
+/// then [MyPopupMenuButton] behaves like an [IconButton].
+///
+/// If both are null, then a standard overflow icon is created (depending on the
+/// platform).
+///
+/// {@tool sample}
+///
+/// This example shows a menu with four items, selecting between an enum's
+/// values and setting a `_selection` field based on the selection.
+///
+/// ```dart
+/// // This is the type used by the popup menu below.
+/// enum WhyFarther { harder, smarter, selfStarter, tradingCharter }
+///
+/// // This menu button widget updates a _selection field (of type WhyFarther,
+/// // not shown here).
+/// MyPopupMenuButton<WhyFarther>(
+///   onSelected: (WhyFarther result) { setState(() { _selection = result; }); },
+///   itemBuilder: (BuildContext context) => <MyPopupMenuEntry<WhyFarther>>[
+///     const MyPopupMenuItem<WhyFarther>(
+///       value: WhyFarther.harder,
+///       child: Text('Working a lot harder'),
+///     ),
+///     const MyPopupMenuItem<WhyFarther>(
+///       value: WhyFarther.smarter,
+///       child: Text('Being a lot smarter'),
+///     ),
+///     const MyPopupMenuItem<WhyFarther>(
+///       value: WhyFarther.selfStarter,
+///       child: Text('Being a self-starter'),
+///     ),
+///     const MyPopupMenuItem<WhyFarther>(
+///       value: WhyFarther.tradingCharter,
+///       child: Text('Placed in charge of trading charter'),
+///     ),
+///   ],
+/// )
+/// ```
+/// {@end-tool}
+///
+/// See also:
+///
+///  * [MyPopupMenuItem], a popup menu entry for a single value.
+///  * [MyPopupMenuDivider], a popup menu entry that is just a horizontal line.
+///  * [CheckedMyPopupMenuItem], a popup menu item with a checkmark.
+///  * [showMenu], a method to dynamically show a popup menu at a given location.
+class MyPopupMenuButton<T> extends StatefulWidget {
+  /// Creates a button that shows a popup menu.
+  ///
+  /// The [itemBuilder] argument must not be null.
+  const MyPopupMenuButton({
+    Key key,
+    @required this.itemBuilder,
+    this.initialValue,
+    this.onSelected,
+    this.onCanceled,
+    this.tooltip,
+    this.elevation = 8.0,
+    this.padding = const EdgeInsets.all(8.0),
+    this.child,
+    this.icon,
+    this.offset = Offset.zero,
+  }) : assert(itemBuilder != null),
+       assert(offset != null),
+       assert(!(child != null && icon != null)), // fails if passed both parameters
+       super(key: key);
+
+  /// Called when the button is pressed to create the items to show in the menu.
+  final MyPopupMenuItemBuilder<T> itemBuilder;
+
+  /// The value of the menu item, if any, that should be highlighted when the menu opens.
+  final T initialValue;
+
+  /// Called when the user selects a value from the popup menu created by this button.
+  ///
+  /// If the popup menu is dismissed without selecting a value, [onCanceled] is
+  /// called instead.
+  final MyPopupMenuItemSelected<T> onSelected;
+
+  /// Called when the user dismisses the popup menu without selecting an item.
+  ///
+  /// If the user selects a value, [onSelected] is called instead.
+  final MyPopupMenuCanceled onCanceled;
+
+  /// Text that describes the action that will occur when the button is pressed.
+  ///
+  /// This text is displayed when the user long-presses on the button and is
+  /// used for accessibility.
+  final String tooltip;
+
+  /// The z-coordinate at which to place the menu when open. This controls the
+  /// size of the shadow below the menu.
+  ///
+  /// Defaults to 8, the appropriate elevation for popup menus.
+  final double elevation;
+
+  /// Matches IconButton's 8 dps padding by default. In some cases, notably where
+  /// this button appears as the trailing element of a list item, it's useful to be able
+  /// to set the padding to zero.
+  final EdgeInsetsGeometry padding;
+
+  /// If provided, the widget used for this button.
+  final Widget child;
+
+  /// If provided, the icon used for this button.
+  final Icon icon;
+
+  /// The offset applied to the Popup Menu Button.
+  ///
+  /// When not set, the Popup Menu Button will be positioned directly next to
+  /// the button that was used to create it.
+  final Offset offset;
+
+  @override
+  _MyPopupMenuButtonState<T> createState() => _MyPopupMenuButtonState<T>();
+}
+
+class _MyPopupMenuButtonState<T> extends State<MyPopupMenuButton<T>> {
+  void showButtonMenu() {
+    final RenderBox button = context.findRenderObject();
+    final RenderBox overlay = Overlay.of(context).context.findRenderObject();
+    final RelativeRect position = RelativeRect.fromRect(
+      Rect.fromPoints(
+        button.localToGlobal(widget.offset, ancestor: overlay),
+        button.localToGlobal(button.size.bottomRight(Offset.zero), ancestor: overlay),
+      ),
+      Offset.zero & overlay.size,
+    );
+    showMenu<T>(
+      context: context,
+      elevation: widget.elevation,
+      items: widget.itemBuilder(context),
+      initialValue: widget.initialValue,
+      position: position,
+    )
+    .then<void>((T newValue) {
+      if (!mounted)
+        return null;
+      if (newValue == null) {
+        if (widget.onCanceled != null)
+          widget.onCanceled();
+        return null;
+      }
+      if (widget.onSelected != null)
+        widget.onSelected(newValue);
+    });
+  }
+
+  Icon _getIcon(TargetPlatform platform) {
+    assert(platform != null);
+    switch (platform) {
+      case TargetPlatform.android:
+      case TargetPlatform.fuchsia:
+        return const Icon(Icons.more_vert);
+      case TargetPlatform.iOS:
+        return const Icon(Icons.more_horiz);
+    }
+    return null;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    assert(debugCheckHasMaterialLocalizations(context));
+    return widget.child != null
+      ? InkWell(
+          onTap: showButtonMenu,
+          child: widget.child,
+        )
+      : IconButton(
+          icon: widget.icon ?? _getIcon(Theme.of(context).platform),
+          padding: widget.padding,
+          tooltip: widget.tooltip ?? MaterialLocalizations.of(context).showMenuTooltip,
+          onPressed: showButtonMenu,
+        );
+  }
+}

+ 138 - 0
lib/widget/room_item.dart

@@ -0,0 +1,138 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:flutter/cupertino.dart';
+import '../pages/roomInfo.dart';
+
+class RommItem extends StatelessWidget {
+  RommItem({this.roomInfo, this.hasBorder, this.isRage});
+  final Map roomInfo;
+  bool hasBorder = true;
+  bool isRage = false;
+
+
+
+  @override
+  Widget build(BuildContext context) {
+    ScreenUtil.instance = ScreenUtil(width: 375, height: 667)..init(context);
+    Map houseLevelInfo =
+        roomInfo["houseLevelInfo"].isNotEmpty ? roomInfo["houseLevelInfo"] : {};
+
+        Map useRoomInfo=roomInfo.isNotEmpty?roomInfo:{};
+
+    Map imageInfo = {
+      "黄金": Image.asset('images/dengji_icon_huangjin.png',
+          width: ScreenUtil().setWidth(14)),
+      "白银": Image.asset('images/dengji_icon_baiyin.png',
+          width: ScreenUtil().setWidth(14)),
+      "青铜": Image.asset('images/dengji_icon_qingtong.png',
+          width: ScreenUtil().setWidth(14))
+    };
+
+    Map colorInfo = {
+      "黄金": Color(0xFFF9D881),
+      "白银": Color(0xFFAFCAD8),
+      "青铜": Color(0xFFE18D50),
+    };
+
+   
+
+      DecorationImage myIcon=DecorationImage(
+                    image: NetworkImage( useRoomInfo.containsKey('icon')?useRoomInfo["icon"]:''),
+                    fit: BoxFit.cover);
+
+    return FlatButton(
+      color: Color(0xFF464B6A),
+      highlightColor: Color(0xFF35395E),
+      textColor: Colors.white,
+      padding: EdgeInsets.all(0),
+      child: Container(
+        padding: EdgeInsets.all(ScreenUtil().setWidth(15)),
+        height: ScreenUtil().setWidth(78),
+        decoration: BoxDecoration(
+            gradient: LinearGradient(
+          begin: Alignment
+          
+          .bottomRight,
+          colors: [Color(0xFF35395E), Color(0xFF464B6A).withOpacity(0)],
+        )),
+        child: Row(
+          children: <Widget>[
+            Container(
+              width: ScreenUtil().setWidth(48),
+              decoration: BoxDecoration(
+                borderRadius: BorderRadius.all(Radius.circular(2)),
+                image:myIcon,
+              ),
+            ),
+            Expanded(
+              flex: 1,
+              child: Container(
+                margin: EdgeInsets.only(left: 10, right: 10),
+                child: Column(
+                  crossAxisAlignment: CrossAxisAlignment.start,
+                  children: <Widget>[
+                    Row(
+                      children: <Widget>[
+                        LimitedBox(
+                          maxWidth: ScreenUtil().setWidth(170),
+                          child: Text(
+                            roomInfo['houseName'],
+                            style: TextStyle(
+                                color: Colors.white,
+                                fontSize: 14,
+                                fontWeight: FontWeight.w500),
+                                  maxLines:1,
+                          overflow:TextOverflow.ellipsis,
+                          ),
+                        ),
+                        Container(
+                          margin: EdgeInsets.only(left: 6),
+                          child: imageInfo[houseLevelInfo['levelName']],
+                        ),
+                        Container(
+                            margin: EdgeInsets.only(left: 1),
+                            child: Text(
+                              houseLevelInfo['levelName'],
+                              style: TextStyle(
+                                  color: colorInfo[houseLevelInfo['levelName']],
+                                  fontSize: 9),
+                            )),
+                      ],
+                    ),
+                    Text(
+                      roomInfo['houseAbstract'],
+                      style: TextStyle(
+                          fontSize: 12,
+                          fontWeight: FontWeight.w400,
+                          color: Color(0xFF9BA0AE)),
+                          maxLines:2,
+                          overflow:TextOverflow.ellipsis,
+                    )
+                  ],
+                ),
+              ),
+            ),
+            Row(
+              mainAxisAlignment: MainAxisAlignment.center,
+              children: <Widget>[
+                Image.asset('images/icon_renshu.png', width: 20),
+                Text(houseLevelInfo['minNumber'].toString()+'/'+houseLevelInfo['maxNumber'].toString(),
+                style: TextStyle(
+                  fontSize: 14,
+                  fontWeight: FontWeight.w500,
+                  color: Color(0xFFB1B2C0)
+                ),)
+              ],
+            )
+          ],
+        ),
+      ),
+      onPressed: () {
+         Navigator.push(context,
+                  new CupertinoPageRoute(builder: (context) => new RoomInfo(
+                    roomId:roomInfo['id'].toString()
+                  )));
+      },
+    );
+  }
+}

+ 56 - 0
pubspec.yaml

@@ -0,0 +1,56 @@
+name: electric_contest
+description: Universal electric contest
+
+version: 1.0.0+1
+
+environment:
+  sdk: ">=2.0.0-dev.68.0 <3.0.0"
+
+
+dependencies:
+  flutter:
+    sdk: flutter
+  cupertino_icons: ^0.1.2
+  flutter_screenutil: ^0.4.2
+  http: ^0.12.0
+  pull_to_refresh: ^1.1.6
+  dio: ^1.0.14
+  flutter_swiper: ^1.0.6
+  image_picker: ^0.4.10
+  redux: ^3.0.0
+  flutter_redux: ^0.5.2
+  redux_persist: ^0.8.0
+  redux_persist_flutter: ^0.8.0
+
+dev_dependencies:
+  flutter_test:
+    sdk: flutter
+
+flutter:
+  uses-material-design: true
+
+  assets:
+    - images/home_icon_wode.png
+    - images/home_icon_shezhi.png
+    - images/home_icon_yuan.png
+    - images/home_icon_fangjian.png
+    - images/home_icon_kuaisu.png
+    - images/home_icon_sousuo.png
+    - images/home_icon_youjian.png
+    - images/icon_jinbi_da_bai.png
+    - images/icon_qianbao.png
+    - images/icon_bangding.png
+    - images/icon_zhanji.png
+    - images/icon_inter.png
+    - images/img_wodeshouyi.png
+    - images/icon_jinbi_xiao_hong.png
+    - images/dengji_icon_huangjin.png
+    - images/dengji_icon_baiyin.png
+    - images/dengji_icon_qingtong.png
+    - images/icon_renshu.png
+    - images/icon_zhankai_baise.png
+    - images/icon_fenxiang.png
+    - images/icon_jinbi_da_hong.png
+    - images/list_icon_shouji.png
+    - images/list_icon_yanzhengma.png
+    - images/list_icon_del.png

+ 30 - 0
test/widget_test.dart

@@ -0,0 +1,30 @@
+// This is a basic Flutter widget test.
+//
+// To perform an interaction with a widget in your test, use the WidgetTester
+// utility that Flutter provides. For example, you can send tap and scroll
+// gestures. You can also use WidgetTester to find child widgets in the widget
+// tree, read text, and verify that the values of widget properties are correct.
+
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import 'package:electric_contest/main.dart';
+
+void main() {
+  testWidgets('Counter increments smoke test', (WidgetTester tester) async {
+    // Build our app and trigger a frame.
+    await tester.pumpWidget(MyApp());
+
+    // Verify that our counter starts at 0.
+    expect(find.text('0'), findsOneWidget);
+    expect(find.text('1'), findsNothing);
+
+    // Tap the '+' icon and trigger a frame.
+    await tester.tap(find.byIcon(Icons.add));
+    await tester.pump();
+
+    // Verify that our counter has incremented.
+    expect(find.text('0'), findsNothing);
+    expect(find.text('1'), findsOneWidget);
+  });
+}