瀏覽代碼

v0.3.0 pre1

thl 5 年之前
父節點
當前提交
de0d53cea7

+ 11 - 1
README.md

@@ -6,13 +6,23 @@ flustars依赖于Dart常用工具类库[common_utils](https://github.com/Sky24n/
 
 
 ### 注意:
 ### 注意:
 由于path_provider库升级,导致Directory路径发生变更,请暂时不要使用DirectoryUtil,谢谢!!!
 由于path_provider库升级,导致Directory路径发生变更,请暂时不要使用DirectoryUtil,谢谢!!!
+v0.3.0版本package参数已删除!
 
 
 ### 使用方式:
 ### 使用方式:
 ```dart
 ```dart
 dependencies:
 dependencies:
   flustars: ^0.2.6+1
   flustars: ^0.2.6+1
   
   
-import 'package:flustars/flustars.dart';  
+import 'package:flustars/flustars.dart';
+
+
+or
+
+// git (version 0.3.0)
+dependencies:
+  flustars:
+    git:
+      url: git://github.com/Sky24n/flustars.git
 ```
 ```
 
 
 ### 注意
 ### 注意

+ 1 - 0
example/.flutter-plugins-dependencies

@@ -0,0 +1 @@
+{"_info":"// This is a generated file; do not edit or check into version control.","dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]},{"name":"shared_preferences","dependencies":[]}]}

+ 7 - 0
example/android/.gitignore

@@ -0,0 +1,7 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java

+ 3 - 3
example/android/app/build.gradle

@@ -38,7 +38,7 @@ android {
         targetSdkVersion 28
         targetSdkVersion 28
         versionCode flutterVersionCode.toInteger()
         versionCode flutterVersionCode.toInteger()
         versionName flutterVersionName
         versionName flutterVersionName
-        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
     }
     }
 
 
     buildTypes {
     buildTypes {
@@ -56,6 +56,6 @@ flutter {
 
 
 dependencies {
 dependencies {
     testImplementation 'junit:junit:4.12'
     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'
+    androidTestImplementation 'androidx.test:runner:1.1.1'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
 }
 }

+ 7 - 0
example/android/app/src/debug/AndroidManifest.xml

@@ -0,0 +1,7 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.thl.flustars_example">
+    <!-- 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"/>
+</manifest>

+ 6 - 9
example/android/app/src/main/AndroidManifest.xml

@@ -1,6 +1,5 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.thl.flustars_example">
     package="com.thl.flustars_example">
-
     <!-- io.flutter.app.FlutterApplication is an android.app.Application that
     <!-- io.flutter.app.FlutterApplication is an android.app.Application that
          calls FlutterMain.startInitialization(this); in its onCreate method.
          calls FlutterMain.startInitialization(this); in its onCreate method.
          In most cases you can leave this as-is, but you if you want to provide
          In most cases you can leave this as-is, but you if you want to provide
@@ -14,20 +13,18 @@
             android:name=".MainActivity"
             android:name=".MainActivity"
             android:launchMode="singleTop"
             android:launchMode="singleTop"
             android:theme="@style/LaunchTheme"
             android:theme="@style/LaunchTheme"
-            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
+            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
             android:hardwareAccelerated="true"
             android:hardwareAccelerated="true"
             android:windowSoftInputMode="adjustResize">
             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>
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.LAUNCHER"/>
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
             </intent-filter>
         </activity>
         </activity>
+        <!-- Don't delete the meta-data below.
+             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
+        <meta-data
+            android:name="flutterEmbedding"
+            android:value="2" />
     </application>
     </application>
 </manifest>
 </manifest>

+ 5 - 5
example/android/app/src/main/java/com/thl/flustars_example/MainActivity.java

@@ -1,13 +1,13 @@
 package com.thl.flustars_example;
 package com.thl.flustars_example;
 
 
-import android.os.Bundle;
-import io.flutter.app.FlutterActivity;
+import androidx.annotation.NonNull;
+import io.flutter.embedding.android.FlutterActivity;
+import io.flutter.embedding.engine.FlutterEngine;
 import io.flutter.plugins.GeneratedPluginRegistrant;
 import io.flutter.plugins.GeneratedPluginRegistrant;
 
 
 public class MainActivity extends FlutterActivity {
 public class MainActivity extends FlutterActivity {
   @Override
   @Override
-  protected void onCreate(Bundle savedInstanceState) {
-    super.onCreate(savedInstanceState);
-    GeneratedPluginRegistrant.registerWith(this);
+  public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
+    GeneratedPluginRegistrant.registerWith(flutterEngine);
   }
   }
 }
 }

+ 7 - 0
example/android/app/src/profile/AndroidManifest.xml

@@ -0,0 +1,7 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.thl.flustars_example">
+    <!-- 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"/>
+</manifest>

+ 1 - 1
example/android/build.gradle

@@ -5,7 +5,7 @@ buildscript {
     }
     }
 
 
     dependencies {
     dependencies {
-        classpath 'com.android.tools.build:gradle:3.2.1'
+        classpath 'com.android.tools.build:gradle:3.5.0'
     }
     }
 }
 }
 
 

+ 3 - 0
example/android/gradle.properties

@@ -1 +1,4 @@
 org.gradle.jvmargs=-Xmx1536M
 org.gradle.jvmargs=-Xmx1536M
+android.enableR8=true
+android.useAndroidX=true
+android.enableJetifier=true

+ 1 - 1
example/android/gradle/wrapper/gradle-wrapper.properties

@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip

+ 32 - 0
example/ios/.gitignore

@@ -0,0 +1,32 @@
+*.mode1v3
+*.mode2v3
+*.moved-aside
+*.pbxuser
+*.perspectivev3
+**/*sync/
+.sconsign.dblite
+.tags*
+**/.vagrant/
+**/DerivedData/
+Icon?
+**/Pods/
+**/.symlinks/
+profile
+xcuserdata
+**/.generated/
+Flutter/App.framework
+Flutter/Flutter.framework
+Flutter/Flutter.podspec
+Flutter/Generated.xcconfig
+Flutter/app.flx
+Flutter/app.zip
+Flutter/flutter_assets/
+Flutter/flutter_export_environment.sh
+ServiceDefinitions.json
+Runner/GeneratedPluginRegistrant.*
+
+# Exceptions to above rules.
+!default.mode1v3
+!default.mode2v3
+!default.pbxuser
+!default.perspectivev3

+ 1 - 1
example/ios/Flutter/AppFrameworkInfo.plist

@@ -3,7 +3,7 @@
 <plist version="1.0">
 <plist version="1.0">
 <dict>
 <dict>
   <key>CFBundleDevelopmentRegion</key>
   <key>CFBundleDevelopmentRegion</key>
-  <string>en</string>
+  <string>$(DEVELOPMENT_LANGUAGE)</string>
   <key>CFBundleExecutable</key>
   <key>CFBundleExecutable</key>
   <string>App</string>
   <string>App</string>
   <key>CFBundleIdentifier</key>
   <key>CFBundleIdentifier</key>

+ 52 - 34
example/ios/Podfile

@@ -15,51 +15,69 @@ def parse_KV_file(file, separator='=')
   if !File.exists? file_abs_path
   if !File.exists? file_abs_path
     return [];
     return [];
   end
   end
-  pods_ary = []
+  generated_key_values = {}
   skip_line_start_symbols = ["#", "/"]
   skip_line_start_symbols = ["#", "/"]
-  File.foreach(file_abs_path) { |line|
-      next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
-      plugin = line.split(pattern=separator)
-      if plugin.length == 2
-        podname = plugin[0].strip()
-        path = plugin[1].strip()
-        podpath = File.expand_path("#{path}", file_abs_path)
-        pods_ary.push({:name => podname, :path => podpath});
-      else
-        puts "Invalid plugin specification: #{line}"
-      end
-  }
-  return pods_ary
+  File.foreach(file_abs_path) do |line|
+    next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
+    plugin = line.split(pattern=separator)
+    if plugin.length == 2
+      podname = plugin[0].strip()
+      path = plugin[1].strip()
+      podpath = File.expand_path("#{path}", file_abs_path)
+      generated_key_values[podname] = podpath
+    else
+      puts "Invalid plugin specification: #{line}"
+    end
+  end
+  generated_key_values
 end
 end
 
 
 target 'Runner' do
 target 'Runner' do
-  # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
-  # referring to absolute paths on developers' machines.
-  system('rm -rf .symlinks')
-  system('mkdir -p .symlinks/plugins')
+  # Flutter Pod
 
 
-  # Flutter Pods
-  generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig')
-  if generated_xcode_build_settings.empty?
-    puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first."
-  end
-  generated_xcode_build_settings.map { |p|
-    if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
-      symlink = File.join('.symlinks', 'flutter')
-      File.symlink(File.dirname(p[:path]), symlink)
-      pod 'Flutter', :path => File.join(symlink, File.basename(p[:path]))
+  copied_flutter_dir = File.join(__dir__, 'Flutter')
+  copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework')
+  copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec')
+  unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path)
+    # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet.
+    # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration.
+    # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist.
+
+    generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig')
+    unless File.exist?(generated_xcode_build_settings_path)
+      raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first"
+    end
+    generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path)
+    cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR'];
+
+    unless File.exist?(copied_framework_path)
+      FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir)
     end
     end
-  }
+    unless File.exist?(copied_podspec_path)
+      FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir)
+    end
+  end
+
+  # Keep pod path relative so it can be checked into Podfile.lock.
+  pod 'Flutter', :path => 'Flutter'
 
 
   # Plugin Pods
   # Plugin Pods
+
+  # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
+  # referring to absolute paths on developers' machines.
+  system('rm -rf .symlinks')
+  system('mkdir -p .symlinks/plugins')
   plugin_pods = parse_KV_file('../.flutter-plugins')
   plugin_pods = parse_KV_file('../.flutter-plugins')
-  plugin_pods.map { |p|
-    symlink = File.join('.symlinks', 'plugins', p[:name])
-    File.symlink(p[:path], symlink)
-    pod p[:name], :path => File.join(symlink, 'ios')
-  }
+  plugin_pods.each do |name, path|
+    symlink = File.join('.symlinks', 'plugins', name)
+    File.symlink(path, symlink)
+    pod name, :path => File.join(symlink, 'ios')
+  end
 end
 end
 
 
+# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
+install! 'cocoapods', :disable_input_output_paths => true
+
 post_install do |installer|
 post_install do |installer|
   installer.pods_project.targets.each do |target|
   installer.pods_project.targets.each do |target|
     target.build_configurations.each do |config|
     target.build_configurations.each do |config|

+ 34 - 0
example/ios/Podfile.lock

@@ -0,0 +1,34 @@
+PODS:
+  - Flutter (1.0.0)
+  - path_provider (0.0.1):
+    - Flutter
+  - path_provider_macos (0.0.1):
+    - Flutter
+  - shared_preferences (0.0.1):
+    - Flutter
+
+DEPENDENCIES:
+  - Flutter (from `Flutter`)
+  - path_provider (from `.symlinks/plugins/path_provider/ios`)
+  - path_provider_macos (from `.symlinks/plugins/path_provider_macos/ios`)
+  - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
+
+EXTERNAL SOURCES:
+  Flutter:
+    :path: Flutter
+  path_provider:
+    :path: ".symlinks/plugins/path_provider/ios"
+  path_provider_macos:
+    :path: ".symlinks/plugins/path_provider_macos/ios"
+  shared_preferences:
+    :path: ".symlinks/plugins/shared_preferences/ios"
+
+SPEC CHECKSUMS:
+  Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
+  path_provider: fb74bd0465e96b594bb3b5088ee4a4e7bb1f2a9d
+  path_provider_macos: f760a3c5b04357c380e2fddb6f9db6f3015897e0
+  shared_preferences: 1feebfa37bb57264736e16865e7ffae7fc99b523
+
+PODFILE CHECKSUM: 3dbe063e9c90a5d7c9e4e76e70a821b9e2c1d271
+
+COCOAPODS: 1.8.4

+ 76 - 6
example/ios/Runner.xcodeproj/project.pbxproj

@@ -13,12 +13,12 @@
 		3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
 		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 */; };
 		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, ); }; };
 		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 */; };
 		978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
 		97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
 		97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
 		97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
 		97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
 		97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
 		97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
 		97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
 		97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
+		98F29E90827F0A7EABE2A9F5 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6772A771EE0D58CC1176700A /* libPods-Runner.a */; };
 /* End PBXBuildFile section */
 /* End PBXBuildFile section */
 
 
 /* Begin PBXCopyFilesBuildPhase section */
 /* Begin PBXCopyFilesBuildPhase section */
@@ -39,8 +39,11 @@
 /* Begin PBXFileReference section */
 /* Begin PBXFileReference section */
 		1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
 		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>"; };
 		1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
+		208EDB1D91D02C3985E4CE45 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
 		3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
 		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>"; };
 		3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
+		3BBB84AD8B98690574E27263 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
+		6772A771EE0D58CC1176700A /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
 		7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; 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>"; };
 		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>"; };
 		7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
@@ -53,6 +56,7 @@
 		97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; 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>"; };
 		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>"; };
 		97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		CC230F2669B0012A7B5CFA1F /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 /* End PBXFileReference section */
 
 
 /* Begin PBXFrameworksBuildPhase section */
 /* Begin PBXFrameworksBuildPhase section */
@@ -62,12 +66,24 @@
 			files = (
 			files = (
 				9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
 				9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
 				3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
 				3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
+				98F29E90827F0A7EABE2A9F5 /* libPods-Runner.a in Frameworks */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
 /* End PBXFrameworksBuildPhase section */
 /* End PBXFrameworksBuildPhase section */
 
 
 /* Begin PBXGroup section */
 /* Begin PBXGroup section */
+		2A0C40B110814A02113F4872 /* Pods */ = {
+			isa = PBXGroup;
+			children = (
+				208EDB1D91D02C3985E4CE45 /* Pods-Runner.debug.xcconfig */,
+				3BBB84AD8B98690574E27263 /* Pods-Runner.release.xcconfig */,
+				CC230F2669B0012A7B5CFA1F /* Pods-Runner.profile.xcconfig */,
+			);
+			name = Pods;
+			path = Pods;
+			sourceTree = "<group>";
+		};
 		9740EEB11CF90186004384FC /* Flutter */ = {
 		9740EEB11CF90186004384FC /* Flutter */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
@@ -87,7 +103,8 @@
 				9740EEB11CF90186004384FC /* Flutter */,
 				9740EEB11CF90186004384FC /* Flutter */,
 				97C146F01CF9000F007C117D /* Runner */,
 				97C146F01CF9000F007C117D /* Runner */,
 				97C146EF1CF9000F007C117D /* Products */,
 				97C146EF1CF9000F007C117D /* Products */,
-				CF3B75C9A7D2FA2A4C99F110 /* Frameworks */,
+				2A0C40B110814A02113F4872 /* Pods */,
+				D52E43F9952FB4695258CB6E /* Frameworks */,
 			);
 			);
 			sourceTree = "<group>";
 			sourceTree = "<group>";
 		};
 		};
@@ -123,6 +140,14 @@
 			name = "Supporting Files";
 			name = "Supporting Files";
 			sourceTree = "<group>";
 			sourceTree = "<group>";
 		};
 		};
+		D52E43F9952FB4695258CB6E /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				6772A771EE0D58CC1176700A /* libPods-Runner.a */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
 /* End PBXGroup section */
 /* End PBXGroup section */
 
 
 /* Begin PBXNativeTarget section */
 /* Begin PBXNativeTarget section */
@@ -130,12 +155,14 @@
 			isa = PBXNativeTarget;
 			isa = PBXNativeTarget;
 			buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
 			buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
 			buildPhases = (
 			buildPhases = (
+				B7C522AA42A80F34B0CF1355 /* [CP] Check Pods Manifest.lock */,
 				9740EEB61CF901F6004384FC /* Run Script */,
 				9740EEB61CF901F6004384FC /* Run Script */,
 				97C146EA1CF9000F007C117D /* Sources */,
 				97C146EA1CF9000F007C117D /* Sources */,
 				97C146EB1CF9000F007C117D /* Frameworks */,
 				97C146EB1CF9000F007C117D /* Frameworks */,
 				97C146EC1CF9000F007C117D /* Resources */,
 				97C146EC1CF9000F007C117D /* Resources */,
 				9705A1C41CF9048500538489 /* Embed Frameworks */,
 				9705A1C41CF9048500538489 /* Embed Frameworks */,
 				3B06AD1E1E4923F5004D2608 /* Thin Binary */,
 				3B06AD1E1E4923F5004D2608 /* Thin Binary */,
+				416631E430B6D9CC44E84C4B /* [CP] Embed Pods Frameworks */,
 			);
 			);
 			buildRules = (
 			buildRules = (
 			);
 			);
@@ -152,7 +179,7 @@
 		97C146E61CF9000F007C117D /* Project object */ = {
 		97C146E61CF9000F007C117D /* Project object */ = {
 			isa = PBXProject;
 			isa = PBXProject;
 			attributes = {
 			attributes = {
-				LastUpgradeCheck = 0910;
+				LastUpgradeCheck = 1020;
 				ORGANIZATIONNAME = "The Chromium Authors";
 				ORGANIZATIONNAME = "The Chromium Authors";
 				TargetAttributes = {
 				TargetAttributes = {
 					97C146ED1CF9000F007C117D = {
 					97C146ED1CF9000F007C117D = {
@@ -162,7 +189,7 @@
 			};
 			};
 			buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
 			buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
 			compatibilityVersion = "Xcode 3.2";
 			compatibilityVersion = "Xcode 3.2";
-			developmentRegion = English;
+			developmentRegion = en;
 			hasScannedForEncodings = 0;
 			hasScannedForEncodings = 0;
 			knownRegions = (
 			knownRegions = (
 				en,
 				en,
@@ -185,7 +212,6 @@
 			files = (
 			files = (
 				97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
 				97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
 				3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
 				3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
-				9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
 				97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
 				97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
 				97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
 				97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
 			);
 			);
@@ -208,6 +234,21 @@
 			shellPath = /bin/sh;
 			shellPath = /bin/sh;
 			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
 			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
 		};
 		};
+		416631E430B6D9CC44E84C4B /* [CP] Embed Pods Frameworks */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "[CP] Embed Pods Frameworks";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
 		9740EEB61CF901F6004384FC /* Run Script */ = {
 		9740EEB61CF901F6004384FC /* Run Script */ = {
 			isa = PBXShellScriptBuildPhase;
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
@@ -222,6 +263,28 @@
 			shellPath = /bin/sh;
 			shellPath = /bin/sh;
 			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
 			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
 		};
 		};
+		B7C522AA42A80F34B0CF1355 /* [CP] Check Pods Manifest.lock */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
+			);
+			name = "[CP] Check Pods Manifest.lock";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+			showEnvVarsInLog = 0;
+		};
 /* End PBXShellScriptBuildPhase section */
 /* End PBXShellScriptBuildPhase section */
 
 
 /* Begin PBXSourcesBuildPhase section */
 /* Begin PBXSourcesBuildPhase section */
@@ -271,12 +334,14 @@
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_COMMA = YES;
 				CLANG_WARN_COMMA = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
 				CLANG_WARN_INFINITE_RECURSION = YES;
 				CLANG_WARN_INFINITE_RECURSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
 				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
 				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
 				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
 				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
 				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -300,6 +365,7 @@
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				SDKROOT = iphoneos;
 				SDKROOT = iphoneos;
+				SUPPORTED_PLATFORMS = iphoneos;
 				TARGETED_DEVICE_FAMILY = "1,2";
 				TARGETED_DEVICE_FAMILY = "1,2";
 				VALIDATE_PRODUCT = YES;
 				VALIDATE_PRODUCT = YES;
 			};
 			};
@@ -311,7 +377,6 @@
 			buildSettings = {
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
 				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
-				DEVELOPMENT_TEAM = S8QB4VV633;
 				ENABLE_BITCODE = NO;
 				ENABLE_BITCODE = NO;
 				FRAMEWORK_SEARCH_PATHS = (
 				FRAMEWORK_SEARCH_PATHS = (
 					"$(inherited)",
 					"$(inherited)",
@@ -343,12 +408,14 @@
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_COMMA = YES;
 				CLANG_WARN_COMMA = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
 				CLANG_WARN_INFINITE_RECURSION = YES;
 				CLANG_WARN_INFINITE_RECURSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
 				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
 				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
 				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
 				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
 				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -397,12 +464,14 @@
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_COMMA = YES;
 				CLANG_WARN_COMMA = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
 				CLANG_WARN_INFINITE_RECURSION = YES;
 				CLANG_WARN_INFINITE_RECURSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
 				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
 				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
 				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
 				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
 				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -426,6 +495,7 @@
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				SDKROOT = iphoneos;
 				SDKROOT = iphoneos;
+				SUPPORTED_PLATFORMS = iphoneos;
 				TARGETED_DEVICE_FAMILY = "1,2";
 				TARGETED_DEVICE_FAMILY = "1,2";
 				VALIDATE_PRODUCT = YES;
 				VALIDATE_PRODUCT = YES;
 			};
 			};

+ 1 - 3
example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
 <Scheme
-   LastUpgradeVersion = "0910"
+   LastUpgradeVersion = "1020"
    version = "1.3">
    version = "1.3">
    <BuildAction
    <BuildAction
       parallelizeBuildables = "YES"
       parallelizeBuildables = "YES"
@@ -26,7 +26,6 @@
       buildConfiguration = "Debug"
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       shouldUseLaunchSchemeArgsEnv = "YES">
       shouldUseLaunchSchemeArgsEnv = "YES">
       <Testables>
       <Testables>
       </Testables>
       </Testables>
@@ -46,7 +45,6 @@
       buildConfiguration = "Debug"
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       launchStyle = "0"
       launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       useCustomWorkingDirectory = "NO"
       ignoresPersistentStateOnLaunch = "NO"
       ignoresPersistentStateOnLaunch = "NO"

+ 3 - 0
example/ios/Runner.xcworkspace/contents.xcworkspacedata

@@ -4,4 +4,7 @@
    <FileRef
    <FileRef
       location = "group:Runner.xcodeproj">
       location = "group:Runner.xcodeproj">
    </FileRef>
    </FileRef>
+   <FileRef
+      location = "group:Pods/Pods.xcodeproj">
+   </FileRef>
 </Workspace>
 </Workspace>

+ 2 - 2
example/ios/Runner/AppDelegate.m

@@ -1,5 +1,5 @@
-#include "AppDelegate.h"
-#include "GeneratedPluginRegistrant.h"
+#import "AppDelegate.h"
+#import "GeneratedPluginRegistrant.h"
 
 
 @implementation AppDelegate
 @implementation AppDelegate
 
 

二進制
example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png


+ 1 - 1
example/ios/Runner/Info.plist

@@ -3,7 +3,7 @@
 <plist version="1.0">
 <plist version="1.0">
 <dict>
 <dict>
 	<key>CFBundleDevelopmentRegion</key>
 	<key>CFBundleDevelopmentRegion</key>
-	<string>en</string>
+	<string>$(DEVELOPMENT_LANGUAGE)</string>
 	<key>CFBundleExecutable</key>
 	<key>CFBundleExecutable</key>
 	<string>$(EXECUTABLE_NAME)</string>
 	<string>$(EXECUTABLE_NAME)</string>
 	<key>CFBundleIdentifier</key>
 	<key>CFBundleIdentifier</key>

+ 79 - 62
example/lib/main.dart

@@ -2,11 +2,11 @@ import 'package:flustars/flustars.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
 
 
-void main() => runApp(new MyApp());
+void main() => runApp(MyApp());
 
 
 class MyApp extends StatefulWidget {
 class MyApp extends StatefulWidget {
   @override
   @override
-  _MyAppState createState() => new _MyAppState();
+  _MyAppState createState() => _MyAppState();
 }
 }
 
 
 class City {
 class City {
@@ -24,7 +24,7 @@ class City {
 
 
   @override
   @override
   String toString() {
   String toString() {
-    StringBuffer sb = new StringBuffer('{');
+    StringBuffer sb = StringBuffer('{');
     sb.write("\"name\":\"$name\"");
     sb.write("\"name\":\"$name\"");
     sb.write('}');
     sb.write('}');
     return sb.toString();
     return sb.toString();
@@ -54,7 +54,7 @@ class _MyAppState extends State<MyApp> {
 
 
     /// save object example.
     /// save object example.
     /// 存储实体对象示例。
     /// 存储实体对象示例。
-    City city = new City();
+    City city = City();
     city.name = "成都市";
     city.name = "成都市";
     SpUtil.putObject("loc_city", city);
     SpUtil.putObject("loc_city", city);
 
 
@@ -63,9 +63,9 @@ class _MyAppState extends State<MyApp> {
 
 
     /// save object list example.
     /// save object list example.
     /// 存储实体对象list示例。
     /// 存储实体对象list示例。
-    List<City> list = new List();
-    list.add(new City(name: "成都市"));
-    list.add(new City(name: "北京市"));
+    List<City> list = List();
+    list.add(City(name: "成都市"));
+    list.add(City(name: "北京市"));
     SpUtil.putObjectList("loc_city_list", list);
     SpUtil.putObjectList("loc_city_list", list);
 
 
     List<City> dataList =
     List<City> dataList =
@@ -76,8 +76,8 @@ class _MyAppState extends State<MyApp> {
 
 
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
-    return new MaterialApp(
-      home: new MainPage(),
+    return MaterialApp(
+      home: MainPage(),
     );
     );
   }
   }
 }
 }
@@ -85,7 +85,7 @@ class _MyAppState extends State<MyApp> {
 class MainPage extends StatefulWidget {
 class MainPage extends StatefulWidget {
   @override
   @override
   State<StatefulWidget> createState() {
   State<StatefulWidget> createState() {
-    return new MainPageState();
+    return MainPageState();
   }
   }
 }
 }
 
 
@@ -94,6 +94,25 @@ class MainPage extends StatefulWidget {
 /// In MainPage, the dependency-free context method is used to obtain screen parameters and adaptions, which requires a call to [MediaQuery. of (context)] within the build method.
 /// In MainPage, the dependency-free context method is used to obtain screen parameters and adaptions, which requires a call to [MediaQuery. of (context)] within the build method.
 /// Or use context-dependent methods to obtain screen parameters and adaptions.
 /// Or use context-dependent methods to obtain screen parameters and adaptions.
 class MainPageState extends State<MainPage> {
 class MainPageState extends State<MainPage> {
+  void test2() async {
+    await DirectoryUtil.getInstance();
+    String tempPath = DirectoryUtil.getTempPath(
+        category: 'Pictures', fileName: 'demo', format: 'png');
+    print("thll  tempPath: $tempPath");
+    String appDocPath = DirectoryUtil.getAppDocPath(
+        category: 'Pictures', fileName: 'demo', format: 'png');
+    print("thll  appDocPath: $appDocPath");
+    String appSupportPath = DirectoryUtil.getAppSupportPath(
+        category: 'Pictures', fileName: 'demo', format: 'png');
+    print("thll  appSupportPath: $appSupportPath");
+  }
+
+  @override
+  void initState() {
+    super.initState();
+    test2();
+  }
+
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     /// 如果使用依赖不context方法获取屏幕参数及适配,需要调用此方法。
     /// 如果使用依赖不context方法获取屏幕参数及适配,需要调用此方法。
@@ -111,78 +130,76 @@ class MainPageState extends State<MainPage> {
     print(
     print(
         "thll  MainPage statusBar: $statusBar, width: $width, height: $height, density: $density, sp: $sp, spc: $spc, adapterW: $adapterW");
         "thll  MainPage statusBar: $statusBar, width: $width, height: $height, density: $density, sp: $sp, spc: $spc, adapterW: $adapterW");
 
 
-    return new Scaffold(
+    return Scaffold(
       // 一个不需要GlobalKey就可以openDrawer的AppBar
       // 一个不需要GlobalKey就可以openDrawer的AppBar
-      appBar: new MyAppBar(
+      appBar: MyAppBar(
         leading: ClipOval(
         leading: ClipOval(
-          child: new Image.asset(('assets/images/ali_connors.png')),
+          child: Image.asset(('assets/images/ali_connors.png')),
         ),
         ),
         title: const Text('Flustars Demos'),
         title: const Text('Flustars Demos'),
         centerTitle: true,
         centerTitle: true,
         actions: <Widget>[
         actions: <Widget>[
-          new IconButton(
-            icon: new Icon(Icons.search),
+          IconButton(
+            icon: Icon(Icons.search),
             onPressed: () {
             onPressed: () {
-              Navigator.push(
-                  context,
-                  new CupertinoPageRoute<void>(
-                      builder: (ctx) => new SecondPage()));
+              Navigator.push(context,
+                  CupertinoPageRoute<void>(builder: (ctx) => SecondPage()));
             },
             },
           ),
           ),
         ],
         ],
       ),
       ),
-      body: new Column(
+      body: Column(
         crossAxisAlignment: CrossAxisAlignment.start,
         crossAxisAlignment: CrossAxisAlignment.start,
         children: <Widget>[
         children: <Widget>[
-          new Container(
+          Container(
             width: 360.0,
             width: 360.0,
             height: 50,
             height: 50,
             color: Colors.grey,
             color: Colors.grey,
-            child: new Center(
-              child: new Text(
+            child: Center(
+              child: Text(
                 "未适配宽",
                 "未适配宽",
-                style: new TextStyle(fontSize: 24.0),
+                style: TextStyle(fontSize: 24.0),
               ),
               ),
             ),
             ),
           ),
           ),
-          new Container(
+          Container(
             width: ScreenUtil.getInstance().getAdapterSize(360.0),
             width: ScreenUtil.getInstance().getAdapterSize(360.0),
             height: 50,
             height: 50,
             color: Colors.grey,
             color: Colors.grey,
-            child: new Center(
-              child: new Text(
+            child: Center(
+              child: Text(
                 "已适配宽",
                 "已适配宽",
-                style: new TextStyle(fontSize: 24.0),
+                style: TextStyle(fontSize: 24.0),
               ),
               ),
             ),
             ),
           ),
           ),
-          new Container(
+          Container(
             width: 100,
             width: 100,
             height: 100,
             height: 100,
             color: Colors.grey,
             color: Colors.grey,
-            child: new Center(
-              child: new Text(
+            child: Center(
+              child: Text(
                 "你好你好你好",
                 "你好你好你好",
-                style: new TextStyle(fontSize: 24.0),
+                style: TextStyle(fontSize: 24.0),
               ),
               ),
             ),
             ),
           ),
           ),
-          new Container(
+          Container(
             margin: EdgeInsets.only(top: 10.0),
             margin: EdgeInsets.only(top: 10.0),
             width: ScreenUtil.getInstance().getAdapterSize(100.0),
             width: ScreenUtil.getInstance().getAdapterSize(100.0),
             height: ScreenUtil.getInstance().getAdapterSize(100.0),
             height: ScreenUtil.getInstance().getAdapterSize(100.0),
             color: Colors.grey,
             color: Colors.grey,
-            child: new Center(
-              child: new Text(
+            child: Center(
+              child: Text(
                 "你好你好你好",
                 "你好你好你好",
-                style: new TextStyle(
+                style: TextStyle(
                     fontSize: ScreenUtil.getInstance().getAdapterSize(24.0)),
                     fontSize: ScreenUtil.getInstance().getAdapterSize(24.0)),
               ),
               ),
             ),
             ),
           ),
           ),
         ],
         ],
       ),
       ),
-      drawer: new MyDrawer(),
+      drawer: MyDrawer(),
     );
     );
   }
   }
 }
 }
@@ -194,22 +211,22 @@ class MyDrawer extends StatelessWidget {
     double width = ScreenUtil.getInstance().screenWidth;
     double width = ScreenUtil.getInstance().screenWidth;
     double height = ScreenUtil.getInstance().screenHeight;
     double height = ScreenUtil.getInstance().screenHeight;
     print(
     print(
-        " thll  SecondPage statusBar: $statusBar, width: $width, height: $height");
+        " thll  MyDrawer statusBar: $statusBar, width: $width, height: $height");
 
 
-    return new Container(
+    return Container(
       color: Colors.white,
       color: Colors.white,
       width: ScreenUtil.getInstance().getWidth(240),
       width: ScreenUtil.getInstance().getWidth(240),
-      child: new ListView(
+      child: ListView(
         padding: EdgeInsets.zero,
         padding: EdgeInsets.zero,
         children: <Widget>[
         children: <Widget>[
-          new Container(
+          Container(
             color: Colors.teal,
             color: Colors.teal,
             padding:
             padding:
                 EdgeInsets.only(top: ScreenUtil.getInstance().statusBarHeight),
                 EdgeInsets.only(top: ScreenUtil.getInstance().statusBarHeight),
-            child: new Center(
-              child: new Text(
+            child: Center(
+              child: Text(
                 "Sky24n",
                 "Sky24n",
-                style: new TextStyle(fontSize: 16, color: Colors.white),
+                style: TextStyle(fontSize: 16, color: Colors.white),
               ),
               ),
             ),
             ),
             height: 160,
             height: 160,
@@ -223,7 +240,7 @@ class MyDrawer extends StatelessWidget {
 class SecondPage extends StatefulWidget {
 class SecondPage extends StatefulWidget {
   @override
   @override
   State<StatefulWidget> createState() {
   State<StatefulWidget> createState() {
-    return new SecondPageState();
+    return SecondPageState();
   }
   }
 }
 }
 
 
@@ -232,7 +249,7 @@ class SecondPageState extends State<SecondPage> {
   void initState() {
   void initState() {
     super.initState();
     super.initState();
     _init();
     _init();
-    _initWithCtx();
+//    _initWithCtx();
   }
   }
 
 
   void _init() {
   void _init() {
@@ -278,47 +295,47 @@ class SecondPageState extends State<SecondPage> {
     print(
     print(
         "thll  SecondPage statusBar: $statusBar, width: $width, height: $height");
         "thll  SecondPage statusBar: $statusBar, width: $width, height: $height");
 
 
-    return new Scaffold(
-      appBar: new AppBar(
-        title: new Text("Second Page"),
+    return Scaffold(
+      appBar: AppBar(
+        title: Text("Second Page"),
         centerTitle: true,
         centerTitle: true,
       ),
       ),
-      body: new Column(
+      body: Column(
         crossAxisAlignment: CrossAxisAlignment.start,
         crossAxisAlignment: CrossAxisAlignment.start,
         children: <Widget>[
         children: <Widget>[
-          new Container(
+          Container(
             width: 100,
             width: 100,
             height: 100,
             height: 100,
             color: Colors.grey,
             color: Colors.grey,
-            child: new Center(
-              child: new Text(
+            child: Center(
+              child: Text(
                 "你好你好你好",
                 "你好你好你好",
-                style: new TextStyle(fontSize: 24.0),
+                style: TextStyle(fontSize: 24.0),
               ),
               ),
             ),
             ),
           ),
           ),
-          new Container(
+          Container(
             margin: EdgeInsets.only(top: 10.0),
             margin: EdgeInsets.only(top: 10.0),
             width: ScreenUtil.getInstance().getAdapterSize(100.0),
             width: ScreenUtil.getInstance().getAdapterSize(100.0),
             height: ScreenUtil.getInstance().getAdapterSize(100.0),
             height: ScreenUtil.getInstance().getAdapterSize(100.0),
             color: Colors.grey,
             color: Colors.grey,
-            child: new Center(
-              child: new Text(
+            child: Center(
+              child: Text(
                 "你好你好你好",
                 "你好你好你好",
-                style: new TextStyle(
+                style: TextStyle(
                     fontSize: ScreenUtil.getInstance().getAdapterSize(24.0)),
                     fontSize: ScreenUtil.getInstance().getAdapterSize(24.0)),
               ),
               ),
             ),
             ),
           ),
           ),
-          new Container(
+          Container(
             margin: EdgeInsets.only(top: 10.0),
             margin: EdgeInsets.only(top: 10.0),
             width: ScreenUtil.getAdapterSizeCtx(context, 100.0),
             width: ScreenUtil.getAdapterSizeCtx(context, 100.0),
             height: ScreenUtil.getAdapterSizeCtx(context, 100.0),
             height: ScreenUtil.getAdapterSizeCtx(context, 100.0),
             color: Colors.grey,
             color: Colors.grey,
-            child: new Center(
-              child: new Text(
+            child: Center(
+              child: Text(
                 "你好你好你好",
                 "你好你好你好",
-                style: new TextStyle(
+                style: TextStyle(
                     fontSize: ScreenUtil.getAdapterSizeCtx(context, 24.0)),
                     fontSize: ScreenUtil.getAdapterSizeCtx(context, 24.0)),
               ),
               ),
             ),
             ),

+ 28 - 0
flustars.iml

@@ -1,9 +1,17 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <module type="JAVA_MODULE" version="4">
 <module type="JAVA_MODULE" version="4">
+  <component name="FacetManager">
+    <facet type="android" name="Android">
+      <configuration>
+        <option name="ALLOW_USER_CONFIGURATION" value="false" />
+      </configuration>
+    </facet>
+  </component>
   <component name="NewModuleRootManager" inherit-compiler-output="true">
   <component name="NewModuleRootManager" inherit-compiler-output="true">
     <exclude-output />
     <exclude-output />
     <content url="file://$MODULE_DIR$">
     <content url="file://$MODULE_DIR$">
       <sourceFolder url="file://$MODULE_DIR$/lib" isTestSource="false" />
       <sourceFolder url="file://$MODULE_DIR$/lib" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
       <excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
       <excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
       <excludeFolder url="file://$MODULE_DIR$/.idea" />
       <excludeFolder url="file://$MODULE_DIR$/.idea" />
       <excludeFolder url="file://$MODULE_DIR$/.pub" />
       <excludeFolder url="file://$MODULE_DIR$/.pub" />
@@ -11,7 +19,27 @@
       <excludeFolder url="file://$MODULE_DIR$/example/.dart_tool" />
       <excludeFolder url="file://$MODULE_DIR$/example/.dart_tool" />
       <excludeFolder url="file://$MODULE_DIR$/example/.pub" />
       <excludeFolder url="file://$MODULE_DIR$/example/.pub" />
       <excludeFolder url="file://$MODULE_DIR$/example/build" />
       <excludeFolder url="file://$MODULE_DIR$/example/build" />
+      <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/path_provider/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/path_provider/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/path_provider/build" />
+      <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/path_provider/example/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/path_provider/example/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/path_provider/example/build" />
+      <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/path_provider_macos/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/path_provider_macos/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/path_provider_macos/build" />
+      <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/path_provider_macos/example/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/path_provider_macos/example/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/path_provider_macos/example/build" />
+      <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/shared_preferences/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/shared_preferences/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/shared_preferences/build" />
+      <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/shared_preferences/example/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/shared_preferences/example/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/shared_preferences/example/build" />
+      <excludeFolder url="file://$MODULE_DIR$/example/ios/Flutter/App.framework/flutter_assets/packages" />
     </content>
     </content>
+    <orderEntry type="jdk" jdkName="Android API 22 Platform" jdkType="Android SDK" />
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="library" name="Dart SDK" level="project" />
     <orderEntry type="library" name="Dart SDK" level="project" />
     <orderEntry type="library" name="Flutter Plugins" level="project" />
     <orderEntry type="library" name="Flutter Plugins" level="project" />

+ 0 - 2
lib/flustars.dart

@@ -1,7 +1,5 @@
 library flustars;
 library flustars;
 
 
-export 'package:common_utils/common_utils.dart';
-
 export 'src/ui/my_app_bar.dart';
 export 'src/ui/my_app_bar.dart';
 
 
 export 'src/directory_util.dart';
 export 'src/directory_util.dart';

+ 126 - 84
lib/src/directory_util.dart

@@ -1,48 +1,53 @@
 import 'dart:async';
 import 'dart:async';
 import 'dart:io';
 import 'dart:io';
 
 
-import 'package:common_utils/common_utils.dart';
 import 'package:path_provider/path_provider.dart';
 import 'package:path_provider/path_provider.dart';
 import 'package:synchronized/synchronized.dart';
 import 'package:synchronized/synchronized.dart';
 
 
 /// getTemporaryDirectory
 /// getTemporaryDirectory
-/// 指向设备上临时目录的路径,该目录没有备份,适合存储下载文件的缓存。
-/// 此目录中的文件可以随时清除。这不会返回一个新的临时目录。相反,调用者负责在这个目录中创建(和清理)文件或目录。这个目录的作用域是调用应用程序。
+/// 设备上未备份的临时目录的路径,适用于存储下载文件的缓存。
+/// 此目录中的文件可以随时清除。 *不会*返回新的临时目录。 相反,调用者负责在此目录中创建(和清理)文件或目录。 此目录的作用域是调用应用程序。
 /// 在iOS上,它使用“NSCachesDirectory”API。
 /// 在iOS上,它使用“NSCachesDirectory”API。
 /// 在Android上,它在上下文中使用“getCacheDir”API。
 /// 在Android上,它在上下文中使用“getCacheDir”API。
 
 
 /// getApplicationSupportDirectory
 /// getApplicationSupportDirectory
-/// 应用程序可以放置应用程序支持文件的目录的路径。
-/// 对不希望向用户公开的文件使用此选项。您的应用程序不应将此目录用于用户数据文件。
-/// 在iOS上,它使用“NSApplicationSupportDirectory”API。如果此目录不存在,则自动创建。
-/// 在Android上,此函数抛出一个[UnsupportedError]
+/// 应用程序可以在其中放置应用程序支持文件的目录的路径。
+/// 将此文件用于您不想向用户公开的文件。 您的应用不应将此目录用于用户数据文件。
+/// 在iOS上,它使用`NSApplicationSupportDirectory` API。 如果此目录不存在,则会自动创建。
+/// 在Android上,此函数在上下文中使用`getFilesDir` API
 
 
 /// getApplicationDocumentsDirectory
 /// getApplicationDocumentsDirectory
-/// 指向应用程序可以放置用户生成的数据或应用程序无法重新创建的数据的目录路径。
-/// 在iOS上,它使用“NSDocumentDirectory”API。如果数据不是用户生成的,请考虑使用[GetApplicationSupportDirectory]。
-/// 在Android上,这在上下文中使用了“getDataDirectory”API。如果数据对用户可见,请考虑改用getExternalStorageDirectory
+/// 应用程序可能在其中放置用户生成的数据或应用程序无法重新创建的数据的目录路径。
+/// 在iOS上,它使用`NSDocumentDirectory` API。 如果不是用户生成的数据,请考虑使用[getApplicationSupportDirectory]。
+/// 在Android上,它在上下文上使用`getDataDirectory` API。 如果要让用户看到数据,请考虑改用[getExternalStorageDirectory]
 
 
 /// getExternalStorageDirectory
 /// getExternalStorageDirectory
-/// 应用程序可以访问顶层存储的目录的路径。在发出这个函数调用之前,应该确定当前操作系统,因为这个功能只在Android上可用。
+/// 应用程序可以访问顶级存储的目录的路径。在发出此函数调用之前,应确定当前操作系统,因为此功能仅在Android上可用。
 /// 在iOS上,这个函数抛出一个[UnsupportedError],因为它不可能访问应用程序的沙箱之外。
 /// 在iOS上,这个函数抛出一个[UnsupportedError],因为它不可能访问应用程序的沙箱之外。
-/// 在Android上,它使用“getExternalStorageDirectory”API
+/// 在Android上,它使用`getExternalFilesDir(null)`
 
 
 bool _initTempDir = true;
 bool _initTempDir = true;
 bool _initAppDocDir = true;
 bool _initAppDocDir = true;
+bool _initAppSupportDir = true;
 bool _initStorageDir = true;
 bool _initStorageDir = true;
 
 
 /// 配置初始化Directory。
 /// 配置初始化Directory。
-void setInitDir({bool initTempDir, bool initAppDocDir, bool initStorageDir}) {
+void setInitDir({
+  bool initTempDir,
+  bool initAppDocDir,
+  bool initAppSupportDir,
+  bool initStorageDir,
+}) {
   _initTempDir = initTempDir ?? _initTempDir;
   _initTempDir = initTempDir ?? _initTempDir;
   _initAppDocDir = initAppDocDir ?? _initAppDocDir;
   _initAppDocDir = initAppDocDir ?? _initAppDocDir;
+  _initAppSupportDir = initAppSupportDir ?? _initAppSupportDir;
   _initStorageDir = initStorageDir ?? _initStorageDir;
   _initStorageDir = initStorageDir ?? _initStorageDir;
 }
 }
 
 
 /**
 /**
- * @Author: thl
+ * @Author: Sky24n
  * @GitHub: https://github.com/Sky24n
  * @GitHub: https://github.com/Sky24n
- * @JianShu: https://www.jianshu.com/u/cbf2ad25d33a
- * @Email: 863764940@qq.com
+ * @Email: sky24no@gmail.com
  * @Description: Directory Util.
  * @Description: Directory Util.
  * @Date: 2019/05/09
  * @Date: 2019/05/09
  */
  */
@@ -55,6 +60,7 @@ class DirectoryUtil {
 
 
   static Directory _tempDir;
   static Directory _tempDir;
   static Directory _appDocDir;
   static Directory _appDocDir;
+  static Directory _appSupportDir;
   static Directory _storageDir;
   static Directory _storageDir;
 
 
   static Future<DirectoryUtil> getInstance() async {
   static Future<DirectoryUtil> getInstance() async {
@@ -81,39 +87,48 @@ class DirectoryUtil {
     if (_initAppDocDir) {
     if (_initAppDocDir) {
       await initAppDocDir();
       await initAppDocDir();
     }
     }
+    if (_initAppSupportDir) {
+      await initAppSupportDir();
+    }
     if (_initStorageDir) {
     if (_initStorageDir) {
       await initStorageDir();
       await initStorageDir();
     }
     }
   }
   }
 
 
-  static Future initTempDir() async {
+  static Future<Directory> initTempDir() async {
     if (_tempDir == null) {
     if (_tempDir == null) {
       _tempDir = await getTemporaryDirectory();
       _tempDir = await getTemporaryDirectory();
     }
     }
+    return _tempDir;
   }
   }
 
 
-  static Future initAppDocDir() async {
+  static Future<Directory> initAppDocDir() async {
     if (_appDocDir == null) {
     if (_appDocDir == null) {
       _appDocDir = await getApplicationDocumentsDirectory();
       _appDocDir = await getApplicationDocumentsDirectory();
     }
     }
+    return _appDocDir;
   }
   }
 
 
-  static Future initStorageDir() async {
+  static Future<Directory> initAppSupportDir() async {
+    if (_appSupportDir == null) {
+      _appSupportDir = await getApplicationSupportDirectory();
+    }
+    return _appSupportDir;
+  }
+
+  static Future<Directory> initStorageDir() async {
     if (_storageDir == null) {
     if (_storageDir == null) {
       if (Platform.isAndroid) {
       if (Platform.isAndroid) {
         _storageDir = await getExternalStorageDirectory();
         _storageDir = await getExternalStorageDirectory();
       }
       }
-// 考虑旧版兼容问题,暂时屏蔽。该方法在v1.1.0才有。
-//      if (Platform.isIOS) {
-//        _storageDir = await getApplicationSupportDirectory();
-//      }
     }
     }
+    return _storageDir;
   }
   }
 
 
   /// 同步创建文件夹
   /// 同步创建文件夹
   static Directory createDirSync(String path) {
   static Directory createDirSync(String path) {
-    if (ObjectUtil.isEmpty(path)) return null;
-    Directory dir = new Directory(path);
+    if (path == null) return null;
+    Directory dir = Directory(path);
     if (!dir.existsSync()) {
     if (!dir.existsSync()) {
       dir.createSync(recursive: true);
       dir.createSync(recursive: true);
     }
     }
@@ -122,8 +137,8 @@ class DirectoryUtil {
 
 
   /// 异步创建文件夹
   /// 异步创建文件夹
   static Future<Directory> createDir(String path) async {
   static Future<Directory> createDir(String path) async {
-    if (ObjectUtil.isEmpty(path)) return null;
-    Directory dir = new Directory(path);
+    if (path == null) return null;
+    Directory dir = Directory(path);
     bool exist = await dir.exists();
     bool exist = await dir.exists();
     if (!exist) {
     if (!exist) {
       dir = await dir.create(recursive: true);
       dir = await dir.create(recursive: true);
@@ -131,108 +146,135 @@ class DirectoryUtil {
     return dir;
     return dir;
   }
   }
 
 
+  /// get path.
+  /// dir
+  /// category 分类,例如:Download,Pictures, Music等等
   /// fileName 文件名
   /// fileName 文件名
   /// format 文件格式,如果文件名包含格式,则不需要
   /// format 文件格式,如果文件名包含格式,则不需要
-  /// package 顶层文件夹名,默认doc
-  /// category 分类,例如:video,image等等
-  /// String path = DirectoryUtil.getTempPath(fileName: 'demo.png', category: 'image');
-  /// String path = DirectoryUtil.getTempPath(fileName: 'demo', format: 'png', category: 'image');
-  /// Android: /data/user/0/com.thl.flustars_example/cache/doc/image/demo.png
+  static String getPath(
+    Directory dir, {
+    String category,
+    String fileName,
+    String format,
+  }) {
+    if (dir == null) return null;
+    StringBuffer sb = StringBuffer("${dir.path}");
+    if (category != null) sb.write("/$category");
+    if (fileName != null) sb.write("/$fileName");
+    if (format != null) sb.write(".$format");
+    return sb.toString();
+  }
+
+  /// get Temporary Directory file path.
+  /// category 分类,例如:Download,Pictures, Music等等
+  /// fileName 文件名
+  /// format 文件格式,如果文件名包含格式,则不需要
+  /// String path = DirectoryUtil.getTempPath(category: 'Pictures',fileName: 'demo.png');
+  /// String path = DirectoryUtil.getTempPath(category: 'Pictures', fileName: 'demo', format: 'png');
+  /// Android: /data/user/0/com.thl.flustars_example/cache/Pictures/demo.png
   /// iOS: xxx;
   /// iOS: xxx;
   static String getTempPath({
   static String getTempPath({
+    String category,
     String fileName,
     String fileName,
     String format,
     String format,
-    String package = 'doc',
-    String category,
   }) {
   }) {
-    if (_tempDir == null) return null;
-    StringBuffer sb = new StringBuffer("${_tempDir.path}");
-    if (!ObjectUtil.isEmpty(package)) sb.write("/$package");
-    if (!ObjectUtil.isEmpty(category)) sb.write("/$category");
-    if (!ObjectUtil.isEmpty(fileName)) sb.write("/$fileName");
-    if (!ObjectUtil.isEmpty(format)) sb.write(".$format");
-    return sb.toString();
+    return getPath(_tempDir,
+        category: category, fileName: fileName, format: format);
   }
   }
 
 
+  /// get Application Documents Directory file path.
   /// fileName 文件名
   /// fileName 文件名
   /// format 文件格式,如果文件名包含格式,则不需要
   /// format 文件格式,如果文件名包含格式,则不需要
-  /// package 顶层文件夹名,默认doc
-  /// category 分类,例如:video,image等等
-  /// String path = DirectoryUtil.getAppDocPath(fileName: 'demo.mp4', category: 'video');
-  /// String path = DirectoryUtil.getAppDocPath(fileName: 'demo', format: 'mp4', category: 'video');
-  /// Android: /data/user/0/com.thl.flustars_example/app_flutter/doc/video/demo.mp4
+  /// category 分类,例如:Download,Pictures, Music等等
+  /// String path = DirectoryUtil.getAppDocPath(category: 'Pictures', fileName: 'demo.png');
+  /// String path = DirectoryUtil.getAppDocPath(category: 'Pictures', fileName: 'demo', format: 'png');
+  /// Android: /data/user/0/com.thl.flustars_example/app_flutter/Pictures/demo.png
   /// iOS: xxx;
   /// iOS: xxx;
   static String getAppDocPath({
   static String getAppDocPath({
+    String category,
     String fileName,
     String fileName,
     String format,
     String format,
-    String package = 'doc',
-    String category,
   }) {
   }) {
-    if (_appDocDir == null) return null;
-    StringBuffer sb = new StringBuffer("${_appDocDir.path}");
-    if (!ObjectUtil.isEmpty(package)) sb.write("/$package");
-    if (!ObjectUtil.isEmpty(category)) sb.write("/$category");
-    if (!ObjectUtil.isEmpty(fileName)) sb.write("/$fileName");
-    if (!ObjectUtil.isEmpty(format)) sb.write(".$format");
-    return sb.toString();
+    return getPath(_appDocDir,
+        category: category, fileName: fileName, format: format);
   }
   }
 
 
+  /// get Application Support Directory file path.
   /// fileName 文件名
   /// fileName 文件名
   /// format 文件格式,如果文件名包含格式,则不需要
   /// format 文件格式,如果文件名包含格式,则不需要
-  /// package 顶层文件夹名,建议使用包名
   /// category 分类,例如:video,image等等
   /// category 分类,例如:video,image等等
-  /// String path = DirectoryUtil.getStoragePath(fileName: 'flutterwanandroid.apk', package: 'com.thl.flutterwanandroid');
-  /// String path = DirectoryUtil.getStoragePath(fileName: 'flutterwanandroid', format: 'apk', package: 'com.thl.flutterwanandroid');
-  /// Android: /storage/emulated/0/com.thl.flutterwanandroid/flutterwanandroid.apk
+  /// String path = DirectoryUtil.getAppSupportPath(category: 'Pictures', fileName: 'demo.png');
+  /// String path = DirectoryUtil.getAppSupportPath(category: 'Pictures', fileName: 'demo', format: 'png');
+  /// Android: /data/user/0/com.thl.flustars_example/files/Pictures/demo.png
   /// iOS: xxx;
   /// iOS: xxx;
-  static String getStoragePath({
+  static String getAppSupportPath({
+    String category,
     String fileName,
     String fileName,
     String format,
     String format,
-    String package,
-    String category,
   }) {
   }) {
-    if (_storageDir == null) return null;
-    StringBuffer sb = new StringBuffer("${_storageDir.path}");
-    if (!ObjectUtil.isEmpty(package)) sb.write("/$package");
-    if (!ObjectUtil.isEmpty(category)) sb.write("/$category");
-    if (!ObjectUtil.isEmpty(fileName)) sb.write("/$fileName");
-    if (!ObjectUtil.isEmpty(format)) sb.write(".$format");
-    return sb.toString();
+    return getPath(_appSupportDir,
+        category: category, fileName: fileName, format: format);
+  }
+
+  /// get External Storage Directory file path.
+  /// category 分类,例如:video,image等等
+  /// fileName 文件名
+  /// format 文件格式,如果文件名包含格式,则不需要
+  /// String path = DirectoryUtil.getStoragePath(category: 'Download', fileName: 'demo.apk';
+  /// String path = DirectoryUtil.getStoragePath(category: 'Download', fileName: 'demo', format: 'apk');
+  /// Android: /storage/emulated/0/Android/data/com.thl.flustars_example/files/Download/demo.apk
+  /// iOS: xxx;
+  static String getStoragePath(
+      {String category, String fileName, String format}) {
+    return getPath(
+      _storageDir,
+      category: category,
+      fileName: fileName,
+      format: format,
+    );
   }
   }
 
 
-  static Directory createTempDirSync({String package, String category}) {
-    String path = getTempPath(package: package, category: category);
+  static Directory createTempDirSync({String category}) {
+    String path = getTempPath(category: category);
     return createDirSync(path);
     return createDirSync(path);
   }
   }
 
 
-  static Directory createAppDocDirSync({String package, String category}) {
-    String path = getAppDocPath(package: package, category: category);
+  static Directory createAppDocDirSync({String category}) {
+    String path = getAppDocPath(category: category);
     return createDirSync(path);
     return createDirSync(path);
   }
   }
 
 
-  static Directory createStorageDirSync({String package, String category}) {
-    String path = getStoragePath(package: package, category: category);
+  static Directory createAppSupportDirSync({String category}) {
+    String path = getAppSupportPath(category: category);
     return createDirSync(path);
     return createDirSync(path);
   }
   }
 
 
-  static Future<Directory> createTempDir(
-      {String package, String category}) async {
+  static Directory createStorageDirSync({String category}) {
+    String path = getStoragePath(category: category);
+    return createDirSync(path);
+  }
+
+  static Future<Directory> createTempDir({String category}) async {
     await initTempDir();
     await initTempDir();
-    String path = getTempPath(package: package, category: category);
+    String path = getTempPath(category: category);
     return createDir(path);
     return createDir(path);
   }
   }
 
 
-  static Future<Directory> createAppDocDir(
-      {String package, String category}) async {
+  static Future<Directory> createAppDocDir({String category}) async {
     await initAppDocDir();
     await initAppDocDir();
-    String path = getAppDocPath(package: package, category: category);
+    String path = getAppDocPath(category: category);
+    return createDir(path);
+  }
+
+  static Future<Directory> createAppSupportDir({String category}) async {
+    await initAppSupportDir();
+    String path = getAppSupportPath(category: category);
     return createDir(path);
     return createDir(path);
   }
   }
 
 
-  static Future<Directory> createStorageDir(
-      {String package, String category}) async {
+  static Future<Directory> createStorageDir({String category}) async {
     await initStorageDir();
     await initStorageDir();
-    String path = getStoragePath(package: package, category: category);
+    String path = getStoragePath(category: category);
     return createDir(path);
     return createDir(path);
   }
   }
 }
 }

+ 1 - 2
lib/src/screen_util.dart

@@ -2,9 +2,8 @@ import 'package:flutter/material.dart';
 import 'dart:ui' as ui show window;
 import 'dart:ui' as ui show window;
 
 
 /**
 /**
- * @Author: thl
+ * @Author: Sky24n
  * @GitHub: https://github.com/Sky24n
  * @GitHub: https://github.com/Sky24n
- * @Email: 863764940@qq.com
  * @Email: sky24no@gmail.com
  * @Email: sky24no@gmail.com
  * @Description: Screen Util.
  * @Description: Screen Util.
  * @Date: 2018/9/8
  * @Date: 2018/9/8

+ 1 - 3
lib/src/sp_util.dart

@@ -5,13 +5,11 @@ import 'package:shared_preferences/shared_preferences.dart';
 import 'package:synchronized/synchronized.dart';
 import 'package:synchronized/synchronized.dart';
 
 
 /**
 /**
- * @Author: thl
+ * @Author: Sky24n
  * @GitHub: https://github.com/Sky24n
  * @GitHub: https://github.com/Sky24n
- * @Email: 863764940@qq.com
  * @Email: sky24no@gmail.com
  * @Email: sky24no@gmail.com
  * @Date: 2018/9/8
  * @Date: 2018/9/8
  * @Description: Sp Util.
  * @Description: Sp Util.
- * 请勿删除作者个人信息!谢谢!
  */
  */
 
 
 /// SharedPreferences Util.
 /// SharedPreferences Util.

+ 294 - 67
lib/src/ui/my_app_bar.dart

@@ -1,5 +1,5 @@
-import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter/rendering.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter/services.dart';
 
 
 const double _kLeadingWidth =
 const double _kLeadingWidth =
@@ -28,11 +28,136 @@ class _ToolbarContainerLayout extends SingleChildLayoutDelegate {
   bool shouldRelayout(_ToolbarContainerLayout oldDelegate) => false;
   bool shouldRelayout(_ToolbarContainerLayout oldDelegate) => false;
 }
 }
 
 
+// TODO(eseidel): Toolbar needs to change size based on orientation:
+// https://material.io/design/components/app-bars-top.html#specs
+// Mobile Landscape: 48dp
+// Mobile Portrait: 56dp
+// Tablet/Desktop: 64dp
+
+/// A material design app bar.
+///
+/// An app bar consists of a toolbar and potentially other widgets, such as a
+/// [TabBar] and a [FlexibleSpaceBar]. App bars typically expose one or more
+/// common [actions] with [IconButton]s which are optionally followed by a
+/// [PopupMenuButton] for less common operations (sometimes called the "overflow
+/// menu").
+///
+/// App bars are typically used in the [Scaffold.appBar] property, which places
+/// the app bar as a fixed-height widget at the top of the screen. For a scrollable
+/// app bar, see [SliverAppBar], which embeds an [AppBar] in a sliver for use in
+/// a [CustomScrollView].
+///
+/// When not used as [Scaffold.appBar], or when wrapped in a [Hero], place the app
+/// bar in a [MediaQuery] to take care of the padding around the content of the
+/// app bar if needed, as the padding will not be handled by [Scaffold].
+///
+/// The AppBar displays the toolbar widgets, [leading], [title], and [actions],
+/// above the [bottom] (if any). The [bottom] is usually used for a [TabBar]. If
+/// a [flexibleSpace] widget is specified then it is stacked behind the toolbar
+/// and the bottom widget. The following diagram shows where each of these slots
+/// appears in the toolbar when the writing language is left-to-right (e.g.
+/// English):
+///
+/// ![The leading widget is in the top left, the actions are in the top right,
+/// the title is between them. The bottom is, naturally, at the bottom, and the
+/// flexibleSpace is behind all of them.](https://flutter.github.io/assets-for-api-docs/assets/material/app_bar.png)
+///
+/// If the [leading] widget is omitted, but the [AppBar] is in a [Scaffold] with
+/// a [Drawer], then a button will be inserted to open the drawer. Otherwise, if
+/// the nearest [Navigator] has any previous routes, a [BackButton] is inserted
+/// instead. This behavior can be turned off by setting the [automaticallyImplyLeading]
+/// to false. In that case a null leading widget will result in the middle/title widget
+/// stretching to start.
+///
+/// {@tool dartpad --template=stateless_widget_material}
+///
+/// This sample shows an [AppBar] with two simple actions. The first action
+/// opens a [SnackBar], while the second action navigates to a new page.
+///
+/// ```dart preamble
+/// final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
+/// final SnackBar snackBar = const SnackBar(content: Text('Showing Snackbar'));
+///
+/// void openPage(BuildContext context) {
+///   Navigator.push(context, MaterialPageRoute(
+///     builder: (BuildContext context) {
+///       return Scaffold(
+///         appBar: AppBar(
+///           title: const Text('Next page'),
+///         ),
+///         body: const Center(
+///           child: Text(
+///             'This is the next page',
+///             style: TextStyle(fontSize: 24),
+///           ),
+///         ),
+///       );
+///     },
+///   ));
+/// }
+/// ```
+///
+/// ```dart
+/// Widget build(BuildContext context) {
+///   return Scaffold(
+///     key: scaffoldKey,
+///     appBar: AppBar(
+///       title: const Text('AppBar Demo'),
+///       actions: <Widget>[
+///         IconButton(
+///           icon: const Icon(Icons.add_alert),
+///           tooltip: 'Show Snackbar',
+///           onPressed: () {
+///             scaffoldKey.currentState.showSnackBar(snackBar);
+///           },
+///         ),
+///         IconButton(
+///           icon: const Icon(Icons.navigate_next),
+///           tooltip: 'Next page',
+///           onPressed: () {
+///             openPage(context);
+///           },
+///         ),
+///       ],
+///     ),
+///     body: const Center(
+///       child: Text(
+///         'This is the home page',
+///         style: TextStyle(fontSize: 24),
+///       ),
+///     ),
+///   );
+/// }
+/// ```
+/// {@end-tool}
+///
+/// See also:
+///
+///  * [Scaffold], which displays the [AppBar] in its [Scaffold.appBar] slot.
+///  * [SliverAppBar], which uses [AppBar] to provide a flexible app bar that
+///    can be used in a [CustomScrollView].
+///  * [TabBar], which is typically placed in the [bottom] slot of the [AppBar]
+///    if the screen has multiple pages arranged in tabs.
+///  * [IconButton], which is used with [actions] to show buttons on the app bar.
+///  * [PopupMenuButton], to show a popup menu on the app bar, via [actions].
+///  * [FlexibleSpaceBar], which is used with [flexibleSpace] when the app bar
+///    can expand and collapse.
+///  * <https://material.io/design/components/app-bars-top.html>
+///
+/// 未来版本可能会被删除!
+/// Future versions may be removed.
+@deprecated
 class MyAppBar extends StatefulWidget implements PreferredSizeWidget {
 class MyAppBar extends StatefulWidget implements PreferredSizeWidget {
   /// Creates a material design app bar.
   /// Creates a material design app bar.
   ///
   ///
-  /// The arguments [elevation], [primary], [toolbarOpacity], [bottomOpacity]
-  /// and [automaticallyImplyLeading] must not be null.
+  /// The arguments [primary], [toolbarOpacity], [bottomOpacity]
+  /// and [automaticallyImplyLeading] must not be null. Additionally, if
+  /// [elevation] is specified, it must be non-negative.
+  ///
+  /// If [backgroundColor], [elevation], [brightness], [iconTheme],
+  /// [actionsIconTheme], or [textTheme] are null, then their [AppBarTheme]
+  /// values will be used. If the corresponding [AppBarTheme] property is null,
+  /// then the default specified in the property's documentation will be used.
   ///
   ///
   /// Typically used in the [Scaffold.appBar] property.
   /// Typically used in the [Scaffold.appBar] property.
   MyAppBar({
   MyAppBar({
@@ -43,10 +168,12 @@ class MyAppBar extends StatefulWidget implements PreferredSizeWidget {
     this.actions,
     this.actions,
     this.flexibleSpace,
     this.flexibleSpace,
     this.bottom,
     this.bottom,
-    this.elevation = 4.0,
+    this.elevation,
+    this.shape,
     this.backgroundColor,
     this.backgroundColor,
     this.brightness,
     this.brightness,
     this.iconTheme,
     this.iconTheme,
+    this.actionsIconTheme,
     this.textTheme,
     this.textTheme,
     this.primary = true,
     this.primary = true,
     this.centerTitle,
     this.centerTitle,
@@ -54,7 +181,7 @@ class MyAppBar extends StatefulWidget implements PreferredSizeWidget {
     this.toolbarOpacity = 1.0,
     this.toolbarOpacity = 1.0,
     this.bottomOpacity = 1.0,
     this.bottomOpacity = 1.0,
   })  : assert(automaticallyImplyLeading != null),
   })  : assert(automaticallyImplyLeading != null),
-        assert(elevation != null),
+        assert(elevation == null || elevation >= 0.0),
         assert(primary != null),
         assert(primary != null),
         assert(titleSpacing != null),
         assert(titleSpacing != null),
         assert(toolbarOpacity != null),
         assert(toolbarOpacity != null),
@@ -71,6 +198,37 @@ class MyAppBar extends StatefulWidget implements PreferredSizeWidget {
   /// widget with an [IconButton] that opens the drawer (using [Icons.menu]). If
   /// widget with an [IconButton] that opens the drawer (using [Icons.menu]). If
   /// there's no [Drawer] and the parent [Navigator] can go back, the [AppBar]
   /// there's no [Drawer] and the parent [Navigator] can go back, the [AppBar]
   /// will use a [BackButton] that calls [Navigator.maybePop].
   /// will use a [BackButton] that calls [Navigator.maybePop].
+  ///
+  /// {@tool sample}
+  ///
+  /// The following code shows how the drawer button could be manually specified
+  /// instead of relying on [automaticallyImplyLeading]:
+  ///
+  /// ```dart
+  /// AppBar(
+  ///   leading: Builder(
+  ///     builder: (BuildContext context) {
+  ///       return IconButton(
+  ///         icon: const Icon(Icons.menu),
+  ///         onPressed: () { Scaffold.of(context).openDrawer(); },
+  ///         tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
+  ///       );
+  ///     },
+  ///   ),
+  /// )
+  /// ```
+  /// {@end-tool}
+  ///
+  /// The [Builder] is used in this example to ensure that the `context` refers
+  /// to that part of the subtree. That way this code snippet can be used even
+  /// inside the very code that is creating the [Scaffold] (in which case,
+  /// without the [Builder], the `context` wouldn't be able to see the
+  /// [Scaffold], since it would refer to an ancestor of that widget).
+  ///
+  /// See also:
+  ///
+  ///  * [Scaffold.appBar], in which an [AppBar] is usually placed.
+  ///  * [Scaffold.drawer], in which the [Drawer] is usually placed.
   final Widget leading;
   final Widget leading;
 
 
   /// Controls whether we should try to imply the leading widget if null.
   /// Controls whether we should try to imply the leading widget if null.
@@ -80,7 +238,7 @@ class MyAppBar extends StatefulWidget implements PreferredSizeWidget {
   /// If leading widget is not null, this parameter has no effect.
   /// If leading widget is not null, this parameter has no effect.
   final bool automaticallyImplyLeading;
   final bool automaticallyImplyLeading;
 
 
-  /// The primary widget displayed in the appbar.
+  /// The primary widget displayed in the app bar.
   ///
   ///
   /// Typically a [Text] widget containing a description of the current contents
   /// Typically a [Text] widget containing a description of the current contents
   /// of the app.
   /// of the app.
@@ -91,28 +249,9 @@ class MyAppBar extends StatefulWidget implements PreferredSizeWidget {
   /// Typically these widgets are [IconButton]s representing common operations.
   /// Typically these widgets are [IconButton]s representing common operations.
   /// For less common operations, consider using a [PopupMenuButton] as the
   /// For less common operations, consider using a [PopupMenuButton] as the
   /// last action.
   /// last action.
-  ///
-  /// ## Sample code
-  ///
-  /// ```dart
-  /// Scaffold(
-  ///   appBar: AppBar(
-  ///     title: Text('Hello World'),
-  ///     actions: <Widget>[
-  ///       IconButton(
-  ///         icon: Icon(Icons.shopping_cart),
-  ///         tooltip: 'Open shopping cart',
-  ///         onPressed: () {
-  ///           // ...
-  ///         },
-  ///       ),
-  ///     ],
-  ///   ),
-  /// )
-  /// ```
   final List<Widget> actions;
   final List<Widget> actions;
 
 
-  /// This widget is stacked behind the toolbar and the tabbar. It's height will
+  /// This widget is stacked behind the toolbar and the tab bar. It's height will
   /// be the same as the app bar's overall height.
   /// be the same as the app bar's overall height.
   ///
   ///
   /// A flexible space isn't actually flexible unless the [AppBar]'s container
   /// A flexible space isn't actually flexible unless the [AppBar]'s container
@@ -132,39 +271,63 @@ class MyAppBar extends StatefulWidget implements PreferredSizeWidget {
   ///  * [PreferredSize], which can be used to give an arbitrary widget a preferred size.
   ///  * [PreferredSize], which can be used to give an arbitrary widget a preferred size.
   final PreferredSizeWidget bottom;
   final PreferredSizeWidget bottom;
 
 
-  /// The z-coordinate at which to place this app bar. This controls the size of
-  /// the shadow below the app bar.
+  /// The z-coordinate at which to place this app bar relative to its parent.
+  ///
+  /// This controls the size of the shadow below the app bar.
+  ///
+  /// The value is non-negative.
   ///
   ///
-  /// Defaults to 4, the appropriate elevation for app bars.
+  /// If this property is null, then [ThemeData.appBarTheme.elevation] is used,
+  /// if that is also null, the default value is 4, the appropriate elevation
+  /// for app bars.
   final double elevation;
   final double elevation;
 
 
+  /// The material's shape as well its shadow.
+  ///
+  /// A shadow is only displayed if the [elevation] is greater than
+  /// zero.
+  final ShapeBorder shape;
+
   /// The color to use for the app bar's material. Typically this should be set
   /// The color to use for the app bar's material. Typically this should be set
   /// along with [brightness], [iconTheme], [textTheme].
   /// along with [brightness], [iconTheme], [textTheme].
   ///
   ///
-  /// Defaults to [ThemeData.primaryColor].
+  /// If this property is null, then [ThemeData.appBarTheme.color] is used,
+  /// if that is also null, then [ThemeData.primaryColor] is used.
   final Color backgroundColor;
   final Color backgroundColor;
 
 
   /// The brightness of the app bar's material. Typically this is set along
   /// The brightness of the app bar's material. Typically this is set along
   /// with [backgroundColor], [iconTheme], [textTheme].
   /// with [backgroundColor], [iconTheme], [textTheme].
   ///
   ///
-  /// Defaults to [ThemeData.primaryColorBrightness].
+  /// If this property is null, then [ThemeData.appBarTheme.brightness] is used,
+  /// if that is also null, then [ThemeData.primaryColorBrightness] is used.
   final Brightness brightness;
   final Brightness brightness;
 
 
   /// The color, opacity, and size to use for app bar icons. Typically this
   /// The color, opacity, and size to use for app bar icons. Typically this
   /// is set along with [backgroundColor], [brightness], [textTheme].
   /// is set along with [backgroundColor], [brightness], [textTheme].
   ///
   ///
-  /// Defaults to [ThemeData.primaryIconTheme].
+  /// If this property is null, then [ThemeData.appBarTheme.iconTheme] is used,
+  /// if that is also null, then [ThemeData.primaryIconTheme] is used.
   final IconThemeData iconTheme;
   final IconThemeData iconTheme;
 
 
+  /// The color, opacity, and size to use for the icons that appear in the app
+  /// bar's [actions]. This should only be used when the [actions] should be
+  /// themed differently than the icon that appears in the app bar's [leading]
+  /// widget.
+  ///
+  /// If this property is null, then [ThemeData.appBarTheme.actionsIconTheme] is
+  /// used, if that is also null, then this falls back to [iconTheme].
+  final IconThemeData actionsIconTheme;
+
   /// The typographic styles to use for text in the app bar. Typically this is
   /// The typographic styles to use for text in the app bar. Typically this is
   /// set along with [brightness] [backgroundColor], [iconTheme].
   /// set along with [brightness] [backgroundColor], [iconTheme].
   ///
   ///
-  /// Defaults to [ThemeData.primaryTextTheme].
+  /// If this property is null, then [ThemeData.appBarTheme.textTheme] is used,
+  /// if that is also null, then [ThemeData.primaryTextTheme] is used.
   final TextTheme textTheme;
   final TextTheme textTheme;
 
 
   /// Whether this app bar is being displayed at the top of the screen.
   /// Whether this app bar is being displayed at the top of the screen.
   ///
   ///
-  /// If true, the appbar's toolbar elements and [bottom] widget will be
+  /// If true, the app bar's toolbar elements and [bottom] widget will be
   /// padded on top by the height of the system status bar. The layout
   /// padded on top by the height of the system status bar. The layout
   /// of the [flexibleSpace] is not affected by the [primary] property.
   /// of the [flexibleSpace] is not affected by the [primary] property.
   final bool primary;
   final bool primary;
@@ -202,14 +365,14 @@ class MyAppBar extends StatefulWidget implements PreferredSizeWidget {
   /// A size whose height is the sum of [kToolbarHeight] and the [bottom] widget's
   /// A size whose height is the sum of [kToolbarHeight] and the [bottom] widget's
   /// preferred height.
   /// preferred height.
   ///
   ///
-  /// [Scaffold] uses this this size to set its app bar's height.
+  /// [Scaffold] uses this size to set its app bar's height.
   @override
   @override
   final Size preferredSize;
   final Size preferredSize;
 
 
-  bool _getEffectiveCenterTitle(ThemeData themeData) {
+  bool _getEffectiveCenterTitle(ThemeData theme) {
     if (centerTitle != null) return centerTitle;
     if (centerTitle != null) return centerTitle;
-    assert(themeData.platform != null);
-    switch (themeData.platform) {
+    assert(theme.platform != null);
+    switch (theme.platform) {
       case TargetPlatform.android:
       case TargetPlatform.android:
       case TargetPlatform.fuchsia:
       case TargetPlatform.fuchsia:
         return false;
         return false;
@@ -224,6 +387,8 @@ class MyAppBar extends StatefulWidget implements PreferredSizeWidget {
 }
 }
 
 
 class _MyAppBarState extends State<MyAppBar> {
 class _MyAppBarState extends State<MyAppBar> {
+  static const double _defaultElevation = 4.0;
+
   void _handleDrawerButton() {
   void _handleDrawerButton() {
     Scaffold.of(context).openDrawer();
     Scaffold.of(context).openDrawer();
   }
   }
@@ -236,7 +401,8 @@ class _MyAppBarState extends State<MyAppBar> {
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     assert(!widget.primary || debugCheckHasMediaQuery(context));
     assert(!widget.primary || debugCheckHasMediaQuery(context));
     assert(debugCheckHasMaterialLocalizations(context));
     assert(debugCheckHasMaterialLocalizations(context));
-    final ThemeData themeData = Theme.of(context);
+    final ThemeData theme = Theme.of(context);
+    final AppBarTheme appBarTheme = AppBarTheme.of(context);
     final ScaffoldState scaffold = Scaffold.of(context, nullOk: true);
     final ScaffoldState scaffold = Scaffold.of(context, nullOk: true);
     final ModalRoute<dynamic> parentRoute = ModalRoute.of(context);
     final ModalRoute<dynamic> parentRoute = ModalRoute.of(context);
 
 
@@ -246,12 +412,17 @@ class _MyAppBarState extends State<MyAppBar> {
     final bool useCloseButton =
     final bool useCloseButton =
         parentRoute is PageRoute<dynamic> && parentRoute.fullscreenDialog;
         parentRoute is PageRoute<dynamic> && parentRoute.fullscreenDialog;
 
 
-    IconThemeData appBarIconTheme =
-        widget.iconTheme ?? themeData.primaryIconTheme;
-    TextStyle centerStyle =
-        widget.textTheme?.title ?? themeData.primaryTextTheme.title;
-    TextStyle sideStyle =
-        widget.textTheme?.body1 ?? themeData.primaryTextTheme.body1;
+    IconThemeData overallIconTheme =
+        widget.iconTheme ?? appBarTheme.iconTheme ?? theme.primaryIconTheme;
+    IconThemeData actionsIconTheme = widget.actionsIconTheme ??
+        appBarTheme.actionsIconTheme ??
+        overallIconTheme;
+    TextStyle centerStyle = widget.textTheme?.title ??
+        appBarTheme.textTheme?.title ??
+        theme.primaryTextTheme.title;
+    TextStyle sideStyle = widget.textTheme?.body1 ??
+        appBarTheme.textTheme?.body1 ??
+        theme.primaryTextTheme.body1;
 
 
     if (widget.toolbarOpacity != 1.0) {
     if (widget.toolbarOpacity != 1.0) {
       final double opacity =
       final double opacity =
@@ -263,16 +434,18 @@ class _MyAppBarState extends State<MyAppBar> {
       if (sideStyle?.color != null)
       if (sideStyle?.color != null)
         sideStyle =
         sideStyle =
             sideStyle.copyWith(color: sideStyle.color.withOpacity(opacity));
             sideStyle.copyWith(color: sideStyle.color.withOpacity(opacity));
-      appBarIconTheme = appBarIconTheme.copyWith(
-          opacity: opacity * (appBarIconTheme.opacity ?? 1.0));
+      overallIconTheme = overallIconTheme.copyWith(
+          opacity: opacity * (overallIconTheme.opacity ?? 1.0));
+      actionsIconTheme = actionsIconTheme.copyWith(
+          opacity: opacity * (actionsIconTheme.opacity ?? 1.0));
     }
     }
 
 
     Widget leading = widget.leading;
     Widget leading = widget.leading;
-    //if (leading == null && widget.automaticallyImplyLeading) {
+//    if (leading == null && widget.automaticallyImplyLeading) {
     if (widget.automaticallyImplyLeading) {
     if (widget.automaticallyImplyLeading) {
       if (hasDrawer) {
       if (hasDrawer) {
         leading = IconButton(
         leading = IconButton(
-          //icon: const Icon(Icons.menu),
+//          icon: const Icon(Icons.menu),
           icon: leading ?? const Icon(Icons.menu),
           icon: leading ?? const Icon(Icons.menu),
           onPressed: _handleDrawerButton,
           onPressed: _handleDrawerButton,
           tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
           tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
@@ -292,7 +465,7 @@ class _MyAppBarState extends State<MyAppBar> {
     Widget title = widget.title;
     Widget title = widget.title;
     if (title != null) {
     if (title != null) {
       bool namesRoute;
       bool namesRoute;
-      switch (defaultTargetPlatform) {
+      switch (theme.platform) {
         case TargetPlatform.android:
         case TargetPlatform.android:
         case TargetPlatform.fuchsia:
         case TargetPlatform.fuchsia:
           namesRoute = true;
           namesRoute = true;
@@ -306,7 +479,7 @@ class _MyAppBarState extends State<MyAppBar> {
         overflow: TextOverflow.ellipsis,
         overflow: TextOverflow.ellipsis,
         child: Semantics(
         child: Semantics(
           namesRoute: namesRoute,
           namesRoute: namesRoute,
-          child: title,
+          child: _AppBarTitleBox(child: title),
           header: true,
           header: true,
         ),
         ),
       );
       );
@@ -327,11 +500,19 @@ class _MyAppBarState extends State<MyAppBar> {
       );
       );
     }
     }
 
 
+    // Allow the trailing actions to have their own theme if necessary.
+    if (actions != null) {
+      actions = IconTheme.merge(
+        data: actionsIconTheme,
+        child: actions,
+      );
+    }
+
     final Widget toolbar = NavigationToolbar(
     final Widget toolbar = NavigationToolbar(
       leading: leading,
       leading: leading,
       middle: title,
       middle: title,
       trailing: actions,
       trailing: actions,
-      centerMiddle: widget._getEffectiveCenterTitle(themeData),
+      centerMiddle: widget._getEffectiveCenterTitle(theme),
       middleSpacing: widget.titleSpacing,
       middleSpacing: widget.titleSpacing,
     );
     );
 
 
@@ -341,7 +522,7 @@ class _MyAppBarState extends State<MyAppBar> {
       child: CustomSingleChildLayout(
       child: CustomSingleChildLayout(
         delegate: const _ToolbarContainerLayout(),
         delegate: const _ToolbarContainerLayout(),
         child: IconTheme.merge(
         child: IconTheme.merge(
-          data: appBarIconTheme,
+          data: overallIconTheme,
           child: DefaultTextStyle(
           child: DefaultTextStyle(
             style: sideStyle,
             style: sideStyle,
             child: toolbar,
             child: toolbar,
@@ -359,14 +540,14 @@ class _MyAppBarState extends State<MyAppBar> {
               child: appBar,
               child: appBar,
             ),
             ),
           ),
           ),
-          widget.bottomOpacity == 1.0
-              ? widget.bottom
-              : Opacity(
-                  opacity:
-                      const Interval(0.25, 1.0, curve: Curves.fastOutSlowIn)
-                          .transform(widget.bottomOpacity),
-                  child: widget.bottom,
-                ),
+          if (widget.bottomOpacity == 1.0)
+            widget.bottom
+          else
+            Opacity(
+              opacity: const Interval(0.25, 1.0, curve: Curves.fastOutSlowIn)
+                  .transform(widget.bottomOpacity),
+              child: widget.bottom,
+            ),
         ],
         ],
       );
       );
     }
     }
@@ -393,23 +574,69 @@ class _MyAppBarState extends State<MyAppBar> {
         ],
         ],
       );
       );
     }
     }
-    final Brightness brightness =
-        widget.brightness ?? themeData.primaryColorBrightness;
+    final Brightness brightness = widget.brightness ??
+        appBarTheme.brightness ??
+        theme.primaryColorBrightness;
     final SystemUiOverlayStyle overlayStyle = brightness == Brightness.dark
     final SystemUiOverlayStyle overlayStyle = brightness == Brightness.dark
         ? SystemUiOverlayStyle.light
         ? SystemUiOverlayStyle.light
         : SystemUiOverlayStyle.dark;
         : SystemUiOverlayStyle.dark;
 
 
     return Semantics(
     return Semantics(
       container: true,
       container: true,
-      explicitChildNodes: true,
       child: AnnotatedRegion<SystemUiOverlayStyle>(
       child: AnnotatedRegion<SystemUiOverlayStyle>(
         value: overlayStyle,
         value: overlayStyle,
         child: Material(
         child: Material(
-          color: widget.backgroundColor ?? themeData.primaryColor,
-          elevation: widget.elevation,
-          child: appBar,
+          color:
+              widget.backgroundColor ?? appBarTheme.color ?? theme.primaryColor,
+          elevation:
+              widget.elevation ?? appBarTheme.elevation ?? _defaultElevation,
+          shape: widget.shape,
+          child: Semantics(
+            explicitChildNodes: true,
+            child: appBar,
+          ),
         ),
         ),
       ),
       ),
     );
     );
   }
   }
+} // Layout the AppBar's title with unconstrained height, vertically
+
+// center it within its (NavigationToolbar) parent, and allow the
+// parent to constrain the title's actual height.
+class _AppBarTitleBox extends SingleChildRenderObjectWidget {
+  const _AppBarTitleBox({Key key, @required Widget child})
+      : assert(child != null),
+        super(key: key, child: child);
+
+  @override
+  _RenderAppBarTitleBox createRenderObject(BuildContext context) {
+    return _RenderAppBarTitleBox(
+      textDirection: Directionality.of(context),
+    );
+  }
+
+  @override
+  void updateRenderObject(
+      BuildContext context, _RenderAppBarTitleBox renderObject) {
+    renderObject.textDirection = Directionality.of(context);
+  }
+}
+
+class _RenderAppBarTitleBox extends RenderAligningShiftedBox {
+  _RenderAppBarTitleBox({
+    RenderBox child,
+    TextDirection textDirection,
+  }) : super(
+            child: child,
+            alignment: Alignment.center,
+            textDirection: textDirection);
+
+  @override
+  void performLayout() {
+    final BoxConstraints innerConstraints =
+        constraints.copyWith(maxHeight: double.infinity);
+    child.layout(innerConstraints, parentUsesSize: true);
+    size = constraints.constrain(child.size);
+    alignChild();
+  }
 }
 }

+ 7 - 9
lib/src/widget_util.dart

@@ -1,11 +1,9 @@
 import 'dart:async';
 import 'dart:async';
-import 'package:common_utils/common_utils.dart';
 import 'package:flutter/widgets.dart';
 import 'package:flutter/widgets.dart';
 
 
 /**
 /**
- * @Author: thl
+ * @Author: Sky24n
  * @GitHub: https://github.com/Sky24n
  * @GitHub: https://github.com/Sky24n
- * @Email: 863764940@qq.com
  * @Email: sky24no@gmail.com
  * @Email: sky24no@gmail.com
  * @Description: Widget Util.
  * @Description: Widget Util.
  * @Date: 2018/9/10
  * @Date: 2018/9/10
@@ -72,9 +70,9 @@ class WidgetUtil {
   /// local url , package
   /// local url , package
   static Future<Rect> getImageWH(
   static Future<Rect> getImageWH(
       {Image image, String url, String localUrl, String package}) {
       {Image image, String url, String localUrl, String package}) {
-    if (ObjectUtil.isEmpty(image) &&
-        ObjectUtil.isEmpty(url) &&
-        ObjectUtil.isEmpty(localUrl)) {
+    if (image == null &&
+        (url == null || url.isEmpty) &&
+        (localUrl == null || localUrl.isEmpty)) {
       return Future.value(Rect.zero);
       return Future.value(Rect.zero);
     }
     }
     Completer<Rect> completer = Completer<Rect>();
     Completer<Rect> completer = Completer<Rect>();
@@ -105,9 +103,9 @@ class WidgetUtil {
   /// package
   /// package
   static Future<Rect> getImageWHE(
   static Future<Rect> getImageWHE(
       {Image image, String url, String localUrl, String package}) {
       {Image image, String url, String localUrl, String package}) {
-    if (ObjectUtil.isEmpty(image) &&
-        ObjectUtil.isEmpty(url) &&
-        ObjectUtil.isEmpty(localUrl)) {
+    if (image == null &&
+        (url == null || url.isEmpty) &&
+        (localUrl == null || localUrl.isEmpty)) {
       return Future.error("image is null.");
       return Future.error("image is null.");
     }
     }
     Completer<Rect> completer = Completer<Rect>();
     Completer<Rect> completer = Completer<Rect>();

+ 3 - 0
pkgget

@@ -0,0 +1,3 @@
+export PUB_HOSTED_URL=https://pub.flutter-io.cn
+export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
+flutter packages get

+ 3 - 5
pubspec.yaml

@@ -1,6 +1,6 @@
 name: flustars
 name: flustars
 description: Flutter common utils library. SpUtil, ScreenUtil, WidgetUtil. SharedPreferences Util. Screen info & Screen adaptation. get image size.
 description: Flutter common utils library. SpUtil, ScreenUtil, WidgetUtil. SharedPreferences Util. Screen info & Screen adaptation. get image size.
-version: 0.2.6+2
+version: 0.3.0
 author: Sky24n <863764940@qq.com>
 author: Sky24n <863764940@qq.com>
 homepage: https://github.com/Sky24n/flustars
 homepage: https://github.com/Sky24n/flustars
 
 
@@ -10,11 +10,9 @@ environment:
 dependencies:
 dependencies:
   flutter:
   flutter:
     sdk: flutter
     sdk: flutter
-  # Dart 常用工具类库 https://github.com/Sky24n/common_utils
-  common_utils: '>=1.1.0 <3.0.0'
   # https://github.com/tekartik/synchronized.dart
   # https://github.com/tekartik/synchronized.dart
-  synchronized: '>=1.5.1 <3.0.0'
+  synchronized: '>=1.5.1 <4.0.0'
   # https://github.com/flutter/plugins/tree/master/packages/shared_preferences
   # https://github.com/flutter/plugins/tree/master/packages/shared_preferences
   shared_preferences: '>=0.4.1 <3.0.0'
   shared_preferences: '>=0.4.1 <3.0.0'
   # https://github.com/flutter/plugins/tree/master/packages/path_provider
   # https://github.com/flutter/plugins/tree/master/packages/path_provider
-  path_provider: '>=0.4.0 <3.0.0'
+  path_provider: '>=1.1.0 <3.0.0'