This commit is contained in:
18631081161 2024-08-06 16:58:12 +08:00
commit aae82abce5
85 changed files with 3107 additions and 0 deletions

44
.gitignore vendored Normal file
View File

@ -0,0 +1,44 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
/pubspec.lock

33
.metadata Normal file
View File

@ -0,0 +1,33 @@
# 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: "a14f74ff3a1cbd521163c5f03d68113d50af93d3"
channel: "stable"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
- platform: android
create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
- platform: ios
create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'

16
README.md Normal file
View File

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

28
analysis_options.yaml Normal file
View File

@ -0,0 +1,28 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at https://dart.dev/lints.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options

13
android/.gitignore vendored Normal file
View File

@ -0,0 +1,13 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks

58
android/app/build.gradle Normal file
View File

@ -0,0 +1,58 @@
plugins {
id "com.android.application"
id "kotlin-android"
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file("local.properties")
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader("UTF-8") { reader ->
localProperties.load(reader)
}
}
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
if (flutterVersionCode == null) {
flutterVersionCode = "1"
}
def flutterVersionName = localProperties.getProperty("flutter.versionName")
if (flutterVersionName == null) {
flutterVersionName = "1.0"
}
android {
namespace = "com.huanmeng.magicsound"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.huanmeng.magicsound"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutterVersionCode.toInteger()
versionName = flutterVersionName
}
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 = "../.."
}

View File

@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@ -0,0 +1,45 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="magicsound"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>

View File

@ -0,0 +1,6 @@
package com.huanmeng.magicsound;
import io.flutter.embedding.android.FlutterActivity;
public class MainActivity extends FlutterActivity {
}

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

18
android/build.gradle Normal file
View File

@ -0,0 +1,18 @@
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = "../build"
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(":app")
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

View File

@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
android.enableJetifier=true

View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip

25
android/settings.gradle Normal file
View File

@ -0,0 +1,25 @@
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "7.3.0" apply false
id "org.jetbrains.kotlin.android" version "1.7.10" apply false
}
include ":app"

BIN
assets/images/banner_bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 KiB

BIN
assets/images/ic_create.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
assets/images/ic_home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
assets/images/ic_me.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
assets/images/ic_music.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
assets/images/ic_vip.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

34
ios/.gitignore vendored Normal file
View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,615 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
331C80F4294D02FB00263BE5 /* RunnerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 331C80F3294D02FB00263BE5 /* RunnerTests.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
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 PBXContainerItemProxy section */
331C80F5294D02FB00263BE5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
proxyType = 1;
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
remoteInfo = Runner;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
331C80F1294D02FB00263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
331C80F3294D02FB00263BE5 /* RunnerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RunnerTests.m; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
331C80EE294D02FB00263BE5 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
331C80F2294D02FB00263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
331C80F3294D02FB00263BE5 /* RunnerTests.m */,
);
path = RunnerTests;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
331C80F2294D02FB00263BE5 /* RunnerTests */,
97C146EF1CF9000F007C117D /* Products */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
331C80F1294D02FB00263BE5 /* RunnerTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
97C146F11CF9000F007C117D /* Supporting Files */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
);
path = Runner;
sourceTree = "<group>";
};
97C146F11CF9000F007C117D /* Supporting Files */ = {
isa = PBXGroup;
children = (
97C146F21CF9000F007C117D /* main.m */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
331C80F0294D02FB00263BE5 /* RunnerTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 331C80F7294D02FB00263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
331C80ED294D02FB00263BE5 /* Sources */,
331C80EE294D02FB00263BE5 /* Frameworks */,
331C80EF294D02FB00263BE5 /* Resources */,
);
buildRules = (
);
dependencies = (
331C80F6294D02FB00263BE5 /* PBXTargetDependency */,
);
name = RunnerTests;
productName = RunnerTests;
productReference = 331C80F1294D02FB00263BE5 /* RunnerTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
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 = {
BuildIndependentTargetsInParallel = YES;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C80F0294D02FB00263BE5 = {
CreatedOnToolsVersion = 14.0;
TestTargetID = 97C146ED1CF9000F007C117D;
};
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
331C80F0294D02FB00263BE5 /* RunnerTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
331C80EF294D02FB00263BE5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
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 */
331C80ED294D02FB00263BE5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
331C80F4294D02FB00263BE5 /* RunnerTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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 PBXTargetDependency section */
331C80F6294D02FB00263BE5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 97C146ED1CF9000F007C117D /* Runner */;
targetProxy = 331C80F5294D02FB00263BE5 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
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_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_IMPLICIT_RETAIN_SELF = 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;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
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 = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.huanmeng.magicsound;
PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
331C80F8294D02FB00263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.huanmeng.magicsound.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Debug;
};
331C80F9294D02FB00263BE5 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.huanmeng.magicsound.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Release;
};
331C80FA294D02FB00263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.huanmeng.magicsound.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
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_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_IMPLICIT_RETAIN_SELF = 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;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
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 = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
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_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_IMPLICIT_RETAIN_SELF = 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;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
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 = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = 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;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.huanmeng.magicsound;
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;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.huanmeng.magicsound;
PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
331C80F7294D02FB00263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
331C80F8294D02FB00263BE5 /* Debug */,
331C80F9294D02FB00263BE5 /* Release */,
331C80FA294D02FB00263BE5 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}

View File

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

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

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

View File

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

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

6
ios/Runner/AppDelegate.h Normal file
View File

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

13
ios/Runner/AppDelegate.m Normal file
View File

@ -0,0 +1,13 @@
#import "AppDelegate.h"
#import "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

View File

@ -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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

View File

@ -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.

View File

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

View File

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

49
ios/Runner/Info.plist Normal file
View File

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

9
ios/Runner/main.m Normal file
View File

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

View File

@ -0,0 +1,16 @@
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
@interface RunnerTests : XCTestCase
@end
@implementation RunnerTests
- (void)testExample {
// If you add code to the Runner application, consider adding tests here.
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
}
@end

56
lib/common/Global.dart Normal file
View File

@ -0,0 +1,56 @@
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import '../network/NetworkConfig.dart';
const int Environment_Dev = 1;
const int Environment_Pre = 2;
const int Environment_Online = 3;
class Global {
factory Global() => _getInstance();
static Global get instance => _getInstance();
static Global? _instance;
Global._internal() {
//
}
static Global _getInstance() {
_instance ??= Global._internal();
return _instance!;
}
static const method = MethodChannel('samples.flutter.dev/battery');
static bool get isRelease => bool.fromEnvironment("dart.vm.product");
static String? flatform_name;
static Future initialize() async {
if (!NetworkConfig.isTest) {
NetworkConfig.BASE_URLS = NetworkConfig.BASE_URLS_AI;
}
// if (Platform.isIOS) {
// //ios相关代码
// flatform_name = 'iOS';
// } else if (Platform.isAndroid) {
// //android相关代码
// flatform_name = 'Android';
// } else if (Platform.isWindows) {
// //android相关代码
// flatform_name = 'Windows';
// }
// WidgetsFlutterBinding.ensureInitialized(); ///
// SystemChrome.setPreferredOrientations([
// //
// DeviceOrientation.portraitUp,
// DeviceOrientation.portraitDown
// ]);
// Global a = Global.instance;
}
}

231
lib/common/app_util.dart Normal file
View File

@ -0,0 +1,231 @@
import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:http/http.dart' as http;
import 'package:image_cropper/image_cropper.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:image_picker/image_picker.dart';
import 'package:mime/mime.dart';
import 'package:permission_handler/permission_handler.dart';
import '../network/NetworkConfig.dart';
class AppUtil {
/// [isAsset] `true`
static Future<void> saveImage(String imageUrl, {bool isAsset = false}) async {
try {
if (imageUrl == null) throw '保存失败,图片不存在!';
print(NetworkConfig.systemVersion);
///
PermissionStatus storageStatus;
///android13及以上版本 "storage"
if (int.parse(NetworkConfig.systemVersion) >= 13) {
storageStatus = await Permission.photos.status;
} else {
storageStatus = await Permission.storage.status;
}
if (storageStatus != PermissionStatus.granted) {
if (int.parse(NetworkConfig.systemVersion) >= 13) {
storageStatus = await Permission.photos.request();
} else {
storageStatus = await Permission.storage.request();
}
if (storageStatus != PermissionStatus.granted) {
throw '无法存储图片,请先授权!';
}
}
///
Uint8List imageBytes;
if (isAsset == true) {
///
ByteData bytes = await rootBundle.load(imageUrl);
imageBytes = bytes.buffer.asUint8List();
} else {
Map<String, String> map = {};
///
CachedNetworkImage image = CachedNetworkImage(imageUrl: imageUrl);
BaseCacheManager manager = image.cacheManager ?? DefaultCacheManager();
Map<String, String> headers = image.httpHeaders != null ? image.httpHeaders! : map;
File file = await manager.getSingleFile(
image.imageUrl,
headers: headers,
);
imageBytes = await file.readAsBytes();
}
///
final result = await ImageGallerySaver.saveImage(imageBytes, quality: 100);
if (result == null || result == '') throw '图片保存失败';
EasyLoading.showToast("Successfully saved");
} catch (e) {
print(e.toString());
}
}
///Widget图片
static Future<void> saveWidgetImage(ByteData bytes) async {
try {
if (bytes == null) throw '保存失败,图片不存在!';
///
PermissionStatus storageStatus;
///android13及以上版本 "storage"
if (int.parse(NetworkConfig.systemVersion) >= 13) {
storageStatus = await Permission.photos.status;
} else {
storageStatus = await Permission.storage.status;
}
if (storageStatus != PermissionStatus.granted) {
if (int.parse(NetworkConfig.systemVersion) >= 13) {
storageStatus = await Permission.photos.request();
} else {
storageStatus = await Permission.storage.request();
}
if (storageStatus != PermissionStatus.granted) {
throw '无法存储图片,请先授权!';
}
}
Uint8List imageBytes = bytes.buffer.asUint8List();
///
final result = await ImageGallerySaver.saveImage(imageBytes, quality: 100);
if (result == null || result == '') throw '图片保存失败';
EasyLoading.showToast("Successfully saved");
} catch (e) {
print(e.toString());
}
}
//
static Future<XFile> getImages() async {
final pkImage = await ImagePicker().pickImage(
source: ImageSource.gallery,
);
return pkImage!;
}
//
static cropImage(BuildContext context, String path, int index) async {
double x = 1.0;
double y = 1.0;
switch (index) {
case 0:
x = 1.0;
y = 1.0;
break;
case 1:
x = 3.0;
y = 4.0;
break;
case 2:
x = 4.0;
y = 3.0;
break;
case 3:
x = 9.0;
y = 16.0;
break;
case 4:
x = 16.0;
y = 9.0;
break;
}
CroppedFile? croppedFile = await ImageCropper().cropImage(
maxHeight: 100,
sourcePath: path,
// aspectRatioPresets: [
// CropAspectRatioPreset.square, //1:1
// ],
//aspectRatio: CropAspectRatio(ratioX: x, ratioY: y),
uiSettings: [
IOSUiSettings(
title: 'Cropper',
aspectRatioLockEnabled: true,
resetAspectRatioEnabled: false,
),
AndroidUiSettings(
toolbarTitle: 'Cropper',
toolbarColor: Color(0xFFBE6FDF),
toolbarWidgetColor: Colors.white,
activeControlsWidgetColor: Color(0xFFBE6FDF),
initAspectRatio: CropAspectRatioPreset.square,
lockAspectRatio: true,
),
WebUiSettings(context: context, viewwMode: WebViewMode.mode_1, cropBoxMovable: false
/*customDialogBuilder: (cropper, initCropper, crop, rotate, scale) {
return CropperDialog(
cropper: cropper,
initCropper: initCropper,
crop: crop,
rotate: rotate,
scale: scale,
);
},*/
),
],
);
return croppedFile;
}
//base64
static uploadImage(XFile pickedFile) async {
var file = File(pickedFile.path);
String? type = lookupMimeType(pickedFile.path); //
Uint8List imageBytes = await file.readAsBytes();
String base64 = base64Encode(imageBytes);
return "data:$type;base64,$base64";
}
//base64
static uploadImage2(File pickedFile) async {
String? type = lookupMimeType(pickedFile.path); //
Uint8List imageBytes = await pickedFile.readAsBytes();
String base64 = base64Encode(imageBytes);
return "data:$type;base64,$base64";
}
//
static String getFileSizeString({int? bytes, int decimals = 0}) {
if (bytes! <= 0) return "0 Bytes";
const suffixes = [" Bytes", "KB", "MB", "GB", "TB"];
var i = (log(bytes) / log(1024)).floor();
return ((bytes / pow(1024, i)).toStringAsFixed(decimals)) + suffixes[i];
}
// (mb)
static double getFileSizeDouble({int? bytes, int decimals = 0}) {
final kb = bytes! / 1024;
final mb = kb / 1024;
print("object===$mb");
return mb;
}
///base64
static Future<String?> networkImageToBase64(String imageUrl) async {
http.Response response = await http.get(Uri.parse(imageUrl));
final bytes = response.bodyBytes;
print("bytes===$bytes");
return bytes != null ? base64Encode(bytes) : null;
}
}

59
lib/common/func.dart Normal file
View File

@ -0,0 +1,59 @@
import 'package:flutter/material.dart';
class FunctionUtil {
static BuildContext? dialogContext;
//
static void popDialog(BuildContext context, Widget widget) {
showDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
dialogContext = context;
return widget;
});
}
//
static void bottomSheetDialog(BuildContext context, Widget widget) {
showModalBottomSheet(
backgroundColor: const Color(0x00FFFFFF),
context: context,
/* isDismissible: false,*/
isScrollControlled: true,
builder: (BuildContext context) {
dialogContext = context;
return widget;
},
);
}
//
static void bottomNoSheetDialog(BuildContext context, Widget widget) {
showModalBottomSheet(
backgroundColor: Color(0x00FFFFFF),
context: context,
isDismissible: false,
isScrollControlled: true,
enableDrag: false,
builder: (BuildContext context) {
dialogContext = context;
return WillPopScope(onWillPop: () async => false, child: widget);
});
}
//
static void pop() {
Navigator.pop(dialogContext!);
}
//push到下一级
static Future push(BuildContext context, Widget widget) {
return Navigator.push(
context,
MaterialPageRoute(
builder: (context) => widget,
),
);
}
}

203
lib/home_page.dart Normal file
View File

@ -0,0 +1,203 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:magicsound/tools/create/create_page.dart';
import 'package:magicsound/tools/home/my_home_page.dart';
import 'package:magicsound/tools/me/me_page.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'common/Global.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
StreamSubscription? subscription;
//StreamController
StreamController? streamController;
// StreamSink用于发射事件
StreamSink? get streamSink => streamController?.sink;
// Stream用于监听
Stream? get streamData => streamController?.stream;
int currentIndex = 0;
late List<BottomNavigationBarItem> items;
late List<StatefulWidget> bodyList;
late PageController pageController; //
AssetImage homeImg = const AssetImage('assets/images/ic_home.png');
AssetImage homeImgS = const AssetImage('assets/images/ic_home.png');
AssetImage createImg = const AssetImage('assets/images/ic_create.png');
AssetImage createImgS = const AssetImage('assets/images/ic_create.png');
AssetImage meImg = const AssetImage('assets/images/ic_me.png');
AssetImage meImgS = const AssetImage('assets/images/ic_me.png');
@override
void initState() {
// TODO: implement initState
super.initState();
streamController = StreamController<int>();
pageController = PageController(initialPage: 0);
streamSink!.add(0);
_firstFiring();
}
//
_firstFiring() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool boolValue = prefs.getBool('firstFiring') ?? false;
if (!boolValue) {}
}
@override
Widget build(BuildContext context) {
bottomItem();
return WillPopScope(
onWillPop: doubleClickBack,
child: Scaffold(
backgroundColor: Colors.white,
bottomNavigationBar: StreamBuilder(
stream: streamData,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data != null) {
currentIndex = snapshot.data;
return BottomNavigationBar(
items: items,
elevation: 0,
backgroundColor: Color(0xFF0E0A10),
currentIndex: snapshot.data,
onTap: onTap,
selectedItemColor: Color(0xFFFFFFFF),
unselectedItemColor: Color(0xFF818181),
selectedFontSize: 12,
unselectedFontSize: 12,
type: BottomNavigationBarType.fixed,
);
} else {
return Container();
}
},
),
body: Stack(
children: [
PageView(
controller: pageController,
onPageChanged: onPageChanged,
children: bodyList,
physics: NeverScrollableScrollPhysics(),
)
],
),
),
);
}
///
bottomItem() {
items = [
BottomNavigationBarItem(
icon: Image(
width: 24,
height: 24,
image: homeImg,
),
activeIcon: Image(
width: 24,
height: 24,
image: homeImgS,
),
label: '首页'),
BottomNavigationBarItem(
icon: Image(
width: 24,
height: 24,
image: createImg,
),
activeIcon: Image(
width: 24,
height: 24,
image: createImgS,
),
label: '创建'),
BottomNavigationBarItem(
icon: Image(
width: 24,
height: 24,
image: meImg,
),
activeIcon: Image(
width: 24,
height: 24,
image: meImgS,
),
label: '我的'),
];
bodyList = [
MyHomePage(),
CreatePage(),
MePage(),
];
}
void onPageChanged(int index) {
streamSink!.add(index);
}
void onTap(int index) {
// if (index > 1 && NetworkConfig.userId == "") {
// showLoginDialog();
// } else {
// EventBusUtil.fire(TabBarEvent(index));
pageController.animateToPage(
index,
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
// }
}
//
invokeNativeMethod(String method, Map<String, dynamic> map) async {
dynamic args;
try {
args = await Global.method.invokeMethod(method, map);
} on PlatformException catch (e) {}
}
int last = 0;
//退
Future<bool> doubleClickBack() async {
int now = DateTime.now().millisecondsSinceEpoch;
// if (currentIndex != 0) {
// EventBusUtil.fire(TabBarEvent(0));
// } else {
if (now - last > 2500) {
last = DateTime.now().millisecondsSinceEpoch;
EasyLoading.showToast("妙创音乐");
return Future.value(false);
} else {
exit(0);
}
// }
}
@override
void dispose() {
// TODO: implement dispose
streamController?.close();
subscription?.cancel();
pageController.dispose();
super.dispose();
}
}

60
lib/main.dart Normal file
View File

@ -0,0 +1,60 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:magicsound/home_page.dart';
import 'common/Global.dart';
Future<void> main() async {
await runZonedGuarded(() async {
WidgetsFlutterBinding.ensureInitialized();
Global.initialize().then((e) {
Global();
runApp(const MyApp());
if (Platform.isAndroid) {
// android状态栏为透明的沉浸set赋值MaterialApp组件会覆盖掉这个值
SystemUiOverlayStyle systemUiOverlayStyle = const SystemUiOverlayStyle(statusBarColor: Colors.transparent);
SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
}
});
}, (error, stackTrace) {
print("error==$error");
});
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
// TODO: implement initState
super.initState();
//
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '妙创音乐',
home: const HomePage(),
//
routes: <String, WidgetBuilder>{
// '/HomePage': (BuildContext context) => const HomePage(),
},
debugShowMaterialGrid: false,
//
debugShowCheckedModeBanner: false,
//debug
builder: EasyLoading.init(),
);
}
}

View File

@ -0,0 +1,43 @@
import 'dart:convert';
class BaseEntity {
int? code;
int? result;
String? message;
dynamic data;
//
BaseEntity({this.code, this.result, this.message, this.data});
//
factory BaseEntity.fromJson(json) {
dynamic data = json["content"][0]["text"];
return BaseEntity(code: 0,data: data);
}
//
factory BaseEntity.PlayfromComfyUi(json) {
Map<String, dynamic> responseData = json;
String message = responseData["type"]; //
dynamic data = responseData["name"];
return BaseEntity(code: 0, result: 0, message: message, data: data);
}
//
factory BaseEntity.PlayfromJson(json) {
Map<String, dynamic> responseData = json;
int code = responseData["code"];
// int result = responseData["Result"];
String message = responseData["message"]; //
dynamic data = responseData["data"];
return BaseEntity(code: code, result: 0, message: message, data: data);
}
}
class ErrorEntity {
int? code;
String? message;
ErrorEntity({this.code, this.message});
}

View File

@ -0,0 +1,134 @@
import 'package:dio/dio.dart';
///
class DioLogInterceptor extends Interceptor {
///
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
String requestStr = "\n 请求 - URL:${/*options.baseUrl + */ options.uri}" + " 时间 - :${DateTime.now().millisecondsSinceEpoch}\n";
//requestStr += "- HEADER:\n${options.headers.mapToStructureString()}\n";
final data = options.data;
if (data != null) {
if (data is Map)
requestStr += "- BODY:\n${data.mapToStructureString()}\n";
else if (data is FormData) {
final formDataMap = Map()
..addEntries(data.fields)
..addEntries(data.files);
requestStr += "- BODY:\n${formDataMap.mapToStructureString()}\n";
} else
requestStr += "- BODY:\n${data.toString()}\n";
}
print(requestStr);
handler.next(options);
}
///
@override
void onError(DioError err, ErrorInterceptorHandler handler) {
String errorStr = "\n==================== 响应 ====================\n"
"- URL:\n${err.requestOptions.path}\n"
"- METHOD: ${err.requestOptions.method}\n";
/* errorStr +=
"- HEADER:\n${err.response.headers.map.mapToStructureString()}\n";*/
if (err.response != null && err.response!.data != null) {
print('${err.type.toString()}');
errorStr += "- ERROR:\n${_parseResponse(err.response!)}\n";
} else {
errorStr += "- ERRORTYPE: ${err.type}\n";
errorStr += "- MSG: ${err.message}\n";
}
print(errorStr);
handler.next(err);
}
///
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
String responseStr = "\n 响应 - URL:${response.requestOptions.uri}" + " 时间 - :${DateTime.now().millisecondsSinceEpoch}\n";
/* responseStr += "- HEADER:\n{";
response.headers.forEach(
(key, list) => responseStr += "\n " + "\"$key\" : \"$list\",");
responseStr += "\n}\n";*/
//responseStr += "- STATUS: ${response.statusCode}\n";
if (response.data != null) {
responseStr += "- BODY:\n ${_parseResponse(response)}";
}
printWrapped(responseStr);
handler.next(response);
}
void printWrapped(String text) {
final pattern = new RegExp('.{1,800}'); // 800 is the size of each chunk
pattern.allMatches(text).forEach((match) => print(match.group(0)));
}
String _parseResponse(Response response) {
String responseStr = "";
var data = response.data;
if (data is Map)
responseStr += data.mapToStructureString();
else if (data is List)
responseStr += data.listToStructureString();
else
responseStr += response.data.toString();
return responseStr;
}
}
///Map拓展MAp转字符串输出
extension Map2StringEx on Map {
String mapToStructureString({int indentation = 2}) {
String result = "";
String indentationStr = " " * indentation;
if (true) {
result += " {";
this.forEach((key, value) {
if (value is Map) {
var temp = value.mapToStructureString(indentation: indentation + 2);
result += "$indentationStr" + "\"$key\":$temp,";
} else if (value is List) {
result += "$indentationStr" + "\"$key\":${value.listToStructureString(indentation: indentation + 2)},";
} else {
result += "$indentationStr" + "\"$key\":\"$value\",";
}
});
result = result.substring(0, result.length - 1);
result += indentation == 2 ? "}" : "\n${" " * (indentation - 1)}}";
}
return result;
}
}
///List拓展List转字符串输出
extension List2StringEx on List {
String listToStructureString({int indentation = 2}) {
String result = "";
String indentationStr = " " * indentation;
if (true) {
result += "$indentationStr[";
this.forEach((value) {
if (value is Map) {
var temp = value.mapToStructureString(indentation: indentation + 2);
result += "\n$indentationStr" + "\"$temp\",";
} else if (value is List) {
result += value.listToStructureString(indentation: indentation + 2);
} else {
result += "\n$indentationStr" + "\"$value\",";
}
});
result = result.substring(0, result.length - 1);
result += "\n$indentationStr]";
}
return result;
}
}

View File

@ -0,0 +1,30 @@
class NetworkConfig {
static String ServerDomain_Online = BASE_URLS[SELECT_INDEX];
static String deviceID = ""; //ID
static String systemVersion = ""; //ID
///
static int SELECT_INDEX = 0;
static List BASE_URLS = [
"http://101.43.19.200:90/",
"http://101.43.19.200:90/",
];
static List BASE_URLS_AI = [
"http://101.43.19.200:90/",
];
static bool isTest = true;
static String token = "";
static String userToken = ""; //
static String AppId = "1";
static String BossId = "";
static String userId = "";
static String userName = "";
static String Version = "1.0.0";
static String Language = "zh";
static const String accountLogin = "api/Account/AccountLogIn"; //
}

View File

@ -0,0 +1,410 @@
import 'dart:async';
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';
import 'BaseEntity.dart';
import 'DioLogInterceptor.dart';
import 'NetworkConfig.dart';
enum RequestMethod {
Post,
Get,
}
const RequestMethodValues = {
RequestMethod.Get: "GET",
RequestMethod.Post: "POST",
};
class RequestCenter {
factory RequestCenter() => _getInstance();
static RequestCenter get instance => _getInstance();
static RequestCenter? _instance;
static String signKey = "5159d59637fe1b79ba789e87443e8282";
Dio? _dio, _dioLog;
final dio = Dio();
void setupDio() {
dio.options.baseUrl = 'https://openapi.shhuanmeng.com/';
dio.interceptors.add(InterceptorsWrapper(
onRequest: (options, handler) {
//
return handler.next(options);
},
onResponse: (response, handler) {
//
return handler.next(response);
},
onError: (DioError e, handler) {
//
return handler.next(e);
},
));
}
RequestCenter._internal() {
setup();
setupDio();
}
static RequestCenter _getInstance() {
_instance ??= RequestCenter._internal();
//
if (_instance!._dio != null &&
NetworkConfig.ServerDomain_Online != _instance!._dio!.options.baseUrl) {
_instance!._dio!.options.baseUrl = NetworkConfig.ServerDomain_Online;
}
return _instance!;
}
void setup() {
//
if (null == _dio) {
_dio = Dio(BaseOptions(
baseUrl: NetworkConfig.ServerDomain_Online,
sendTimeout: const Duration(seconds: 10),
receiveTimeout: const Duration(seconds: 20),
connectTimeout: const Duration(seconds: 20),
contentType: Headers.jsonContentType,
responseType: ResponseType.json));
_dio!.interceptors.add(DioLogInterceptor());
/* _dio.interceptors.add(new ResponseInterceptors());*/
_dioLog = Dio(BaseOptions(
sendTimeout: const Duration(seconds: 10),
receiveTimeout: const Duration(seconds: 20),
connectTimeout: const Duration(seconds: 20),
contentType: Headers.jsonContentType,
responseType: ResponseType.json));
//_dioLog!.interceptors.add(DioLogInterceptor());
}
}
// post
Future<BaseEntity?> request(
path,
Map<Object, dynamic> parmeters,
Function(BaseEntity dataEntity) success,
Function(ErrorEntity errorEntity) error,
{RequestMethod? method}) async {
try {
//FormData formData = FormData.fromMap(parmeters);
Response response = await _dio!.post(path, data: parmeters,
options: Options(
headers: {
'Authorization': "Bearer ${NetworkConfig.token}"
},
));
BaseEntity entity = BaseEntity.PlayfromJson(response.data);
success(entity);
return entity;
} catch (e) {
error(ErrorEntity(code: -1, message: "$e"));
return null;
}
}
Future<BaseEntity?> requestGet(
path,
Map<String, dynamic> parmeters,
Function(BaseEntity dataEntity) success,
Function(ErrorEntity errorEntity) error,
{RequestMethod? method}) async {
try {
//FormData formData = FormData.fromMap(parmeters);
Response response = await _dio!.get(path, queryParameters: parmeters,
options: Options(
headers: {
'Authorization': "Bearer ${NetworkConfig.token}"
},
));
BaseEntity entity = BaseEntity.PlayfromJson(response.data);
success(entity);
return entity;
} catch (e) {
error(ErrorEntity(code: -1, message: "$e"));
return null;
}
}
Future<BaseEntity?> sendRequest(
Map<Object, dynamic> parmeters,
Function(BaseEntity dataEntity) success,
Function(ErrorEntity errorEntity) error,
) async {
try {
print('Request: $parmeters');
final response = await dio.post('/messages',
data: parmeters,
options: Options(
contentType: Headers.jsonContentType,
responseType: ResponseType.json,
headers: {
'x-api-key':
'sk-V6d51cc6aa28906caecb7f22803d92ae3f18cfeb799nh4mc',
'anthropic-version': "2023-06-01"
},
));
print('Response: ${response.data}');
BaseEntity entity = BaseEntity.fromJson(response.data);
success(entity);
return entity;
} on DioError catch (e) {
print('Error: ${e.response?.data}');
}
}
//post
Future<BaseEntity?> request1(
path,
Map<String, dynamic> parmeters,
Function(BaseEntity dataEntity) success,
Function(ErrorEntity errorEntity) error,
{RequestMethod? method}) async {
Map<String, dynamic> headers = {
"AppId": NetworkConfig.AppId,
"userId": NetworkConfig.userId,
"Version": NetworkConfig.Version,
"Language": NetworkConfig.Language
};
parmeters.addAll(headers);
Map<String, dynamic> parmetersSign = sign(parmeters);
try {
/*由于服务器是表单结构*/
FormData formData = FormData.fromMap(parmetersSign);
Response response = await _dio!.post(path, data: formData);
if (response != null && response.statusCode == 200) {
BaseEntity entity = BaseEntity.fromJson(response.data);
success(entity);
return entity;
} else {
error(ErrorEntity(code: -1, message: "Network Anomaly"));
return null;
}
} catch (e) {
error(ErrorEntity(code: -1, message: "Network Anomaly"));
return null;
}
}
Future<BaseEntity?> requestLog(
path,
Map<String, dynamic> parmeters,
Function(BaseEntity dataEntity) success,
Function(ErrorEntity errorEntity) error,
{RequestMethod? method}) async {
Map<String, dynamic> headers = {
"AppId": NetworkConfig.AppId,
/*"BossId": NetworkConfig.BossId,*/
"userId": NetworkConfig.userId,
"Version": NetworkConfig.Version,
"Language": NetworkConfig.Language
};
parmeters.addAll(headers);
Map<String, dynamic> parmetersSign = sign(parmeters);
try {
/*由于服务器是表单结构*/
FormData formData = FormData.fromMap(parmetersSign);
Response response = await _dioLog!.post(path, data: formData);
if (response != null && response.statusCode == 200) {
BaseEntity entity = BaseEntity.fromJson(response.data);
success(entity);
return entity;
} else {
error(ErrorEntity(code: -1, message: "Network Anomaly"));
return null;
}
} catch (e) {
error(ErrorEntity(code: -1, message: "Network Anomaly"));
return null;
}
}
// post
Future<BaseEntity?> requestPay(
path,
Map<String, dynamic> parmeters,
Function(BaseEntity dataEntity) success,
Function(ErrorEntity errorEntity) error,
{RequestMethod? method}) async {
Map<String, dynamic> headers = {
"AppId": NetworkConfig.AppId,
/*"BossId": NetworkConfig.BossId,*/
"userId": NetworkConfig.userId,
"Version": NetworkConfig.Version,
"Language": NetworkConfig.Language
};
parmeters.addAll(headers);
Map<String, dynamic> parmetersSign = sign(parmeters);
try {
FormData formData = FormData.fromMap(parmetersSign);
Response response = await _dio!.post(path, data: formData);
if (response != null && response.statusCode == 200) {
BaseEntity entity = BaseEntity.fromJson(response.data);
success(entity);
return entity;
} else {
error(ErrorEntity(code: -1, message: "未知错误"));
return null;
}
} catch (e) {
ErrorEntity(code: -1, message: "未知错误");
return null;
}
}
// post ()
Future<BaseEntity?> requestWeb(
path,
Map<String, dynamic> parmeters,
Function(BaseEntity dataEntity) success,
Function(ErrorEntity errorEntity) error,
{RequestMethod? method}) async {
Map<String, dynamic> headers = {
"AppId": NetworkConfig.AppId,
/*"BossId": NetworkConfig.BossId,*/
"UserId": NetworkConfig.userId,
"Version": NetworkConfig.Version,
"Language": NetworkConfig.Language
};
parmeters.addAll(headers);
//
Map<String, dynamic> parmetersSign = sign(parmeters);
try {
/*由于服务器是表单结构*/
FormData formData = FormData.fromMap(parmetersSign);
Response response = await _dio!.post(path, data: formData);
if (response != null && response.statusCode == 200) {
BaseEntity entity = BaseEntity.fromJson(response.data);
Map<String, dynamic> parmeters = {
"AppId": NetworkConfig.AppId,
/*"BossId": NetworkConfig.BossId,*/
"UserId": NetworkConfig.userId,
"Token": entity.message
};
Map<String, dynamic> p1 = sign(parmeters);
parmeters.addAll(p1);
//data
entity.data = gettoken(parmeters);
success(entity);
return entity;
} else {
error(ErrorEntity(code: -1, message: "Network Anomaly"));
return null;
}
} catch (e) {
ErrorEntity(code: -1, message: "Network Anomaly");
return null;
}
}
//
ErrorEntity _getErrorMsg(DioError error) {
switch (error.type) {
case DioErrorType.cancel:
{
return ErrorEntity(code: -1, message: "请求取消");
}
break;
case DioErrorType.connectionTimeout:
{
return ErrorEntity(code: -1, message: "连接超时");
}
break;
case DioErrorType.sendTimeout:
{
return ErrorEntity(code: -1, message: "请求超时");
}
break;
case DioErrorType.receiveTimeout:
{
return ErrorEntity(code: -1, message: "响应超时");
}
break;
case DioErrorType.badResponse:
{
try {
int errCode = error.response!.statusCode!;
String errorMsg = error.response!.statusMessage!;
return ErrorEntity(code: errCode, message: errorMsg);
} on Exception catch (_) {
return ErrorEntity(code: -1, message: "Network Anomaly");
}
}
break;
default:
{
return ErrorEntity(code: -1, message: "Network Anomaly");
}
}
}
Map<String, dynamic> sign(Map<String, dynamic> parmeters) {
List<String> keys = parmeters.keys.toList();
// key排序
keys.sort((a, b) {
List<int> al = a.codeUnits;
List<int> bl = b.codeUnits;
for (int i = 0; i < al.length; i++) {
if (bl.length <= i) return 1;
if (al[i] > bl[i]) {
return 1;
} else if (al[i] < bl[i]) return -1;
}
return 0;
});
Map<String, dynamic> treeMap = Map();
keys.forEach((element) {
treeMap[element] = parmeters[element];
});
String data = "";
for (dynamic str in treeMap.values) {
if (str != null) {
data = data + str.toString();
}
}
treeMap["sign"] = generateMd5(data + NetworkConfig.userToken);
return treeMap;
}
String gettoken(Map<String, dynamic> parmeters) {
List<String> keys = parmeters.keys.toList();
// key排序
keys.sort((a, b) {
List<int> al = a.codeUnits;
List<int> bl = b.codeUnits;
for (int i = 0; i < al.length; i++) {
if (bl.length <= i) return 1;
if (al[i] > bl[i]) {
return 1;
} else if (al[i] < bl[i]) return -1;
}
return 0;
});
Map<String, dynamic> treeMap = Map();
keys.forEach((element) {
treeMap[element] = parmeters[element];
});
String data = "";
treeMap.forEach((key, value) {
if (data == "") {
data = key + "=" + value.toString();
} else {
data = data + "&" + key + "=" + value.toString();
}
});
return data;
}
String generateMd5(String data) {
return md5.convert(utf8.encode(data)).toString();
}
}

View File

@ -0,0 +1,18 @@
import 'package:flutter/material.dart';
class CreatePage extends StatefulWidget {
const CreatePage({super.key});
@override
State<CreatePage> createState() => _CreatePageState();
}
class _CreatePageState extends State<CreatePage> {
@override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.center,
child: Text('创建'),
);
}
}

View File

@ -0,0 +1,76 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
class MyUnderlineTabIndicator extends Decoration {
const MyUnderlineTabIndicator({
this.borderSide = const BorderSide(width: 2.0, color: Colors.white),
this.insets = EdgeInsets.zero, required this.wantWidth,
}) : assert(borderSide != null),
assert(insets != null);
final BorderSide borderSide;
final EdgeInsetsGeometry insets;
final double wantWidth;
@override
Decoration? lerpFrom(Decoration? a, double t) {
if (a is MyUnderlineTabIndicator) {
return MyUnderlineTabIndicator(
wantWidth:5,
borderSide: BorderSide.lerp(a.borderSide, borderSide, t),
insets: EdgeInsetsGeometry.lerp(a.insets, insets, t)!,
);
}
return super.lerpFrom(a, t);
}
@override
Decoration? lerpTo(Decoration? b, double t) {
if (b is MyUnderlineTabIndicator) {
return MyUnderlineTabIndicator(
borderSide: BorderSide.lerp(borderSide, b.borderSide, t),
insets: EdgeInsetsGeometry.lerp(insets, b.insets, t)!, wantWidth: 5,
);
}
return super.lerpTo(b, t);
}
@override
_UnderlinePainter createBoxPainter([ VoidCallback? onChanged ]) {
return _UnderlinePainter(this, onChanged);
}
Rect _indicatorRectFor(Rect rect, TextDirection textDirection) {
assert(rect != null);
assert(textDirection != null);
final Rect indicator = insets.resolve(textDirection).deflateRect(rect);
//
double cw = (indicator.left + indicator.right) / 2;
return Rect.fromLTWH(cw - wantWidth / 2,
indicator.bottom - borderSide.width, wantWidth, borderSide.width);
}
@override
Path getClipPath(Rect rect, TextDirection textDirection) {
return Path()..addRect(_indicatorRectFor(rect, textDirection));
}
}
class _UnderlinePainter extends BoxPainter {
_UnderlinePainter(this.decoration, VoidCallback? onChanged)
: assert(decoration != null),
super(onChanged);
final MyUnderlineTabIndicator decoration;
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
assert(configuration != null);
assert(configuration.size != null);
final Rect rect = offset & configuration.size!;
final TextDirection textDirection = configuration.textDirection!;
final Rect indicator = decoration._indicatorRectFor(rect, textDirection).deflate(decoration.borderSide.width / 2.0);
final Paint paint = decoration.borderSide.toPaint()..strokeCap = StrokeCap.round;
canvas.drawLine(indicator.bottomLeft, indicator.bottomRight, paint);
}
}

View File

@ -0,0 +1,20 @@
import 'package:flutter/material.dart';
class MusicListPage extends StatefulWidget {
final int type;
MusicListPage(Key key, {required this.type});
@override
State<MusicListPage> createState() => _MusicListPageState();
}
class _MusicListPageState extends State<MusicListPage> {
@override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.center,
child: Text("${widget.type}"),
);
}
}

View File

@ -0,0 +1,157 @@
import 'package:flutter/material.dart';
import 'TabUnderLine.dart';
import 'music_list_page.dart';
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
final List<String> tablist = [
'推荐',
'摇滚',
'民谣',
'爵士',
'说唱',
'流行',
'古风',
];
late List<Widget> tabView; //tab对应
var tabs; //
late TabController _tabController;
@override
void initState() {
// TODO: implement initState
super.initState();
tabs = _tabsItem();
tabView = _tabViewItem();
_tabController = TabController(initialIndex: 0, length: tabs.length, vsync: this);
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
_tabsItem() {
return tablist.map((res) {
int index = tablist.indexOf(res);
return Container(
alignment: Alignment.center,
child: Text(res),
);
}).toList();
}
_tabViewItem() {
return tablist.map((res) {
int index = tablist.indexOf(res);
return MusicListPage(
UniqueKey(),
type: index,
);
}).toList();
}
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return Scaffold(
backgroundColor: Color(0xFF0E0A10),
body: Stack(
children: [
Image(width: size.width, height: 180, image: AssetImage('assets/images/banner_bg.png')),
Column(
children: [
Container(
margin: EdgeInsets.only(top: 24, left: 17, right: 17),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image(width: 79, height: 19, image: AssetImage('assets/images/ic_music.png')),
Image(width: 49, height: 45, image: AssetImage('assets/images/ic_vip.png')),
],
),
),
Expanded(
child:
// Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.start,
// children: [
// Container(
// height: 40,
// alignment: Alignment.centerLeft,
// child: TabBar(
// controller: _tabController,
// isScrollable: true,
// indicator: MyUnderlineTabIndicator(wantWidth: 20),
// indicatorSize: TabBarIndicatorSize.label,
// indicatorColor: Colors.white,
// labelColor: Colors.white,
// unselectedLabelColor: Color(0xFF999999),
// tabs: tabs,
// ),
// ),
// Expanded(
// child: TabBarView(
// controller: _tabController,
// children: tabView,
// ))
// ],
// ),
DefaultTabController(
length: tabs.length,
child: Column(
children: <Widget>[
Container(
width: double.infinity,
height: 40,
padding: const EdgeInsets.only(top: 10),
alignment: Alignment.centerLeft,
child: TabBar(
tabs: tabs,
controller: _tabController,
indicator: MyUnderlineTabIndicator(wantWidth: 20),
unselectedLabelColor: Color(0xFF9B9B9B),
//tabs里面的字体样式优先级最高
unselectedLabelStyle: TextStyle(fontSize: 15, fontWeight: FontWeight.normal),
//tabs里面的字体样式优先级最高
labelColor: Colors.white,
//tabs里面的字体样式优先级最高
labelStyle: TextStyle(fontSize: 15, fontWeight: FontWeight.w600),
//tabs里面的字体样式优先级最高
isScrollable: true,
//
indicatorWeight: 3.0,
//线20
onTap: (int index) {
},
),
),
Expanded(
child: TabBarView(
controller: _tabController,
children: tabView,
))
],
)),
)
],
),
],
),
);
}
}

18
lib/tools/me/me_page.dart Normal file
View File

@ -0,0 +1,18 @@
import 'package:flutter/material.dart';
class MePage extends StatefulWidget {
const MePage({super.key});
@override
State<MePage> createState() => _MePageState();
}
class _MePageState extends State<MePage> {
@override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.center,
child: Text('我的'),
);
}
}

67
pubspec.yaml Normal file
View File

@ -0,0 +1,67 @@
name: magicsound
description: "A new Flutter project."
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# 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.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.0+1
environment:
sdk: '>=3.4.1 <4.0.0'
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.6
dev_dependencies:
flutter_test:
sdk: flutter
dio: ^5.4.3+1
intl: ^0.19.0
cupertino_icons: ^1.0.6
flutter_easyloading: ^3.0.5
flutter_spinkit: ^5.2.1
crypto: ^3.0.3
shared_preferences: ^2.2.3
json_annotation: ^4.9.0
cached_network_image: ^3.2.3
image_cropper: ^7.0.5
flutter_native_image: ^0.0.6
photo_view: ^0.14.0
image_picker: ^0.8.4
permission_handler: ^10.4.5
image_gallery_saver: ^2.0.3
web_socket_channel: ^3.0.0
flutter_client_sse: ^2.0.1
expandable_text: ^2.3.0
card_swiper: ^3.0.1
flutter_slidable: ^3.1.0
flutter_keyboard_visibility: ^6.0.0
webview_flutter: ^4.8.0
package_info_plus: ^8.0.0
flutter:
uses-material-design: true
assets:
- assets/
- assets/images/

30
test/widget_test.dart Normal file
View File

@ -0,0 +1,30 @@
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility in the flutter_test package. 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:magicsound/main.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(const 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);
});
}