diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..69bbfbf --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.DS_Store +.dart_tool/ +.idea/ +.packages +.pub/ + +build/ + +.flutter-plugins diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..691cc8a --- /dev/null +++ b/.metadata @@ -0,0 +1,8 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 5ab9e70727d858def3a586db7fb98ee580352957 + channel: beta diff --git a/README.md b/README.md new file mode 100644 index 0000000..887c024 --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# xiaoming + +A new Flutter application. + +## Getting Started + +For help getting started with Flutter, view our online +[documentation](https://flutter.io/). diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..65b7315 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,10 @@ +*.iml +*.class +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures +GeneratedPluginRegistrant.java diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..5bb8b56 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,61 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 27 + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.spadek.xiaoming" + minSdkVersion 16 + targetSdkVersion 27 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' +} diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..b24c9a8 --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/java/com/spadek/xiaoming/MainActivity.java b/android/app/src/main/java/com/spadek/xiaoming/MainActivity.java new file mode 100644 index 0000000..b3be072 --- /dev/null +++ b/android/app/src/main/java/com/spadek/xiaoming/MainActivity.java @@ -0,0 +1,13 @@ +package com.spadek.xiaoming; + +import android.os.Bundle; +import io.flutter.app.FlutterActivity; +import io.flutter.plugins.GeneratedPluginRegistrant; + +public class MainActivity extends FlutterActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + GeneratedPluginRegistrant.registerWith(this); + } +} diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..db77bb4 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..17987b7 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..09d4391 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..d5f1c8d Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..4d6372e Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..00fa441 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..d4225c7 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,29 @@ +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.1.2' + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..8bd86f6 --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx1536M diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..13372ae Binary files /dev/null and b/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..9372d0f --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip diff --git a/android/gradlew b/android/gradlew new file mode 100644 index 0000000..9d82f78 --- /dev/null +++ b/android/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/android/gradlew.bat b/android/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/android/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..5a2f14f --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,15 @@ +include ':app' + +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } +} + +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory +} diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..79cc4da --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,45 @@ +.idea/ +.vagrant/ +.sconsign.dblite +.svn/ + +.DS_Store +*.swp +profile + +DerivedData/ +build/ +GeneratedPluginRegistrant.h +GeneratedPluginRegistrant.m + +.generated/ + +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 + +!default.pbxuser +!default.mode1v3 +!default.mode2v3 +!default.perspectivev3 + +xcuserdata + +*.moved-aside + +*.pyc +*sync/ +Icon? +.tags* + +/Flutter/app.flx +/Flutter/app.zip +/Flutter/flutter_assets/ +/Flutter/App.framework +/Flutter/Flutter.framework +/Flutter/Generated.xcconfig +/ServiceDefinitions.json + +Pods/ +.symlinks/ diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..9367d48 --- /dev/null +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 8.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..df6574c --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,436 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; + 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; + 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 2D5378251FAA1A9400D5DBA9 /* flutter_assets */, + 3B80C3931E831B6300D905FE /* App.framework */, + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEBA1CF902C7004384FC /* Flutter.framework */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + CF3B75C9A7D2FA2A4C99F110 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, + 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 97C146F21CF9000F007C117D /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0910; + ORGANIZATIONNAME = "The Chromium Authors"; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, + 97C146F31CF9000F007C117D /* main.m in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.spadek.xiaoming; + PRODUCT_NAME = "$(TARGET_NAME)"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.spadek.xiaoming; + PRODUCT_NAME = "$(TARGET_NAME)"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..1263ac8 --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner/AppDelegate.h b/ios/Runner/AppDelegate.h new file mode 100644 index 0000000..36e21bb --- /dev/null +++ b/ios/Runner/AppDelegate.h @@ -0,0 +1,6 @@ +#import +#import + +@interface AppDelegate : FlutterAppDelegate + +@end diff --git a/ios/Runner/AppDelegate.m b/ios/Runner/AppDelegate.m new file mode 100644 index 0000000..59a72e9 --- /dev/null +++ b/ios/Runner/AppDelegate.m @@ -0,0 +1,13 @@ +#include "AppDelegate.h" +#include "GeneratedPluginRegistrant.h" + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [GeneratedPluginRegistrant registerWithRegistry:self]; + // Override point for customization after application launch. + return [super application:application didFinishLaunchingWithOptions:launchOptions]; +} + +@end diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000..3d43d11 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000..28c6bf0 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000..2ccbfd9 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000..f091b6b Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000..4cde121 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000..d0ef06e Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000..dcdc230 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000..2ccbfd9 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000..c8f9ed8 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000..a6d6b86 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000..a6d6b86 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000..75b2d16 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000..c4df70d Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000..6a84f41 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000..d0e1f58 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000..0bedcf2 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist new file mode 100644 index 0000000..3763a4b --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + xiaoming + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/ios/Runner/main.m b/ios/Runner/main.m new file mode 100644 index 0000000..dff6597 --- /dev/null +++ b/ios/Runner/main.m @@ -0,0 +1,9 @@ +#import +#import +#import "AppDelegate.h" + +int main(int argc, char* argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/lib/README.md b/lib/README.md new file mode 100644 index 0000000..61634b0 --- /dev/null +++ b/lib/README.md @@ -0,0 +1,37 @@ +# xiaoming + +#### 项目介绍 +我的第一个flutter应用 + +#### 软件架构 +软件架构说明 + + +#### 安装教程 + +1. xxxx +2. xxxx +3. xxxx + +#### 使用说明 + +1. xxxx +2. xxxx +3. xxxx + +#### 参与贡献 + +1. Fork 本项目 +2. 新建 Feat_xxx 分支 +3. 提交代码 +4. 新建 Pull Request + + +#### 码云特技 + +1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md +2. 码云官方博客 [blog.gitee.com](https://blog.gitee.com) +3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解码云上的优秀开源项目 +4. [GVP](https://gitee.com/gvp) 全称是码云最有价值开源项目,是码云综合评定出的优秀开源项目 +5. 码云官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) +6. 码云封面人物是一档用来展示码云会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) \ No newline at end of file diff --git a/lib/View/myview.dart b/lib/View/myview.dart new file mode 100644 index 0000000..d5a9c4f --- /dev/null +++ b/lib/View/myview.dart @@ -0,0 +1,301 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:xiaoming/data/data.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:xiaoming/command/Matrix.dart'; + +///单个输出文本的视图 +class TextView extends StatelessWidget { + TextView({this.context, this.text, this.animationController}); + BuildContext context; + final AnimationController animationController; + final String text; +// final scaffoldState = GlobalKey(); + @override + Widget build(BuildContext context) { + return new SizeTransition( + sizeFactor: new CurvedAnimation( + parent: animationController, curve: Curves.easeOut), + axisAlignment: 0.0, + child: new GestureDetector( + child: new ListTile( + title: new Container( + margin: const EdgeInsets.only(left: 5.0), + child: new Text(text), + )), + onLongPress: _handleLongPress, + ), + ); + } + + void _handleLongPress() { + Clipboard.setData(new ClipboardData(text: text)); + Scaffold.of(context).showSnackBar(SnackBar( + duration: Duration(milliseconds: 1000), + content: new Text('内容已复制到剪切板'), + )); + } +} + +///保存的方法界面 +void methodRoute(BuildContext context) { + Navigator.of(context).push(new MaterialPageRoute(builder: (context) { + final List tiles = []; + for (CmdMethod method in cmdMethods) { + tiles.add(new Card( + color: Colors.amber, + child: new ListTile( + leading: new Text( + method.name, + ), + title: new Text(method.methodValue), + subtitle: new Text(method.methodDescription), + ), + )); + } + for (UserFunction u in userFunctions) { + tiles.add(new Card( + color: Colors.amber, + child: new ListTile( + leading: new Text( + u.funName, + ), + title: new Text( + '${u.funName}(${u.paras.toString().substring(1, u.paras.toString().length - 1)})'), + subtitle: new Text(u.funCmds.toString()), + ), + )); + } + final List divided = ListTile.divideTiles( + context: context, + tiles: tiles, + ).toList(); + + return new Scaffold( + appBar: new AppBar( + title: new Text('保存的函数'), + ), + body: new ListView( + children: divided, + ), + ); + })); +} + +///保存的数据界面 +void dataRoute(BuildContext context) { + Navigator.of(context) + .push(new MaterialPageRoute(builder: (BuildContext context) { + List tiles = []; + if (matrixs.isNotEmpty) { + matrixs.forEach((name, list) => tiles.add(new Card( + color: Colors.cyan, + child: new ListTile( + leading: new Text(name), + title: new Text(mtoString(list: list)), + ), + ))); + } + if (dbs.isNotEmpty) { + dbs.forEach((name, value) => tiles.add(new Card( + color: Colors.green, + child: new ListTile( + leading: new Text(name), + title: new Text(value.toString()), + ), + ))); + } + final List divided = ListTile.divideTiles( + context: context, + tiles: tiles.reversed, + ).toList(); + return new Scaffold( + appBar: new AppBar( + title: new Text('保存的数据'), + ), + body: new ListView( + children: divided, + ), + ); + })); +} + +///设置界面 +class SettingRoute extends StatefulWidget { + @override + _SettingRouteState createState() => _SettingRouteState(); +} + +///控制设置界面的状态 +class _SettingRouteState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('设置'), + ), + body: ListView( + children: [ + Card( + elevation: 5.0, + margin: const EdgeInsets.all(8.0), + child: new Container( + margin: const EdgeInsets.all(12.0), + child: new Row( + children: [ + Expanded( + child: Text('显示小数位数'), + ), + Text(fixedNum.toString()), + CupertinoSlider( + divisions: 8, + max: 9.0, + min: 1.0, + value: fixedNum, + onChanged: (double d) { + setState(() { + fixedNum = d; + }); + writeSettingData(); + }, + ), + ], + )), + ), + Card( + elevation: 5.0, + margin: const EdgeInsets.all(8.0), + child: new Container( + margin: const EdgeInsets.all(12.0), + child: new Row( + children: [ + Expanded( + child: Text('内置函数快捷输入显示方式'), + ), + Text('横轴'), + Switch( + value: isHorizontalBottons, + onChanged: (newValue) { + setState(() { + isHorizontalBottons = !isHorizontalBottons; + }); + writeSettingData(); + }, + ), + ], + ), + ), + ), + ], + ), + ); + } +} + +///加载设置界面 +void settingRoute(BuildContext context) { + Navigator.of(context) + .push(new MaterialPageRoute(builder: (BuildContext context) { + return new SettingRoute(); + })); +} + +///帮助界面 +class helpView extends StatefulWidget { + @override + _helpViewState createState() => _helpViewState(); +} + +class HelpItem { + bool isExpanded; + final String header; + final Widget body; + HelpItem(this.isExpanded, this.header, this.body); +} + +///控制帮助界面的状态 +class _helpViewState extends State { + List items = [ + new HelpItem( + false, + '矩阵赋值', + Container( + margin: EdgeInsets.only(left: 16.0, right: 16.0, bottom: 16.0), + child: new Text('矩阵赋值的语句格式为:a=[1,2,3;4,5,6;7,8,9],' + ' 名称可以由字母和数字组成,但必须以字母开头。' + '每一行的多个值用逗号分隔开,行之间用分号分隔开。输入框的上方有方便输入的' + '逗号和分号按钮。矩阵和实数会自动保存到文件,同名的数据会被替换(输入a=2也会替换' + '原有的a=[1,2,3;4,5,6])'), + )), + new HelpItem( + false, + '函数调用', + Container( + margin: EdgeInsets.only(left: 16.0, right: 16.0, bottom: 16.0), + child: new Text('输入函数名及其参数即可调用函数。例:b=inv(a).函数可以嵌套调用,' + '例:c=tran(inv(a)。在自定义函数中也可以调用内置函数,输入框的上方有方便输入函数名的按钮列' + '点击主界面左上角的按钮可以打开抽屉,点击抽屉中的保存的函数按钮可以打开函数介绍界面,里面有内置函数的' + '详细介绍,还有用户的自定义函数'), + )), + new HelpItem( + false, + '自定义函数', + Container( + margin: EdgeInsets.only(left: 16.0, right: 16.0, bottom: 16.0), + child: new Text( + '示例: Fun test(a,b,c):d=a*b/(b+c);r=factorial(d)自定义函数可以由多个命令语句或单个命令语句组成,多个命令语句之间用' + '分号分隔开,最后一条命令为函数的返回结果。自定义函数会保存在文件中,方便下次使用,同名的自定义函数只会保留最新定义的' + '那个函数。自定义函数名不能为内置函数的名称。在调用自定义函数时传入参数, 例:test(3,2,-1)。注:示例中使用到的阶乘函数' + '会自动将小数部分四舍五入成整数再求阶乘。'), + )), + new HelpItem( + false, + '设置小数位数', + Container( + margin: EdgeInsets.only(left: 16.0, right: 16.0, bottom: 16.0), + child: new Text('在抽屉界面中点击设置按钮可以跳转到设置界面,滑动滑块选择保留小数到小数点后第几位'), + )), + ]; + + @override + Widget build(BuildContext context) { + return new Scaffold( + appBar: new AppBar( + title: const Text('帮助'), + ), + body: Container( + margin: const EdgeInsets.all(12.0), + child: ListView( + children: [ + new Card( + child: new ExpansionPanelList( + expansionCallback: (int i, bool b) => setState(() { + items[i].isExpanded = !items[i].isExpanded; + }), + children: items.map((HelpItem item) { + return new ExpansionPanel( + headerBuilder: (context, isExpanded) { + return new ListTile( + leading: new Text(item.header, + style: TextStyle( + fontSize: 18.0, color: Colors.deepOrange)), + ); + }, + isExpanded: item.isExpanded, + body: item.body, + ); + }).toList(), + )) + ], + ), + ), + ); + } +} + +void helpRoute(BuildContext context) { + Navigator.of(context) + .push(new MaterialPageRoute(builder: (BuildContext context) { + return new helpView(); + })); +} diff --git a/lib/command/CmdMethod.dart b/lib/command/CmdMethod.dart new file mode 100644 index 0000000..1f56309 --- /dev/null +++ b/lib/command/CmdMethod.dart @@ -0,0 +1,120 @@ +import 'dart:math'; + +///拉格朗日插值法 +List> lagrange( + List> xs, List> ys, List> rs) { + List results = []; + List value = []; + num result = 0.0; + if (xs.length != 1 || + ys.length != 1 || + rs.length != 1 || + xs[0].length != ys[0].length) { + throw FormatException( + 'lagrange函数参数行列数不符合要求,节点x值和y值,所求值必须为单行。节点x值个数必须与y值个数相等'); + } + for (int k = 0; k < rs[0].length; k++) { + for (int i = 0; i < xs[0].length; i++) { + num temp1 = 1.0; + num temp2 = 1.0; + for (int j = 0; j < xs[0].length; j++) { + if (j == i) continue; + temp1 *= (rs[0][k] - xs[0][j]); + temp2 *= (xs[0][i] - xs[0][j]); + } + value.add(temp1 / temp2); + } + for (int i = 0; i < xs[0].length; i++) { + result += ys[0][i] * value[i]; + } + results.add(result); + result = 0.0; + value = []; + } + List> list = []; + list.add(results); + return list; +} +///求和函数 +num sum(List> list) { + num sum = 0.0; + for (List l in list) { + for (num d in l) { + sum += d; + } + } + return sum; +} +///绝对值求和函数 +num absSum(List> list) { + num sum = 0.0; + for (List l in list) { + for (num d in l) { + if (d > 0) { + sum += d; + } else { + sum -= d; + } + } + } + return sum; +} +///求平均函数 +num average(List> list) { + num average = sum(list) / (list.length * list[0].length); + return average; +} +///求绝对值平均函数 +num absAverage(List> list) { + num average = absSum(list) / (list.length * list[0].length); + return average; +} +///求阶乘函数 +num factorial(num d) { + int i = d.round(); + num result = 1.0; + if (d < 0) { + throw FormatException('负数没有阶乘'); + } + if (d == 0) { + return 1.0; + } + + while (i != 1) { + result *= i; + i--; + } + return result; +} +///弧度转角度 +num radToDeg(double rad) { + return (rad / pi) * 180; +} +///格式化角度函数 +String formatDeg(num deg) { + String format; + int du = (deg ~/ 1); + var fen = (deg - du) * 60; + var miao = (fen - (fen ~/ 1)) * 60; + format = du.toString() + + '°' + + fen.floor().toString() + + '′' + + miao.floor().toString() + + '″'; + return format; +} +///反格式化角度 +num reForDeg(num deg){ + var du = deg ~/ 1; + var deci = deg - du; + var fen = (deci * 100).floor(); + var miao = (deg * 10000 - (du * 10000 + fen * 100)).floor(); + return du + fen / 60 + miao / 6000; +} +///角度转弧度 +num degToRad(num deg){ + var rad = deg / 180 * pi; + return rad; +} + diff --git a/lib/command/Matrix.dart b/lib/command/Matrix.dart new file mode 100644 index 0000000..3969f01 --- /dev/null +++ b/lib/command/Matrix.dart @@ -0,0 +1,238 @@ +import 'package:xiaoming/data/data.dart'; + +String mtoString({String name, List> list}) { + StringBuffer buffer = new StringBuffer(); + if(name != null){ + buffer.write('$name = \n'); + } + for (List l in list) { + for (num d in l) { + buffer.write(' '); + buffer.write(d.toStringAsFixed(fixedNum.round()) + ' '); + } + buffer.write("\n"); + } + return buffer.toString(); +} +///矩阵复制 +List> copyMatrix(List> list){ + List> newlist = []; + int index = 0; + for(List l in list){ + newlist.add([]); + for(num d in l){ + newlist[index].add(d); + } + index++; + } + return newlist; +} +/// 矩阵相乘 +List> m2mRide(List> list1, List> list2) { + if (list1[0].length != list2.length) { + throw FormatException("相乘矩阵的行列数不符合要求"); + } + List> newl = []; + num sum = 0.0; + for (int i = 0; i < list1.length; i++) { + newl.add([]); + for (int j = 0; j < list2[0].length; j++) { + for (int k = 0; k < list2.length; k++) { + sum += list1[i][k] * list2[k][j]; + } + newl[i].add(sum); + sum = 0.0; + } + } + return newl; +} + +/// 矩阵相减 +List> m2mMinus( + List> list1, List> list2) { + if (list1.length != list2.length || list1[0].length != list2[0].length) { + throw FormatException("相减矩阵的行列数不符合要求"); + } + List> newl = []; + for (int i = 0; i < list1.length; i++) { + newl.add([]); + for (int j = 0; j < list1[0].length; j++) { + newl[i].add(list1[i][j] - list2[i][j]); + } + } + return newl; +} + +/// 矩阵相加 +List> m2mPlus(List> list1, List> list2) { + if (list1.length != list2.length || list1[0].length != list2[0].length) { + throw FormatException("相加矩阵的行列数不符合要求"); + } + List> newl = []; + for (int i = 0; i < list1.length; i++) { + newl.add([]); + for (int j = 0; j < list1[0].length; j++) { + newl[i].add(list1[i][j] + list2[i][j]); + } + } + return newl; +} + +/// 矩阵相除 +List> m2mDivide( + List> list1, List> list2) { + return m2mRide(list1, getAdjoint(list2)); +} + +/// 矩阵乘以一个浮点数 +List> m2dRide(List> list1, num d) { + List> newl = []; + for (int i = 0; i < list1.length; i++) { + newl.add([]); + for (int j = 0; j < list1[0].length; j++) { + newl[i].add(list1[i][j] * d); + } + } + return newl; +} + +/// 矩阵除以一个浮点数 +List> m2dDivide(List> list1, num d) { + if (d == 0.0) { + throw FormatException("除数不能为零"); + } + List> newl = []; + for (int i = 0; i < list1.length; i++) { + newl.add([]); + for (int j = 0; j < list1[0].length; j++) { + newl[i].add(list1[i][j] / d); + } + } + return newl; +} + +/// 矩阵加上一个浮点数 +List> m2dPlus(List> list1, num d) { + List> newl = []; + for (int i = 0; i < list1.length; i++) { + newl.add([]); + for (int j = 0; j < list1[0].length; j++) { + newl[i].add(list1[i][j] + d); + } + } + return newl; +} + +/// 矩阵减去一个浮点数 +List> m2dMinus(List> list1, num d) { + List> newl = []; + for (int i = 0; i < list1.length; i++) { + newl.add([]); + for (int j = 0; j < list1[0].length; j++) { + newl[i].add(list1[i][j] - d); + } + } + return newl; +} + +/// 判断矩阵是否为方阵 +bool isSquare(List> list) { + if (list.length == list[0].length) { + return true; + } + return false; +} + +/// 获取给定行列式的值 +num getDetValue(List> list) { + if (!isSquare(list)) throw FormatException('只有方阵才能求行列式的值'); + if (list.length == 2) { + return list[0][0] * list[1][1] - list[0][1] * list[1][0]; + } + var result = 0.0; + int num = list.length; + var nums = new List(num); + for (int i = 0; i < list.length; i++) { + if (i % 2 == 0) { + nums[i] = list[0][i] * getDetValue(getConfactor(list, 0, i)); + } else { + nums[i] = -list[0][i] * getDetValue(getConfactor(list, 0, i)); + } + } + for (int i = 0; i < list.length; i++) { + result += nums[i]; + } + return result; +} + +/// 获取矩阵的逆阵 +List> getAdjoint(List> list) { + if (!isSquare(list)) throw FormatException('只有方阵才可逆'); + List> newdata = []; + //1阶方阵返回倒数 + if (list.length == 1) { + newdata.add([]); + newdata[0].add(1 / list[0][0]); + return newdata; + } + num A = getDetValue(list); + if (A == 0.0) throw FormatException('行列式的值为零的矩阵不能求逆'); + + //2阶方阵直接求逆 + if (list.length == 2) { + for (int i = 0; i < 2; i++) { + newdata.add([]); + } + newdata[0].add(list[1][1]); + newdata[0].add(-list[0][1]); + newdata[1].add(-list[1][0]); + newdata[1].add(list[0][0]); + newdata = m2dDivide(list, A); + return newdata; + } + for (int i = 0; i < list.length; i++) { + newdata.add([]); + for (int j = 0; j < list[0].length; j++) { + if ((i + j) % 2 == 0) { + newdata[i].add(getDetValue(getConfactor(list, i, j)) / A); + } else { + newdata[i].add(-getDetValue(getConfactor(list, i, j)) / A); + } + } + } + newdata = transList(newdata); + return newdata; +} + +/// 静态方法,获取给定方阵中 (h,v)位置的伴随阵 +List> getConfactor(List> list, int h, int v) { + if (!(h < list.length)) { + throw FormatException('h: $h 标签值越界 H: ${list.length}'); + } else if (!(v < list[0].length)) { + throw FormatException('v: $v 标签值越界 V: ${list[0].length}'); + } + List> newlist = []; + for (int i = 0; i < list.length; i++) { + newlist.add([]); + for (int j = 0; j < list[0].length; j++) { + newlist[i].add(list[i][j]); + } + } + newlist.removeAt(h); + for (List l in newlist) { + l.removeAt(v); + } + return newlist; +} + +/// 静态方法,传入源矩阵,返回对应的转置矩阵 +List> transList(List> list) { + List> newlist = []; + for (int i = 0; i < list[0].length; i++) { + newlist.add([]); + for (int j = 0; j < list.length; j++) { + newlist[i].add(list[j][i]); + } + } + return newlist; +} diff --git a/lib/command/handleCommand.dart b/lib/command/handleCommand.dart new file mode 100644 index 0000000..fdb66ab --- /dev/null +++ b/lib/command/handleCommand.dart @@ -0,0 +1,464 @@ +import 'dart:math'; + +import 'Matrix.dart'; +import 'CmdMethod.dart'; +import 'package:xiaoming/data/data.dart'; +///处理字符命令 +String handleCommand(String command) { + String cmd = command.trim(); + String result; + //矩阵赋值语法的正则表达式 + RegExp inputMatrix = new RegExp(r"[A-Za-z][A-Za-z0-9]*(\s*)=(\s*)\[(.+)\]"); + //矩阵与浮点数运算的正则表达式 + RegExp matrixArithmetic = new RegExp( + r"(^([A-Za-z][A-Za-z0-9]*)=)?([A-Za-z0-9\.\(\)]+)([\+|-|\*|/|\^]([A-Za-z0-9\.\(\)]+))*"); + RegExp definFunction = new RegExp(r"^(Fun)\s+[A-Za-z0-9]+\(.*\)\s*:(.*)"); + if (inputMatrix.firstMatch(cmd) != null) { + result = _handleGetMatrix(cmd); + //判断命令是否为矩阵和浮点数的运算 + } else if (definFunction.hasMatch(cmd)) { + result = _handleDefinFunction(cmd); + } else if (matrixArithmetic.firstMatch(cmd) != null) { + result = _handleMatrixArithmetic(cmd.replaceAll(' ', '')); + } else { + result = "$command 为未知命令"; + } + return result; +} + +/// 处理矩阵赋值的命令 +String _handleGetMatrix(String cmd) { + String name; //变量名 + int vertical; //行数, 列数 + List> list = []; //存储数据的num数列 + //将变量名和矩阵数据分隔开 + List strlist = cmd.split("="); + name = strlist.first.trim(); + //去除矩阵数字两端的空格和方括号 + String listraw = strlist.last.trim().replaceAll('[', "").replaceAll(']', ''); + //用分号分割数据并记录行数 + List lines = listraw.split(new RegExp(r'(\s*);(\s*)')); + //记录第一行列数 + vertical = lines.first.split(new RegExp(r'(\s*,\s*)|,|\s+')).length; + //往list中添加数据 + int index = 0; + for (String line in lines) { + list.add([]); + List numraws = line.split(new RegExp(r'(\s*,\s*)|,|\s+')); + if (vertical == numraws.length) { + //判断每一列个数是否相等 + for (String numraw in numraws) { + num dnum = num.tryParse(numraw); + if (dnum != null) { + list[index].add(dnum); + } else { + return '非法字符: $numraw'; + } + } + } else { + return '矩阵行数不一致'; + } + index++; + } + matrixs.remove(name); + dbs.remove(name); + matrixs[name] = list; + writeMatrix(); + return mtoString(name: name, list: list); +} + +/// 处理矩阵与浮点数的四则运算 +String _handleMatrixArithmetic(String cmd) { + //存储结果的字符串 + String result; + String newcmd; + String name; + //判断是否赋值 + if (cmd.contains('=')) { + List list = _splitEqual(cmd); + name = list[0]; + newcmd = list[1]; + } else { + newcmd = cmd; + } + //处理运算语句,返回运算结果或异常信息 + try { + var re = handleCaculStr(newcmd); + if (name != null) { + if (re is List>) { + dbs.remove(name); + matrixs[name] = copyMatrix(re); //将运算得到的矩阵添加到矩阵池 + writeMatrix(); + result = mtoString(name: name, list: matrixs[name]); + } else if (re is num) { + matrixs.remove(name); + dbs[name] = re; //将运算得到的浮点数添加到浮点池 + writeDb(); + result = '$name = ' + re.toStringAsFixed(fixedNum.round()); + } else { + result = '该类型不能存储 $re'; + } + } else { + if (re is List>) { + result = mtoString(list: re); + } else if (re is num) { + result = re.toStringAsFixed(fixedNum.round()); + } else { + result = re.toString(); + } + } + } on FormatException catch (e) { + result = e.message; + } + return result; +} + +/// 处理函数调用字符串,返回函数调用结果 +dynamic _invocationMethod(String cmd) { + int index = cmd.indexOf('('); + String methodName = cmd.substring(0, index); //存储函数名 + String methodValue = cmd.substring(index + 1, cmd.length - 1); //存储函数参数 + //处理用户自定义函数调用 + if (UFcontain(methodName)) { + UserFunction u = getUfByName(methodName); + if (u != null) { + return u.invoke(methodValue); + } + } + + //函数参数列 + List vals = getMethodValue(methodValue); + //根据函数名调用函数 + switch (methodName) { + case 'inv': + if (vals.length != 1 || vals[0] is! List>) + throw FormatException('inv函数参数传递错误'); + return getAdjoint(vals[0]); + case 'tran': + if (vals.length != 1 || vals[0] is! List>) + throw FormatException('tran函数参数传递错误'); + return transList(vals[0]); + case 'value': + if (vals.length != 1 || vals[0] is! List>) + throw FormatException('value函数参数传递错误'); + return getDetValue(vals[0]); + case 'lagrange': + if (vals.length != 3 || + !(vals[0] is List>) || + !(vals[1] is List>) || + !(vals[2] is List>)) + throw FormatException('lagrange函数参数传递错误'); + return lagrange(vals[0], vals[1], vals[2]); + case 'sum': + if (vals.length != 1 || vals[0] is! List>) + throw FormatException('sum函数参数传递错误'); + return sum(vals[0]); + case 'absSum': + if (vals.length != 1 || vals[0] is! List>) + throw FormatException('absSum函数参数传递错误'); + return absSum(vals[0]); + case 'average': + if (vals.length != 1 || vals[0] is! List>) + throw FormatException('average函数参数传递错误'); + return average(vals[0]); + case 'absAverage': + if (vals.length != 1 || vals[0] is! List>) + throw FormatException('absAverage函数参数传递错误'); + return absAverage(vals[0]); + case 'factorial': + if (vals.length != 1 || vals[0] is! num) + throw FormatException('factorial函数参数传递错误'); + return factorial(vals[0]); + + case 'sin': + if (vals.length != 1 || vals[0] is! num) + throw FormatException('sin函数参数传递错误'); + return sin(degToRad(vals[0])); + + case 'cos': + if (vals.length != 1 || vals[0] is! num) + throw FormatException('cos函数参数传递错误'); + return cos(degToRad(vals[0])); + + case 'tan': + if (vals.length != 1 || vals[0] is! num) + throw FormatException('tan函数参数传递错误'); + if (vals[0] == 90) { + throw FormatException('tan(90)为无穷大'); + } + return tan(degToRad(vals[0])); + + case 'asin': + if (vals.length != 1 || vals[0] is! num) + throw FormatException('asin函数参数传递错误'); + return radToDeg(asin(vals[0])); + + case 'acos': + if (vals.length != 1 || vals[0] is! num) + throw FormatException('acos函数参数传递错误'); + return radToDeg(acos(vals[0])); + + case 'atan': + if (vals.length != 1 || vals[0] is! num) + throw FormatException('atan函数参数传递错误'); + return radToDeg(atan(vals[0])); + + case 'radToDeg': + if (vals.length != 1 || vals[0] is! num) + throw FormatException('radToDeg函数参数传递错误'); + return radToDeg(vals[0]); + case 'formatDeg': + if (vals.length != 1 || vals[0] is! num) + throw FormatException('formatDeg函数参数传递错误'); + return formatDeg(vals[0]); + case 'reForDeg': + if (vals.length != 1 || vals[0] is! num) + throw FormatException('reForDeg函数参数传递错误'); + return reForDeg(vals[0]); + default: + throw FormatException('$methodName 为未知命令'); + } +} + +/// 处理定义函数字符串,保存定义函数 +/// Fun juli(a,b,c,d) : a * b - c * d +String _handleDefinFunction(String cmd) { + cmd = cmd.replaceAll(' ', ''); + var index1 = cmd.indexOf('('); + var index2 = cmd.indexOf(':'); + var funName = cmd.substring(3, index1); + var paras = cmd.substring(index1 + 1, index2 - 1); + var funBody = cmd.substring(index2 + 1); + var funCmds = funBody.split(';'); + List cmds = []; + List funPara = []; + for (String funcmd in funCmds) { + if (funcmd.length > 1) { + cmds.add(funcmd); + } + } + for (String para in paras.split(',')) { + funPara.add(para); + } + userFunctions.add(new UserFunction(funName, funPara, cmds)); + writeUserFun(); + return '已保存'; +} + +///通过函数名返回用户自定义函数 +UserFunction getUfByName(String funName) { + for (UserFunction u in userFunctions) { + if (u.funName == funName) { + return u; + } + } + return null; +} +///判断传入的函数名是否为用户已定义函数 +bool UFcontain(String funName) { + for (UserFunction u in userFunctions) { + if (u.funName == funName) { + return true; + } + } + return false; +} + +///获取函数参数列 +List getMethodValue(String methodValue) { + List values = methodValue.split(','); + //将参数字符串转化为实际类型 + List vals = []; + for (String str in values) { + vals.add(handleCaculStr(str)); + } + return vals; +} + +/// 传入需要运算的语句,返回结果 +dynamic handleCaculStr(String caculStr) { + var temp = new Map(); + if (matrixs.containsKey(caculStr)) { + return matrixs[caculStr]; + } + if (dbs.containsKey(caculStr)) { + return dbs[caculStr]; + } + if (num.tryParse(caculStr) != null) { + return num.tryParse(caculStr); + } + if(UFtemp.containsKey(caculStr)){ + return UFtemp[caculStr]; + } + if (caculStr.contains('(')) { + var caculStrs = []; + int index = -1; + List stack = []; + for (int i = 0; i < caculStr.length; i++) { + if (caculStr[i] == '(') { + if (stack.length == 0) { + caculStrs.add(new StringBuffer()); + index++; + } + stack.add('('); + if (stack.length == 1) { + continue; + } + } + if (caculStr[i] == ')') { + stack.removeLast(); + if (stack.length == 0) continue; + } + if (stack.length != 0) { + caculStrs[index].write(caculStr[i]); + } + } + + if (caculStrs.length != 0) { + for (int i = 0; i < caculStrs.length; i++) { + RegExp inlayMethod = new RegExp(r'[A-Za-z]+\(' + + caculStrs[i] + .toString() + .replaceAll('(', '\\(') + .replaceAll(')', '\\)') + + r'\)'); + if (inlayMethod.hasMatch(caculStr)) { + temp['caculStrTemp$i'] = + _invocationMethod(inlayMethod.firstMatch(caculStr).group(0)); + caculStr = caculStr.replaceFirst( + inlayMethod.firstMatch(caculStr).group(0), 'caculStrTemp$i'); + continue; + } + caculStr = caculStr.replaceFirst( + '(' + caculStrs[i].toString() + ')', 'caculStrTemp$i'); + temp['caculStrTemp$i'] = handleCaculStr(caculStrs[i].toString()); + } + } + } + RegExp oper = new RegExp(r'(\+|-|\*|/|\^)'); + List varibales = caculStr.split(oper); + //存储运算符的列表 + Iterable opers = oper.allMatches(caculStr); + List operStrs = []; + //运算符列表 + for (Match m in opers) { + operStrs.add(m.group(0)); + } + //运算数列表 + List nums = []; + for (String str in varibales) { + if (num.tryParse(str) == null) { + if(!UFtemp.containsKey(str)){ + if (!matrixs.containsKey(str)) { + if (!dbs.containsKey(str)) { + if (!temp.containsKey(str)) { + throw FormatException('未知的符号: $str'); + } else { + nums.add(temp[str]); + } + } else { + nums.add(dbs[str]); + } + } else { + nums.add(matrixs[str]); + } + }else { + nums.add(UFtemp[str]); + } + + } else { + nums.add(num.tryParse(str)); + } + } + //根据运算符优先级调用运算符运算,直到运算符列表中没有值时返回运算值列表中的第一个数 + while (operStrs.length != 0) { + String oper = _handleOperStrs(operStrs); + int index = operStrs.indexOf(oper); + operStrs.removeAt(index); + var num1 = nums.removeAt(index); + var num2 = nums.removeAt(index); + nums.insert(index, _handleCacul(num1, num2, oper)); + } + return nums[0]; +} + +/// 分离变量名和计算语句 +List _splitEqual(String cmd) { + List list = cmd.split('='); + return list; +} + +/// 处理运算符优先级 +String _handleOperStrs(List operStrs) { + //先乘除再加减 + for (String oper in operStrs) { + if (oper == '^') return oper; + if (oper == '*' || oper == '/') return oper; + } + return operStrs[0]; +} + +/// 处理两个值计算 +dynamic _handleCacul(dynamic num1, dynamic num2, String oper) { + if (num1 is num) { + if (num2 is num) { + //两个浮点数运算 + switch (oper) { + case '*': + return num1 * num2; + case '/': + return num1 / num2; + case '+': + return num1 + num2; + case '-': + return num1 - num2; + case '^': + return pow(num1, num2); + } + } else { + //浮点数和矩阵运算 + switch (oper) { + case '*': + return m2dRide(num2, num1); + case '/': + return m2dDivide(num2, num1); + case '+': + return m2dPlus(num2, num1); + case '-': + return m2dMinus(num2, num1); + case '^': + throw FormatException('$num2 为矩阵不能进行指数运算'); + } + } + } else { + if (num2 is num) { + //浮点数和矩阵运算 + switch (oper) { + case '*': + return m2dRide(num1, num2); + case '/': + return m2dDivide(num1, num2); + case '+': + return m2dPlus(num1, num2); + case '-': + return m2dMinus(num1, num2); + case '^': + throw FormatException('$num2 为矩阵不能进行指数运算'); + } + } else { + //两个矩阵运算 ps:矩阵已重载运算符 + switch (oper) { + case '*': + return m2mRide(num1, num2); + case '/': + return m2mDivide(num1, num2); + case '+': + return m2mPlus(num1, num2); + case '-': + return m2mMinus(num1, num2); + case '^': + throw FormatException('$num2 为矩阵不能进行指数运算'); + } + } + } +} diff --git a/lib/command/matrix.txt b/lib/command/matrix.txt new file mode 100644 index 0000000..0ec6a98 --- /dev/null +++ b/lib/command/matrix.txt @@ -0,0 +1 @@ +a:[[1.0, 2.0], [3.0, 4.0]];b:[[3.0, 1.0], [4.0, 2.0]];c:[[1], [2]]; \ No newline at end of file diff --git a/lib/data/data.dart b/lib/data/data.dart new file mode 100644 index 0000000..b1ddf8c --- /dev/null +++ b/lib/data/data.dart @@ -0,0 +1,247 @@ +import 'package:xiaoming/command/handleCommand.dart'; +import 'dart:io'; +import 'dart:async'; +import 'package:path_provider/path_provider.dart'; + + +Map dbs = new Map(); //存储浮点数变量 + +Map>> matrixs = new Map(); //存储矩阵变量 +double fixedNum=6.0; //存储小数位值 +bool isHorizontalBottons = true; +List userFunctions = []; +var UFtemp = new Map(); + +List cmdMethods = [ + new CmdMethod('矩阵求逆', 'inv', '该函数为内置函数', '用法:inv(A), A必须为方阵,且行列式的值不为零'), + new CmdMethod('矩阵转置', 'tran', '该函数为内置函数', '用法:tran(A), A必须为矩阵'), + new CmdMethod('矩阵求值', 'value', '该函数为内置函数', '用法:value(A), A必须为方阵'), + new CmdMethod('拉格朗日插值法', 'lagrange(', '该函数为内置函数', + '用法:lagrange(A,B,C), A为节点的x值列,B为节点的y值列,C为所求点的x值列'), + new CmdMethod('求和', 'sum', '该函数为内置函数', '用法:sum(A), A必须为矩阵,求矩阵内所有值的和'), + new CmdMethod( + '求绝对值之和', 'absSum', '该函数为内置函数', '用法:absSum(A), A必须为矩阵,求矩阵内所有值的绝对值之和'), + new CmdMethod( + '平均值', 'average', '该函数为内置函数', '用法:average(A), A必须为矩阵,求矩阵内所有值的平均值'), + new CmdMethod('绝对值的平均值', 'absAverage', '该函数为内置函数', + '用法:absAverage(A), A必须为矩阵,求矩阵内所有值的绝对值的平均值'), + new CmdMethod('阶乘', 'factorial', '该函数为内置函数', + '用法:factorial(A), A必须为正整数,求该数的阶乘(若传入小数会四舍五入转成整数'), + new CmdMethod('sin', 'sin', '该函数为内置函数', + "用法:sin(A), A必须为角度 例:'134.9824'或'reForDeg(134.59(分)57(秒)'"), + new CmdMethod('cos', 'cos', '该函数为内置函数', + "用法:cos(A), A必须为角度 例:'134.9824'或'reForDeg(134.59(分)57(秒)'"), + new CmdMethod('tan', 'tan', '该函数为内置函数', + "用法:tan(A), A必须为角度 例:'134.9824'或'reForDeg(134.59(分)57(秒)'"), + new CmdMethod('asin', 'asin', '该函数为内置函数', + "用法:asin(A), A必须为数字 例:'0.5 ,返回角度,若需显示度分秒则使用 formatDeg(asin(0.5))"), + new CmdMethod('acos', 'acos', '该函数为内置函数', + "用法:acos(A), A必须为数字 例:'0.5,返回角度,若需显示度分秒则使用 formatDeg(acos(0.5))"), + new CmdMethod('atan', 'atan', '该函数为内置函数', + "用法:atan(A), A必须为数字 例:'0.5,返回角度,若需显示度分秒则使用 formatDeg(atan(0.5))"), + new CmdMethod('格式化角度', 'formatDeg', '该函数为内置函数', + "用法:formatDeg(A), A必须为数字 例:'formatDeg(134.9824) = 134°59′57″ "), + new CmdMethod('反格式化角度', 'reForDeg', '该函数为内置函数', + "用法:reForDeg(A), A必须为数字 例:'reForDeg(134.5957) = 134.9824 "), + new CmdMethod('弧度转角度', 'radToDeg', '该函数为内置函数', + "用法:radToDeg(A), A必须为数字 例:'reForDeg(1) = 57.29578 "), +]; + +class CmdMethod { + String name; //函数名 + String cmdText; //函数命令 + String methodValue; //函数操作文本 + String methodDescription; //函数详细描述 + + CmdMethod(this.name, this.cmdText, this.methodValue, this.methodDescription); + +} + +class UserFunction { + String funName; + List paras; + List funCmds; + UserFunction(this.funName, this.paras, this.funCmds); + ///自定义函数执行。 + dynamic invoke(String methodVals){ + var result; + List vals = getMethodValue(methodVals); + if(vals.length != this.paras.length){ + throw FormatException('$funName 方法的参数数量传递错误'); + } + for(int i=0;i _getMatrixsFile() async { + // get the path to the document directory. + String dir = (await getApplicationDocumentsDirectory()).path; + return new File('$dir/matrixs.txt'); +} + +///获取存储数字的文件 +Future _getDbsFile() async { + // get the path to the document directory. + String dir = (await getApplicationDocumentsDirectory()).path; + return new File('$dir/dbs.txt'); +} + +///获取存储用户自定义函数的文件 +Future _getUserFunFile() async { + String dir = (await getApplicationDocumentsDirectory()).path; + return new File('$dir/userFun.txt'); +} + +///读取存储的矩阵 +Future readMatrixs() async { + File matrixFile = await _getMatrixsFile(); + if (matrixFile.existsSync()) { + String matrixsStr = matrixFile.readAsStringSync(); + List matrixStr = matrixsStr.split(';'); + for (String str in matrixStr) { + if (str.contains(':')) { + List strs = str.split(':'); + String name = strs[0]; + List> value = stringToList(strs[1]); + matrixs[name] = value; + } + } + } +} + +///读取存储的数字 +Future readDbs() async { + File dbsFile = await _getDbsFile(); + if (dbsFile.existsSync()) { + String matrixsStr = dbsFile.readAsStringSync(); + List dbstr = matrixsStr.split(';'); + for (String str in dbstr) { + if (str.contains(':')) { + List strs = str.split(':'); + String name = strs[0]; + num value = num.parse(strs[1]); + dbs[name] = value; + } + } + } +} + +///读取存储的用户自定义函数 +Future readUserFun() async { + File UserFunFile = await _getUserFunFile(); + if (UserFunFile.existsSync()) { + String userFunStr = UserFunFile.readAsStringSync(); + List ufstr = userFunStr.split('/'); + for (String str in ufstr) { + if(str.length == 0) continue; + List strs = str.split('|'); + String funName = strs[0]; + List paras = strs[1].substring(1, strs[1].length - 1).split(','); + List funCmds = strs[2].substring(1, strs[2].length - 1).split(','); + UserFunction uf = new UserFunction(funName, paras, funCmds); + userFunctions.add(uf); + } + } +} + + +Future writeUserFun() async { + File userFunFile = await _getUserFunFile(); + if(userFunFile.existsSync()){ + userFunFile.delete(); + } + userFunFile.createSync(); + var sb = new StringBuffer(); + userFunctions.forEach((UserFunction u){ + sb.write(u.funName); + sb.write('|'); + sb.write(u.paras); + sb.write('|'); + sb.write(u.funCmds); + sb.write('/'); + }); +} + +///从字符串中读取矩阵(矩阵自动写入的格式) +List> stringToList(String str) { + str = str.replaceAll(' ', ''); + List list = str.split('],['); + List> result = []; + var index = 0; + for (String s in list) { + result.add([]); + List temp = s.replaceAll('[', '').replaceAll(']', '').split(','); + for (String s1 in temp) { + result[index].add(num.parse(s1)); + } + index++; + } + return result; +} + +///将内存中的矩阵列存储到文件 +writeMatrix() async { + File matrixsFile = await _getMatrixsFile(); + if (matrixsFile.existsSync()) { + matrixsFile.delete(); + } + await matrixsFile.create(); + var sb = new StringBuffer(); + matrixs.forEach((name, value) => sb.write('$name:$value;')); + matrixsFile.writeAsStringSync(sb.toString()); +} + +///将内存中的数字列存储到文件 +writeDb() async { + File DbsFile = await _getDbsFile(); + if (DbsFile.existsSync()) { + DbsFile.delete(); + } + await DbsFile.create(); + var sb = new StringBuffer(); + dbs.forEach((name, value) => sb.write('$name:$value;')); + DbsFile.writeAsStringSync(sb.toString()); +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..251f960 --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,365 @@ +import 'package:flutter/material.dart'; +import 'package:xiaoming/command/handleCommand.dart'; +import 'package:xiaoming/View/myview.dart'; +import 'package:xiaoming/data/data.dart'; + +void main() => runApp(new MyApp()); + +class MyApp extends StatelessWidget { + @override + Widget build(BuildContext context) { + return new MaterialApp( + title: '小明同学', + theme: new ThemeData( + primaryColor: Colors.white, //使用白色的颜色主题 + ), + home: new TextScreen(), + ); + } +} + +/// 主界面,包含一个listview显示输出的文本,一个输入框和发送按钮,两排方便输入的按钮 +/// _texts用来存储要显示的文本 +/// _textFocusNode用来控制键盘弹出/收回 +/// _textController用来获取输入文本和控制输入焦点 +/// funMap存储自带函数和自定义函数 +/// 状态栏包含两个菜单控件,用来进入函数界面和数据界面 +class TextScreenState extends State with TickerProviderStateMixin { + final TextEditingController _textController = new TextEditingController(); + final FocusNode _textFocusNode = new FocusNode(); + final List _texts = []; //存储消息的列表 + bool _isComposing = false; + bool isExpanded = false; + @override + void initState() { + super.initState(); + loadData(); + } + + @override + Widget build(BuildContext context){ + return new Scaffold( + drawer: new Drawer( + child: new ListView( + children: [ + DrawerHeader( + decoration: BoxDecoration( + color: Colors.grey, + ), + child: new Center( + child: new Text('小明同学'), + )), + ListTile( + leading: Icon(Icons.settings), + title: Text('设置'), + onTap: () => settingRoute(context), + ), + ListTile( + leading: Icon(Icons.bookmark), + title: Text('保存的函数'), + onTap: () => methodRoute(context), + ), + ListTile( + leading: Icon(Icons.bookmark), + title: Text('保存的数据'), + onTap: () => dataRoute(context), + ), + ], + ), + ), + appBar: new AppBar( + title: new Text('小明同学'), + actions: [ + new IconButton( + icon: new Icon(Icons.help), + onPressed: () => helpRoute(context), + ) + ], + //AppBar显示的标题 + ), + body: Builder( + builder: (context) => Column( + children: [ + new Flexible( + child: new GestureDetector( + behavior: HitTestBehavior.translucent, + onTap: () => _textFocusNode.unfocus(), + child: new ListView.builder( + padding: new EdgeInsets.only(left: 5.0), + reverse: true, + itemBuilder: (_, int index) => _texts[index], + itemCount: _texts.length, + ))), + new Divider(height: 1.0), + new Container( + decoration: new BoxDecoration( + color: Theme.of(context).cardColor, + ), + child: _buildMethodButtons(), + ), + new Divider(height: 1.0), + new Container( + decoration: new BoxDecoration( + color: Theme.of(context).cardColor, + ), + child: _buildButtons(), + ), + new Divider( + height: 1.0, + ), + new Container( + decoration: new BoxDecoration( + color: Theme.of(context).cardColor, + ), + child: _buildTextComposer(context), + ) + ], + ))); + } + + ///创建方便输入方法名的按钮列 + Widget _buildMethodButtons() { + Widget buttonsH; + Widget buttonsV; + buttonsV = new Card( + child: new ExpansionPanelList( + expansionCallback: (int i, bool b) => setState(() { + isExpanded = !isExpanded; + }), + children: [ + new ExpansionPanel( + headerBuilder: (context, isExpanded) { + return new ListTile( + leading: new Text('内置的函数', + style: TextStyle(fontSize: 18.0, color: Colors.deepOrange)), + ); + }, + isExpanded: isExpanded, + body: LimitedBox( + maxHeight: 200.0, + child: ListView( + children: [ + new Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _buildButtonCard('Fun', width: double.infinity), + _buildButtonCard('inv(', width: double.infinity), + _buildButtonCard('tran(', width: double.infinity), + _buildButtonCard('value(', width: double.infinity), + ], + ), + new Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _buildButtonCard('sum(', width: double.infinity), + _buildButtonCard('average(', width: double.infinity), + _buildButtonCard('factorial(', width: double.infinity), + _buildButtonCard('sin(', width: double.infinity), + ], + ), + new Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _buildButtonCard('cos(', width: double.infinity), + _buildButtonCard('tan(', width: double.infinity), + _buildButtonCard('asin(', width: double.infinity), + _buildButtonCard('acos(', width: double.infinity), + ], + ), + new Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _buildButtonCard('atan(', width: double.infinity), + _buildButtonCard('formatDeg(', width: double.infinity), + _buildButtonCard('reForDeg(', width: double.infinity), + _buildButtonCard('absSum(', width: double.infinity), + ], + ), + new Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _buildButtonCard('absAverage(', width: double.infinity), + _buildButtonCard('radToDeg(', width: double.infinity), + _buildButtonCard('lagrange(', width: double.infinity), + ], + ) + ], + ), + ), + ), + ], + )); + buttonsH = new LimitedBox( + maxHeight: 40.0, + child: new ListView( + scrollDirection: Axis.horizontal, + cacheExtent: 0.0, + children: [ + _buildButtonCard('Fun', width: 50.0), + _buildButtonCard('inv(', width: 50.0), + _buildButtonCard('tran(', width: 50.0), + _buildButtonCard('value(', width: 60.0), + _buildButtonCard('sum(', width: 50.0), + _buildButtonCard('average(', width: 80.0), + _buildButtonCard('factorial(', width: 80.0), + _buildButtonCard('sin(', width: 50.0), + _buildButtonCard('cos(', width: 50.0), + _buildButtonCard('tan(', width: 50.0), + _buildButtonCard('asin(', width: 55.0), + _buildButtonCard('acos(', width: 55.0), + _buildButtonCard('atan(', width: 55.0), + _buildButtonCard('formatDeg(', width: 90.0), + _buildButtonCard('reForDeg(', width: 80.0), + _buildButtonCard('absSum(', width: 80.0), + _buildButtonCard('absAverage(', width: 90.0), + _buildButtonCard('radToDeg(', width: 90.0), + _buildButtonCard('lagrange(', width: 80.0), + ], + ), + ); + if (isHorizontalBottons) { + return buttonsH; + } + return buttonsV; + } + + /// 创建方便输入符号的按钮列 + Widget _buildButtons() { + Widget buttons; + buttons = new LimitedBox( + maxHeight: 40.0, + child: new ListView( + scrollDirection: Axis.horizontal, + children: [ + _buildButtonCard(','), + _buildButtonCard(';'), + _buildButtonCard(':'), + _buildButtonCard('['), + _buildButtonCard(']'), + _buildButtonCard('='), + _buildButtonCard('('), + _buildButtonCard(')'), + _buildButtonCard('^'), + _buildButtonCard('+'), + _buildButtonCard('-'), + _buildButtonCard('*'), + _buildButtonCard('/'), + ], + ), + ); + return buttons; + } + + /// 传入标签,创建便捷输入按钮 + Widget _buildButtonCard(String label, {double width = 50.0}) { + Widget buttonCard = new LimitedBox( + maxWidth: width, + child: new FlatButton( + padding: const EdgeInsets.all(0.0), + onPressed: () => _handleTextButton(label), + child: new Text(label, style: new TextStyle(fontSize: 14.0)), + ), + ); + return buttonCard; + } + + ///输入控件,包含一个输入框和一个按钮 + Widget _buildTextComposer(BuildContext context) { + return new IconTheme( + data: new IconThemeData(color: Theme.of(context).accentColor), + child: new Container( + margin: const EdgeInsets.symmetric(horizontal: 8.0), + child: new Row(children: [ + new Flexible( + child: new Container( + margin: new EdgeInsets.only(left: 25.0), + child: new TextField( + focusNode: _textFocusNode, + maxLines: null, + controller: _textController, + onChanged: (String text) { + setState(() { + _isComposing = text.length > 0; + }); + }, + onSubmitted: (String text) => + _handleSubmitted(context, text), + decoration: + new InputDecoration.collapsed(hintText: '输入命令'), + ))), + new Container( + margin: new EdgeInsets.symmetric(horizontal: 4.0), + child: new IconButton( + icon: new Icon(Icons.send), + onPressed: _isComposing + ? () => _handleSubmitted(context, _textController.text) + : null, + ), + ) + ]))); + } + + ///处理发送按钮的点击事件 + void _handleSubmitted(BuildContext context, String text) { + _textController.clear(); + setState(() { + _isComposing = false; + }); + TextView textView1 = new TextView( + text: text, + context: context, + animationController: new AnimationController( + duration: new Duration(milliseconds: 200), vsync: this)); + + setState(() { + _texts.insert(0, textView1); + }); + TextView textView2 = new TextView( + text: handleCommand(text), + context: context, + animationController: new AnimationController( + duration: new Duration(milliseconds: 200), vsync: this)); + + setState(() { + _texts.insert(0, textView2); + }); + + textView1.animationController.forward(); + textView2.animationController.forward(); + } + + /// 处理便捷输入按钮的点击事件 + void _handleTextButton(String text) { + if (_textController.selection.isValid) { + int index = _textController.value.selection.extentOffset; + String newStr = _textController.text.substring(0, index) + + text + + _textController.text.substring(index, _textController.text.length); + setState(() { + _isComposing = true; + }); + _textController.value = new TextEditingValue( + text: newStr, + selection: new TextSelection.collapsed(offset: index + text.length), + ); + } else { + _textController.value = new TextEditingValue( + text: text, + selection: new TextSelection.collapsed(offset: text.length), + ); + } + } + + ///退出该路由时释放动画资源 + void dispose() { + for (TextView textView in _texts) { + textView.animationController.dispose(); + } + super.dispose(); + } +} + +class TextScreen extends StatefulWidget { + @override + State createState() => new TextScreenState(); +} diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..7d3ebf4 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,392 @@ +# Generated by pub +# See https://www.dartlang.org/tools/pub/glossary#lockfile +packages: + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.33.0" + args: + dependency: transitive + description: + name: args + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.5.0" + async: + dependency: transitive + description: + name: async + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.8" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.4" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.2" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.14.11" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.2" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.6" + csslib: + dependency: transitive + description: + name: csslib + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.14.6" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.2" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + front_end: + dependency: transitive + description: + name: front_end + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.6" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.7" + html: + dependency: transitive + description: + name: html + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.13.3+3" + http: + dependency: transitive + description: + name: http + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.12.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.5" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.1.3" + io: + dependency: transitive + description: + name: io + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.3.3" + js: + dependency: transitive + description: + name: js + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.6.1+1" + json_rpc_2: + dependency: transitive + description: + name: json_rpc_2 + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.9" + kernel: + dependency: transitive + description: + name: kernel + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.3.6" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.11.3+2" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.12.3+1" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.6" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.9.6+2" + multi_server_socket: + dependency: transitive + description: + name: multi_server_socket + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.2" + node_preamble: + dependency: transitive + description: + name: node_preamble + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.4.4" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.5" + package_resolver: + dependency: transitive + description: + name: package_resolver + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.6" + path: + dependency: transitive + description: + name: path + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.6.2" + path_provider: + dependency: "direct main" + description: + name: path_provider + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.4.1" + plugin: + dependency: transitive + description: + name: plugin + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.0+3" + pool: + dependency: transitive + description: + name: pool + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.3.6" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.4.2" + quiver: + dependency: transitive + description: + name: quiver + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.0+1" + shelf: + dependency: transitive + description: + name: shelf + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.7.3+3" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.4" + shelf_static: + dependency: transitive + description: + name: shelf_static + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.8" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.2+4" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.5" + source_maps: + dependency: transitive + description: + name: source_maps + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.10.8" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.4.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.9.3" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.6.8" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.4" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.1" + test: + dependency: transitive + description: + name: test + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.3.4" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.6" + utf: + dependency: transitive + description: + name: utf + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.9.0+5" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.8" + vm_service_client: + dependency: transitive + description: + name: vm_service_client + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.6" + watcher: + dependency: transitive + description: + name: watcher + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.9.7+10" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.9" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.15" +sdks: + dart: ">=2.0.0 <3.0.0" + flutter: ">=0.1.4 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..62a422c --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,69 @@ +name: xiaoming +description: A new Flutter application. + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# Read more about versioning at semver.org. +version: 1.0.0+1 + +environment: + sdk: ">=2.0.0-dev.68.0 <3.0.0" + +dependencies: + flutter: + sdk: flutter + + path_provider: ^0.4.1 + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^0.1.2 + +dev_dependencies: + flutter_test: + sdk: flutter + + +# For information on the generic Dart part of this file, see the +# following page: https://www.dartlang.org/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.io/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.io/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.io/custom-fonts/#from-packages diff --git a/test/testCommand.dart b/test/testCommand.dart new file mode 100644 index 0000000..74a49a4 --- /dev/null +++ b/test/testCommand.dart @@ -0,0 +1,9 @@ +import 'package:test/test.dart'; +import 'package:xiaoming/command/handleCommand.dart'; + +void main(){ + test('test UserFunction invoke', () { + print(handleCommand('Fun test(a,b,c):d=a*b/(b-c);r=factorial(d)')); + expect(handleCommand('test(1,3,2)'), '6.000000'); + }); +} \ No newline at end of file diff --git a/test/widget_test.dart b/test/widget_test.dart new file mode 100644 index 0000000..75a8555 --- /dev/null +++ b/test/widget_test.dart @@ -0,0 +1,29 @@ +// This is a basic Flutter widget test. +// To perform an interaction with a widget in your test, use the WidgetTester utility that Flutter +// provides. For example, you can send tap and scroll gestures. You can also use WidgetTester to +// find child widgets in the widget tree, read text, and verify that the values of widget properties +// are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:xiaoming/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(new MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} diff --git a/xiaoming.iml b/xiaoming.iml new file mode 100644 index 0000000..e5c8371 --- /dev/null +++ b/xiaoming.iml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xiaoming_android.iml b/xiaoming_android.iml new file mode 100644 index 0000000..b050030 --- /dev/null +++ b/xiaoming_android.iml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + +