├── .flutter-plugins-dependencies
├── .gitignore
├── .metadata
├── .travis.yml
├── README.md
├── android
├── app
│ ├── build.gradle
│ ├── release
│ │ ├── app-release.apk
│ │ └── output.json
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ └── com
│ │ │ └── example
│ │ │ └── flutterwanandroid
│ │ │ └── MainActivity.kt
│ │ └── res
│ │ ├── drawable
│ │ └── launch_background.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_2.png
│ │ └── splash.png
│ │ ├── values
│ │ └── styles.xml
│ │ └── xml
│ │ ├── network_security_config.xml
│ │ └── provider_paths.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── key.properties
├── res
│ └── values
│ │ └── strings_en.arb
├── settings.gradle
└── settings_aar.gradle
├── assets
├── app.db
└── images
│ ├── 23038-animatonblue.gif
│ ├── 7903-error-404.gif
│ ├── 8021-empty-and-lost.gif
│ ├── calendar.png
│ ├── house.png
│ ├── p1.png
│ ├── p2.png
│ ├── p3.png
│ ├── paimaiLogo.png
│ └── plane.png
├── ios
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ ├── Release.xcconfig
│ └── flutter_export_environment.sh
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ └── contents.xcworkspacedata
└── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-App-1024x1024@1x.png
│ │ ├── Icon-App-20x20@1x.png
│ │ ├── Icon-App-20x20@2x.png
│ │ ├── Icon-App-20x20@3x.png
│ │ ├── Icon-App-29x29@1x.png
│ │ ├── Icon-App-29x29@2x.png
│ │ ├── Icon-App-29x29@3x.png
│ │ ├── Icon-App-40x40@1x.png
│ │ ├── Icon-App-40x40@2x.png
│ │ ├── Icon-App-40x40@3x.png
│ │ ├── Icon-App-60x60@2x.png
│ │ ├── Icon-App-60x60@3x.png
│ │ ├── Icon-App-76x76@1x.png
│ │ ├── Icon-App-76x76@2x.png
│ │ └── Icon-App-83.5x83.5@2x.png
│ └── LaunchImage.imageset
│ │ ├── Contents.json
│ │ ├── LaunchImage.png
│ │ ├── LaunchImage@2x.png
│ │ ├── LaunchImage@3x.png
│ │ └── README.md
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ └── Runner-Bridging-Header.h
├── lib
├── api
│ ├── Api.dart
│ ├── common_service.dart
│ ├── dio_manager.dart
│ ├── error_entity.dart
│ └── http.dart
├── components
│ ├── cate_card.dart
│ ├── cate_card_container.dart
│ ├── cate_card_item.dart
│ ├── category.dart
│ ├── disclaimer_msg.dart
│ ├── home_banner.dart
│ ├── list_refresh.dart
│ ├── list_view_item.dart
│ ├── navi_list.dart
│ ├── pagination.dart
│ ├── project_list.dart
│ └── search_input.dart
├── constant
│ ├── color_config.dart
│ └── shared_preferences_keys.dart
├── event
│ ├── event_bus.dart
│ ├── event_model.dart
│ └── event_theme.dart
├── generated
│ └── i18n.dart
├── init
│ ├── app.dart
│ └── app_init.dart
├── main.dart
├── main_page.dart
├── model
│ ├── article.dart
│ ├── banner.dart
│ ├── cat.dart
│ ├── coin.dart
│ ├── collect.dart
│ ├── constant.dart
│ ├── navi_bean.dart
│ ├── project_model.dart
│ ├── provider
│ │ └── state_provider.dart
│ ├── search_history.dart
│ ├── splash.dart
│ ├── store.dart
│ ├── theme.dart
│ ├── tree_list.dart
│ ├── user.dart
│ └── user_model.dart
├── routers
│ ├── application.dart
│ ├── navigation_service.dart
│ ├── router.dart
│ ├── router_handler.dart
│ └── router_path.dart
├── utils
│ ├── bugly.dart
│ ├── event.dart
│ ├── image.dart
│ ├── provider.dart
│ ├── push.dart
│ ├── random.dart
│ ├── shared_preferences.dart
│ ├── sql.dart
│ ├── style.dart
│ ├── toast.dart
│ └── update_dialog.dart
├── views
│ ├── about_page
│ │ ├── about_page.dart
│ │ ├── page_dragger.dart
│ │ ├── page_reveal.dart
│ │ ├── pager_indicator.dart
│ │ └── pages.dart
│ ├── article_list_page
│ │ └── article_list_page.dart
│ ├── cat_page
│ │ ├── cat_page.dart
│ │ └── cat_sub_page.dart
│ ├── coin_rank_page
│ │ └── coin_rank_page.dart
│ ├── collection_page
│ │ └── collection_page.dart
│ ├── home_page
│ │ └── home_page.dart
│ ├── login_page
│ │ └── login_page.dart
│ ├── mine_page
│ │ └── mine_page.dart
│ ├── my_collect_list_page
│ │ └── my_collect_list_page.dart
│ ├── page_not_found.dart
│ ├── photo_detail_page
│ │ └── photo_detail_page.dart
│ ├── photo_page
│ │ ├── item_card.dart
│ │ └── photo_page.dart
│ ├── register_page
│ │ └── register_page.dart
│ ├── search_page
│ │ └── search_page.dart
│ ├── splash_page
│ │ └── SplashPage.dart
│ └── web_page
│ │ └── webview_page.dart
└── widgets
│ ├── error
│ ├── error_page.dart
│ └── flutter_crash_plugin.dart
│ ├── list_item.dart
│ ├── loading
│ ├── dialog_manager.dart
│ └── loading_dialog.dart
│ └── state
│ ├── empty_view.dart
│ └── load_state.dart
├── pubspec.yaml
├── res
└── values
│ ├── strings_en.arb
│ └── strings_zh.arb
├── screenshot
├── about.png
├── cat.png
├── change-color.png
├── home.png
├── login.png
├── mine.png
├── my-collect.png
├── project.png
├── rank.png
├── splash.png
├── theme.png
└── web-detail.png
└── test
└── widget_test.dart
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.lock
4 | *.log
5 | *.pyc
6 | *.swp
7 | .DS_Store
8 | .atom/
9 | .buildlog/
10 | .history
11 | .svn/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # Visual Studio Code related
20 | .vscode/
21 |
22 | # Flutter/Dart/Pub related
23 | **/doc/api/
24 | .dart_tool/
25 | .flutter-plugins
26 | .packages
27 | .pub-cache/
28 | .pub/
29 | build/
30 |
31 | # Android related
32 | **/android/**/gradle-wrapper.jar
33 | **/android/.gradle
34 | **/android/captures/
35 | **/android/gradlew
36 | **/android/gradlew.bat
37 | **/android/local.properties
38 | **/android/**/GeneratedPluginRegistrant.java
39 |
40 | # iOS/XCode related
41 | **/ios/**/*.mode1v3
42 | **/ios/**/*.mode2v3
43 | **/ios/**/*.moved-aside
44 | **/ios/**/*.pbxuser
45 | **/ios/**/*.perspectivev3
46 | **/ios/**/*sync/
47 | **/ios/**/.sconsign.dblite
48 | **/ios/**/.tags*
49 | **/ios/**/.vagrant/
50 | **/ios/**/DerivedData/
51 | **/ios/**/Icon?
52 | **/ios/**/Pods/
53 | **/ios/**/.symlinks/
54 | **/ios/**/profile
55 | **/ios/**/xcuserdata
56 | **/ios/.generated/
57 | **/ios/Flutter/App.framework
58 | **/ios/Flutter/Flutter.framework
59 | **/ios/Flutter/Generated.xcconfig
60 | **/ios/Flutter/app.flx
61 | **/ios/Flutter/app.zip
62 | **/ios/Flutter/flutter_assets/
63 | **/ios/ServiceDefinitions.json
64 | **/ios/Runner/GeneratedPluginRegistrant.*
65 |
66 | # Exceptions to above rules.
67 | !**/ios/**/default.mode1v3
68 | !**/ios/**/default.mode2v3
69 | !**/ios/**/default.pbxuser
70 | !**/ios/**/default.perspectivev3
71 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
72 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: caf6027d81cc88540193dd42f9952251bc84e6fd
8 | channel: master
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 |
2 | matrix:
3 | include:
4 | #声明Android运行环境
5 | - os: linux
6 | language: android
7 | dist: trusty
8 | licenses:
9 | - 'android-sdk-preview-license-.+'
10 | - 'android-sdk-license-.+'
11 | - 'google-gdk-license-.+'
12 | #声明需要安装的Android组件
13 | android:
14 | components:
15 | - tools
16 | - platform-tools
17 | - build-tools-28.0.3
18 | - android-28
19 | - sys-img-armeabi-v7a-google_apis-28
20 | - extra-android-m2repository
21 | - extra-google-m2repository
22 | - extra-google-android-support
23 | jdk: oraclejdk8
24 | sudo: false
25 | addons:
26 | apt:
27 | sources:
28 | - ubuntu-toolchain-r-test
29 | packages:
30 | - libstdc++6
31 | - fonts-droid
32 | #确保sdkmanager是最新的
33 | before_script:
34 | - yes | sdkmanager --update
35 | script:
36 | - yes | flutter doctor --android-licenses
37 | - flutter doctor && flutter -v build apk
38 |
39 | #声明iOS的运行环境
40 | - os: osx
41 | language: objective-c
42 | osx_image: xcode10.2
43 | script:
44 | - flutter doctor && flutter -v build ios --no-codesign
45 | install:
46 | - git clone https://github.com/flutter/flutter.git
47 | - export PATH="$PATH:`pwd`/flutter/bin"
48 |
49 |
50 | #声明构建需要执行的命令
51 | script:
52 | - yes | flutter doctor --android-licenses
53 | - flutter doctor && flutter -v build apk
54 |
55 | #对发布前的构建产物进行预处理,打包成ipa
56 | before_deploy:
57 | - mkdir app && mkdir app/Payload
58 | - cp -r build/ios/iphoneos/Runner.app app/Payload
59 | - pushd app && zip -r -m app.ipa Payload && popd
60 | #将ipa上传至github release
61 | deploy:
62 | provider: releases
63 | api_key: ${GITHUB_TOKEN}
64 | file:
65 | - app/app.ipa
66 | skip_cleanup: true
67 | on:
68 | tags: true
69 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # flutter_wanandroid
2 |
3 | an app that mimics the [flutter-go](https://github.com/alibaba/flutter-go) UI effect and adds some cool effects...
4 |
5 |
6 |
7 | # thx
8 |
9 | - [flutter-go](https://github.com/alibaba/flutter-go)
10 | - [玩Android](https://www.wanandroid.com/)
11 | - open source lib author
12 |
13 | ## screenshot
14 |
15 | talk is cheap,show me the picture!!
16 |
17 |
18 |
19 | 
20 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new FileNotFoundException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '3'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.2'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 |
28 | def keystorePropertiesFile = rootProject.file("key.properties")
29 | def keystoreProperties = new Properties()
30 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
31 |
32 | android {
33 | compileSdkVersion 28
34 |
35 | sourceSets {
36 | main.java.srcDirs += 'src/main/kotlin'
37 | }
38 |
39 | lintOptions {
40 | disable 'InvalidPackage'
41 | }
42 |
43 | defaultConfig {
44 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
45 | applicationId "com.example.flutterwanandroid"
46 | minSdkVersion 21
47 | targetSdkVersion 28
48 | versionCode flutterVersionCode.toInteger()
49 | versionName flutterVersionName
50 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
51 | ndk {
52 | //设置支持的SO库架构
53 | abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
54 | }
55 |
56 | manifestPlaceholders = [
57 | JPUSH_PKGNAME : applicationId,
58 | JPUSH_APPKEY : "e510f2e57ab1cb6d33fdc233", // NOTE: JPush 上注册的包名对应的 Appkey.
59 | JPUSH_CHANNEL : "developer-default", //暂时填写默认值即可.
60 | ]
61 |
62 | // // 自定义输出配置
63 | // android.applicationVariants.all { variant ->
64 | // variant.outputs.all {
65 | // outputFileName = "${variant.name}_${variant.versionName}_${variant.name}.apk"
66 | // }
67 | // }
68 | }
69 |
70 | signingConfigs {
71 | release {
72 | keyAlias keystoreProperties['keyAlias']
73 | keyPassword keystoreProperties['keyPassword']
74 | storeFile file(keystoreProperties['storeFile'])
75 | storePassword keystoreProperties['storePassword']
76 | }
77 | }
78 |
79 | buildTypes {
80 | release {
81 | // Signing with the debug keys for now, so `flutter run --release` works.
82 | signingConfig signingConfigs.release
83 | }
84 | release {
85 | // Signing with the debug keys for now, so `flutter run --debug` works.
86 | signingConfig signingConfigs.debug
87 | }
88 | }
89 |
90 | lintOptions {
91 | checkReleaseBuilds false
92 | abortOnError false
93 | }
94 | }
95 |
96 | flutter {
97 | source '../..'
98 | }
99 |
100 | dependencies {
101 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
102 | testImplementation 'junit:junit:4.12'
103 | androidTestImplementation 'androidx.test:runner:1.1.1'
104 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
105 | // androidTestImplementation 'com.android.support.test:runner:1.0.2'
106 | // androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
107 | }
108 |
--------------------------------------------------------------------------------
/android/app/release/app-release.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/android/app/release/app-release.apk
--------------------------------------------------------------------------------
/android/app/release/output.json:
--------------------------------------------------------------------------------
1 | [{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
22 |
28 |
35 |
39 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
54 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/example/flutterwanandroid/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.flutterwanandroid
2 |
3 | import android.os.Bundle
4 |
5 | import io.flutter.app.FlutterActivity
6 | import io.flutter.plugin.common.MethodChannel
7 | import android.content.Context
8 | import android.content.ContextWrapper
9 | import android.content.Intent
10 | import android.content.IntentFilter
11 | import android.os.BatteryManager
12 | import android.os.Build.VERSION
13 | import android.os.Build.VERSION_CODES
14 | import android.net.Uri
15 | import android.util.Log
16 | import io.flutter.plugins.GeneratedPluginRegistrant
17 |
18 |
19 | class MainActivity: FlutterActivity() {
20 | private val TAG = MainActivity::class.java.simpleName
21 | private val CHANNEL = "com.flutter.method.channel"
22 |
23 | override fun onCreate(savedInstanceState: Bundle?) {
24 | super.onCreate(savedInstanceState)
25 | GeneratedPluginRegistrant.registerWith(this)
26 | MethodChannel(flutterView, CHANNEL).setMethodCallHandler { call, result ->
27 | when(call.method){
28 | "getBatteryLevel" ->{
29 | val batteryLevel = getBatteryLevel()
30 | if (batteryLevel != -1) {
31 | result.success(batteryLevel)
32 | }else {
33 | result.error("UNAVAILABLE", "Battery level not available.", null)
34 | }
35 | }
36 | "openAppStore" ->{
37 | try {
38 | var appId = ""
39 | var packageName = "com.tencent.mm"
40 | if (call.hasArgument("appId")){
41 | appId = call.argument("appId").toString()
42 | Log.e(TAG,"appId: $appId")
43 | }
44 | if (call.hasArgument("packageName")){
45 | packageName = call.argument("packageName").toString()
46 | Log.e(TAG,"packageName: $packageName")
47 | }
48 | val uri = Uri.parse("market://details?id=$packageName")
49 | val intent = Intent(Intent.ACTION_VIEW, uri)
50 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
51 | startActivity(intent)
52 | } catch (e: Exception) {
53 | result.error("UNAVAILABLE", "没有安装应用市场", null)
54 | }
55 | }
56 | else ->{
57 | result.notImplemented()
58 | }
59 | }
60 | }
61 | }
62 | private fun getBatteryLevel(): Int {
63 | val batteryLevel: Int
64 | batteryLevel = if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
65 | val batteryManager = getSystemService(Context.BATTERY_SERVICE) as BatteryManager
66 | batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
67 | } else {
68 | val intent = ContextWrapper(applicationContext).registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
69 | intent!!.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
70 | }
71 |
72 | return batteryLevel
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | -
8 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_2.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/android/app/src/main/res/mipmap-xxxhdpi/splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/android/app/src/main/res/xml/network_security_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/res/xml/provider_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.3.50'
3 | repositories {
4 | google()
5 | jcenter()
6 | // maven { url 'https://maven.aliyun.com/repository/google' }
7 | // maven { url 'https://maven.aliyun.com/repository/jcenter' }
8 | // maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
9 |
10 | }
11 |
12 | dependencies {
13 | classpath 'com.android.tools.build:gradle:3.5.3'
14 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
15 | }
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | google()
21 | jcenter()
22 | // maven { url 'https://maven.aliyun.com/repository/google' }
23 | // maven { url 'https://maven.aliyun.com/repository/jcenter' }
24 | // maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
25 | }
26 | }
27 |
28 | rootProject.buildDir = '../build'
29 | subprojects {
30 | project.buildDir = "${rootProject.buildDir}/${project.name}"
31 | }
32 | subprojects {
33 | project.evaluationDependsOn(':app')
34 | }
35 |
36 | task clean(type: Delete) {
37 | delete rootProject.buildDir
38 | }
39 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.enableR8=true
3 | android.useAndroidX=true
4 | android.enableJetifier=true
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | #distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
7 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
8 |
--------------------------------------------------------------------------------
/android/key.properties:
--------------------------------------------------------------------------------
1 | storePassword=123456
2 | keyPassword=key123456
3 | keyAlias=key0
4 | storeFile=C:/Users/Aller/AndroidStudioProjects/flutter_wanandroid.jks
--------------------------------------------------------------------------------
/android/res/values/strings_en.arb:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/android/settings_aar.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/assets/app.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/assets/app.db
--------------------------------------------------------------------------------
/assets/images/23038-animatonblue.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/assets/images/23038-animatonblue.gif
--------------------------------------------------------------------------------
/assets/images/7903-error-404.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/assets/images/7903-error-404.gif
--------------------------------------------------------------------------------
/assets/images/8021-empty-and-lost.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/assets/images/8021-empty-and-lost.gif
--------------------------------------------------------------------------------
/assets/images/calendar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/assets/images/calendar.png
--------------------------------------------------------------------------------
/assets/images/house.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/assets/images/house.png
--------------------------------------------------------------------------------
/assets/images/p1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/assets/images/p1.png
--------------------------------------------------------------------------------
/assets/images/p2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/assets/images/p2.png
--------------------------------------------------------------------------------
/assets/images/p3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/assets/images/p3.png
--------------------------------------------------------------------------------
/assets/images/paimaiLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/assets/images/paimaiLogo.png
--------------------------------------------------------------------------------
/assets/images/plane.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/assets/images/plane.png
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Flutter/flutter_export_environment.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # This is a generated file; do not edit or check into version control.
3 | export "FLUTTER_ROOT=D:\dong\flutter\flutter_windows_1.17.0-stable\flutter"
4 | export "FLUTTER_APPLICATION_PATH=D:\dong\android\project_github\Flutter-WanAndroid"
5 | export "FLUTTER_TARGET=lib\main.dart"
6 | export "FLUTTER_BUILD_DIR=build"
7 | export "SYMROOT=${SOURCE_ROOT}/../build\ios"
8 | export "OTHER_LDFLAGS=$(inherited) -framework Flutter"
9 | export "FLUTTER_FRAMEWORK_DIR=D:\dong\flutter\flutter_windows_1.17.0-stable\flutter\bin\cache\artifacts\engine\ios"
10 | export "FLUTTER_BUILD_NAME=1.0.2"
11 | export "FLUTTER_BUILD_NUMBER=3"
12 | export "DART_OBFUSCATION=false"
13 | export "TRACK_WIDGET_CREATION=false"
14 | export "TREE_SHAKE_ICONS=false"
15 | export "PACKAGE_CONFIG=.packages"
16 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
56 |
58 |
64 |
65 |
66 |
67 |
68 |
69 |
75 |
77 |
83 |
84 |
85 |
86 |
88 |
89 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YGragon/Flutter-WanAndroid/ef3ac56a2dc090362f7c1a9c6aa14e9fb6fd6a2d/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | flutter_wanandroid
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
--------------------------------------------------------------------------------
/lib/api/Api.dart:
--------------------------------------------------------------------------------
1 | class Api{
2 | /// baseUrl
3 | static const String BASE_URL = "http://www.wanandroid.com/";
4 | /// 首页 banner
5 | static const String HOME_BANNER = "http://www.wanandroid.com/banner/json";
6 | /// 首页文章列表
7 | static const String HOME_ARTICLE_LIST = "http://www.wanandroid.com/article/list/";
8 | /// 知识体系
9 | static const String SYSTEM_TREE = "http://www.wanandroid.com/tree/json";
10 | /// 知识体系详情
11 | static const String SYSTEM_TREE_CONTENT = "http://www.wanandroid.com/article/list/";
12 | /// 导航列表数据
13 | static const String NAVI_LIST = "http://www.wanandroid.com/navi/json";
14 | /// 项目分类
15 | static const String PROJECT_TREE = "http://www.wanandroid.com/project/tree/json";
16 | /// 项目列表
17 | static const String PROJECT_LIST = "http://www.wanandroid.com/project/list/";
18 | /// 搜索列表
19 | static const String SEARCH_LIST = "https://www.wanandroid.com/article/query/";
20 | /// 登录接口
21 | static const String LOGIN = "https://www.wanandroid.com/user/login";
22 | /// 注册接口
23 | static const String REGISTER = "https://www.wanandroid.com/user/register";
24 | /// 退出接口
25 | static const String LOGOUT = "https://www.wanandroid.com/user/logout/json";
26 | /// 我的收藏接口
27 | static const String MY_COLLECT = "https://www.wanandroid.com/lg/collect/list/";
28 | /// 积分排行榜
29 | static const String COIN_RANK = "$BASE_URL coin/rank/";
30 | /// 每日一图
31 | static const String DAY_IMAGE = "https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=zh-CN";
32 | }
--------------------------------------------------------------------------------
/lib/api/dio_manager.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:io';
3 | import 'package:cookie_jar/cookie_jar.dart';
4 | import 'package:dio/dio.dart';
5 | import 'package:dio_cookie_manager/dio_cookie_manager.dart';
6 | import 'package:flutter_wanandroid/api/Api.dart';
7 | import 'package:flutter_wanandroid/api/error_entity.dart';
8 |
9 | class DioManager{
10 | Dio _dio;
11 |
12 | /// 网络请求配置信息
13 | BaseOptions _getOptions() {
14 | return BaseOptions(
15 | //请求基地址,可以包含子路径
16 | baseUrl: Api.BASE_URL,
17 | //连接服务器超时时间,单位是毫秒.
18 | connectTimeout: 10000,
19 | //响应流上前后两次接受到数据的间隔,单位为毫秒。
20 | receiveTimeout: 5000,
21 | headers: {
22 | HttpHeaders.userAgentHeader: "dio",
23 | "api": "1.0.0",
24 | },
25 | //请求的Content-Type,默认值是"application/json; charset=utf-8",Headers.formUrlEncodedContentType会自动编码请求体.
26 | contentType: Headers.formUrlEncodedContentType,
27 | //表示期望以那种格式(方式)接受响应数据。接受4种类型 `json`, `stream`, `plain`, `bytes`. 默认值是 `json`,
28 | responseType: ResponseType.json,
29 | );
30 | }
31 | /// 单例
32 | DioManager._internal() {
33 | _dio = new Dio(_getOptions());
34 | var cookieJar= CookieJar();
35 | _dio.interceptors.add(CookieManager(cookieJar));
36 | _dio.interceptors.add(LogInterceptor(responseBody: false)); //开启请求日志,放在最后一个拦截器
37 | // Print cookies
38 | print("cookie===>>>:${cookieJar.loadForRequest(Uri.parse(Api.BASE_URL))}");
39 | }
40 |
41 | static DioManager singleton = DioManager._internal();
42 |
43 | factory DioManager() => singleton;
44 |
45 | get dio {
46 | return _dio;
47 | }
48 |
49 | /// get请求
50 | get(url, {data, options, cancelToken, showLoading, hideLoading, success, Function(ErrorEntity) error}) async {
51 | try {
52 | showLoading();
53 | Response response = await dio.get(url, queryParameters: data, options: options, cancelToken: cancelToken);
54 | if (response != null) {
55 | if(response.statusCode == 200){
56 | print('get response:${response.data}');
57 | success(response.data);
58 | }else{
59 | error(ErrorEntity(code: -2, message: "未知错误"));
60 | }
61 | } else {
62 | error(ErrorEntity(code: -1, message: "未知错误"));
63 | }
64 | hideLoading();
65 | } on DioError catch(e) {
66 | /// 格式化输出错误信息
67 | formatError(e);
68 | hideLoading();
69 | }finally{
70 | hideLoading();
71 | }
72 | }
73 |
74 | /// post 请求
75 | post(url, {data, options, cancelToken, showLoading, hideLoading, Function(T) success, Function(ErrorEntity) error}) async {
76 | try {
77 | showLoading();
78 | Response response = await dio.post(url, queryParameters: data, options: options, cancelToken: cancelToken);
79 | if (response != null) {
80 | if(response.statusCode == 200){
81 | print('post response:${response.data}');
82 | success(response.data);
83 | }else{
84 | error(ErrorEntity(code: -2, message: "未知错误"));
85 | }
86 | } else {
87 | error(ErrorEntity(code: -1, message: "未知错误"));
88 | }
89 | hideLoading();
90 | } on DioError catch (e) {
91 | formatError(e);
92 | hideLoading();
93 | } finally {
94 | hideLoading();
95 | }
96 | }
97 |
98 | /// 下载文件
99 | downloadFile(urlPath, savePath, progress) async {
100 | try {
101 | Response response = await dio.download(urlPath, savePath, onReceiveProgress: (int count, int total){
102 | //进度
103 | progress(count,total);
104 | });
105 | print('downloadFile data---------${response.data}');
106 | } on DioError catch (e) {
107 | print('downloadFile error---------$e');
108 | formatError(e);
109 | } finally{
110 |
111 | }
112 | }
113 |
114 | /// error 统一处理
115 | void formatError(DioError e) {
116 | if (e.type == DioErrorType.CONNECT_TIMEOUT) {
117 | print("连接超时");
118 | } else if (e.type == DioErrorType.SEND_TIMEOUT) {
119 | print("请求超时");
120 | } else if (e.type == DioErrorType.RECEIVE_TIMEOUT) {
121 | print("响应超时");
122 | } else if (e.type == DioErrorType.RESPONSE) {
123 | print("出现异常");
124 | } else if (e.type == DioErrorType.CANCEL) {
125 | print("请求取消");
126 | } else {
127 | print("未知错误");
128 | }
129 | }
130 |
131 |
132 | }
--------------------------------------------------------------------------------
/lib/api/error_entity.dart:
--------------------------------------------------------------------------------
1 | /// 网络请求返回错误
2 | class ErrorEntity {
3 | int code;
4 | String message;
5 | ErrorEntity({this.code, this.message});
6 | }
--------------------------------------------------------------------------------
/lib/api/http.dart:
--------------------------------------------------------------------------------
1 | import 'package:cookie_jar/cookie_jar.dart';
2 | import 'package:dio/dio.dart';
3 | import 'package:dio_cookie_manager/dio_cookie_manager.dart';
4 | import 'package:flutter_wanandroid/api/error_entity.dart';
5 |
6 | /// 网络请求工具
7 | class Http{
8 | /// 单例
9 | Http._internal();
10 |
11 | static final Dio dio = Dio(BaseOptions(
12 | baseUrl: "https://www.wanandroid.com",
13 | connectTimeout: 5000,
14 | receiveTimeout: 3000,
15 | ));
16 |
17 | ///初始化dio
18 | static init() {
19 | ///初始化cookie
20 | var cookieJar= CookieJar();
21 | dio.interceptors.add(CookieManager(cookieJar));
22 | dio.interceptors.add(LogInterceptor(responseBody: false)); //开启请求日志,放在最后一个拦截器
23 |
24 | /// 添加拦截器
25 | dio.interceptors.add(InterceptorsWrapper(onRequest: (RequestOptions options) {
26 | print("请求之前");
27 | return options;
28 | }, onResponse: (Response response) {
29 | print("响应之前");
30 | return response;
31 | }, onError: (DioError e) {
32 | print("错误之前");
33 | handleError(e);
34 | return e;
35 | }));
36 | }
37 |
38 | ///error统一处理
39 | static void handleError(DioError e) {
40 | switch (e.type) {
41 | case DioErrorType.CONNECT_TIMEOUT:
42 | print("连接超时");
43 | break;
44 | case DioErrorType.SEND_TIMEOUT:
45 | print("请求超时");
46 | break;
47 | case DioErrorType.RECEIVE_TIMEOUT:
48 | print("响应超时");
49 | break;
50 | case DioErrorType.RESPONSE:
51 | print("出现异常");
52 | break;
53 | case DioErrorType.CANCEL:
54 | print("请求取消");
55 | break;
56 | default:
57 | print("未知错误");
58 | break;
59 | }
60 | }
61 |
62 | /// get请求
63 | static Future get(String url, [Map params]) async {
64 | Response response;
65 | if (params != null) {
66 | response = await dio.get(url, queryParameters: params);
67 | } else {
68 | response = await dio.get(url);
69 | }
70 | return response.data;
71 | }
72 |
73 | /// get请求
74 | static Future getData(url, {data, options, cancelToken, success, Function(ErrorEntity) error}) async {
75 | try {
76 | Response response = await dio.get(url, queryParameters: data, options: options, cancelToken: cancelToken);
77 | if (response != null) {
78 | if(response.statusCode == 200){
79 | print('get response:${response.data}');
80 | success(response.data);
81 | }else{
82 | error(ErrorEntity(code: -2, message: "未知错误"));
83 | }
84 | } else {
85 | error(ErrorEntity(code: -1, message: "未知错误"));
86 | }
87 | } on DioError catch(e) {
88 | /// 格式化输出错误信息
89 | handleError(e);
90 | }finally{
91 | }
92 | }
93 |
94 | /// post 表单请求
95 | static Future post(String url, [Map params]) async {
96 | Response response = await dio.post(url, queryParameters: params);
97 | return response.data;
98 | }
99 |
100 | /// post body请求
101 | static Future postJson(String url, [Map data]) async {
102 | Response response = await dio.post(url, data: data);
103 | return response.data;
104 | }
105 |
106 | /// post 请求
107 | static Future postData(url, {data, options, cancelToken, Function(T) success, Function(ErrorEntity) error}) async {
108 | try {
109 | Response response = await dio.post(url, queryParameters: data, options: options, cancelToken: cancelToken);
110 | if (response != null) {
111 | if(response.statusCode == 200){
112 | print('post response:${response.data}');
113 | success(response.data);
114 | }else{
115 | error(ErrorEntity(code: -2, message: "未知错误"));
116 | }
117 | } else {
118 | error(ErrorEntity(code: -1, message: "未知错误"));
119 | }
120 | } on DioError catch (e) {
121 | handleError(e);
122 | } finally {
123 | }
124 | }
125 |
126 | /// 下载文件
127 | static Future downloadFile(urlPath, savePath) async {
128 | Response response;
129 | try {
130 | response = await dio.download(urlPath, savePath,
131 | onReceiveProgress: (int count, int total) {
132 | //进度
133 | print("$count $total");
134 | });
135 | } on DioError catch (e) {
136 | handleError(e);
137 | }
138 | return response.data;
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/lib/components/cate_card.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter_wanandroid/api/common_service.dart';
5 | import 'package:flutter_wanandroid/components/cate_card_container.dart';
6 | import 'package:flutter_wanandroid/model/navi_bean.dart';
7 | import 'package:flutter_wanandroid/model/cat.dart';
8 |
9 | class CateCard extends StatefulWidget {
10 | // 猫耳标题
11 | final String category;
12 | final List categorieLists;
13 | final List naviLists;
14 |
15 | CateCard({@required this.category, this.categorieLists, this.naviLists});
16 |
17 | @override
18 | _CateCardState createState() => _CateCardState();
19 | }
20 |
21 | class _CateCardState extends State {
22 |
23 | @override
24 | Widget build(BuildContext context) {
25 | double screenWidth = MediaQuery.of(context).size.width;
26 |
27 | return Container(
28 | width: screenWidth,
29 | padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 10.0),
30 | /// 层叠布局,让猫耳icon在左上角
31 | child: Stack(
32 | children: [
33 | Container(
34 | width: screenWidth - 20,
35 | margin: const EdgeInsets.only(top: 30.0, bottom: 0.0),
36 | decoration: BoxDecoration(
37 | color: Colors.white,
38 | borderRadius: BorderRadius.circular(4.0),
39 | ),
40 | child: Column(
41 | children: [
42 | /// 标题
43 | Container(
44 | width: screenWidth - 20,
45 | padding: const EdgeInsets.only(left: 65.0, top: 3.0),
46 | height: 30.0,
47 | // 一级标题
48 | child: Text(
49 | widget.category,
50 | style: TextStyle(
51 | color: Theme.of(context).primaryColor,
52 | fontSize: 18.0,
53 | ),
54 | ),
55 | ),
56 | /// 网格布局
57 | _buildWidgetContainer(),
58 | ],
59 | ),
60 | ),
61 | /// 标题左边的icon
62 | Positioned(
63 | left: 0.0,
64 | top: 0.0,
65 | child: Container(
66 | height: 60.0,
67 | width: 60.0,
68 | decoration: BoxDecoration(
69 | color: Colors.white,
70 | borderRadius: BorderRadius.circular(30.0),
71 | ),
72 | child: Center(
73 | child: Container(
74 | decoration: BoxDecoration(
75 | color: Theme.of(context).primaryColor,
76 | borderRadius: BorderRadius.circular(23.0),
77 | ),
78 | height: 46.0,
79 | width: 46.0,
80 | child: Icon(
81 | Icons.link,
82 | color: Colors.white,
83 | size: 30.0,
84 | ),
85 | ),
86 | ),
87 | ),
88 | )
89 | ],
90 | ),
91 | );
92 | }
93 |
94 | Widget _buildWidgetContainer() {
95 | /// 没有数据显示空页面
96 | if(widget.category == "导航"){
97 | if (widget.naviLists.length == 0) {
98 | return Container();
99 | }
100 | /// 有数据显示网格布局
101 | return Container(
102 | padding: const EdgeInsets.only(bottom: 10.0, top: 5.0),
103 | decoration: BoxDecoration(
104 | image: DecorationImage(
105 | image: AssetImage('assets/images/paimaiLogo.png'),
106 | alignment: Alignment.bottomRight),
107 | ),
108 | child: CateCardContainer(categories: widget.naviLists, columnCount: 3, type: 0, isWidgetPoint: false),
109 | );
110 | }else{
111 | if (widget.categorieLists.length == 0) {
112 | return Container();
113 | }
114 | /// 有数据显示网格布局
115 | return Container(
116 | padding: const EdgeInsets.only(bottom: 10.0, top: 5.0),
117 | decoration: BoxDecoration(
118 | image: DecorationImage(
119 | image: AssetImage('assets/images/paimaiLogo.png'),
120 | alignment: Alignment.bottomRight),
121 | ),
122 | child: CateCardContainer(categories: widget.categorieLists, columnCount: 3, type: 1, isWidgetPoint: false),
123 | );
124 | }
125 |
126 |
127 |
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/lib/components/cate_card_container.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 | import 'dart:math';
3 |
4 | /// 猫耳页面 一行 主布局
5 | /// 作者 :龙衣
6 |
7 | import 'package:flutter/material.dart';
8 | import 'package:fluro/fluro.dart';
9 | import 'package:flutter_wanandroid/components/cate_card_item.dart';
10 | import 'package:flutter_wanandroid/model/cat.dart';
11 | import 'package:flutter_wanandroid/model/navi_bean.dart';
12 | import 'package:flutter_wanandroid/routers/router_path.dart';
13 | import 'package:flutter_wanandroid/views/cat_page/cat_sub_page.dart';
14 | import '../routers/application.dart';
15 |
16 | /// 每一个猫耳布局展示的内容
17 | class CateCardContainer extends StatelessWidget {
18 | final int columnCount; //一行几个
19 | final List categories;
20 | final bool isWidgetPoint;
21 | final int type; // 0表示导航,其他表示体系和项目
22 |
23 |
24 | CateCardContainer(
25 | {Key key,
26 | @required this.categories,
27 | @required this.columnCount,
28 | @required this.type,
29 | @required this.isWidgetPoint})
30 | : super(key: key);
31 |
32 | List _buildColumns(context) {
33 | List _listWidget = [];
34 | List _listRows = [];
35 | int addI;
36 | for (int i = 0, length = categories.length; i < length; i += columnCount) {
37 | _listRows = [];
38 | for (int innerI = 0; innerI < columnCount; innerI++) {
39 | addI = innerI + i;
40 | if (addI < length) {
41 | dynamic item = categories[addI];
42 | _listRows.add(
43 | Expanded(
44 | flex: 1,
45 | child: CateCardItem(
46 | title: item.name,
47 | onTap: () {
48 | /// 导航
49 | /// 如果有 articles 集合 进入列表页面
50 | ///
51 | /// 项目,体系
52 | /// 如果有 cats 集合 ,有子分类,进入子分类页面
53 | /// 如果有 cats 集合 ,进入列表页面
54 | if(type == 0){
55 | // 导航
56 | var articles = item.articles as List ;
57 | var name = item.name;
58 | var cid = item.cid;
59 | print("articles--->"+articles.toString());
60 | if(articles != null){
61 | // 项目,体系
62 | Application.router.navigateTo(context, "${RouterPath.treeList}?id=${Uri.encodeComponent(cid.toString())}&name=${Uri.encodeComponent(name.toString())}");
63 | }
64 | }else{
65 | var cats = item.cats as List ;
66 | print("cats--->"+cats.toString());
67 | if(cats != null){
68 | // 项目,体系
69 | if(cats.isNotEmpty){
70 | // 继续显示猫耳朵
71 | print("跳转猫耳-- 传递list->"+cats.toString());
72 | Navigator.push(context, MaterialPageRoute(builder: (context) => CatSubPage(name:item.name, cats: cats,)));
73 | }else{
74 | Application.router.navigateTo(context, "${RouterPath.treeList}?id=${Uri.encodeComponent(item.id.toString())}&name=${Uri.encodeComponent(item.name.toString())}");
75 | }
76 | }
77 | }
78 |
79 | },
80 | index: addI,
81 | totalCount: length,
82 | rowLength: columnCount,
83 | textSize: isWidgetPoint ? 'middle' : 'small',
84 | ),
85 | ),
86 | );
87 | } else {
88 | _listRows.add(
89 | Expanded(
90 | flex: 1,
91 | child: Container(),
92 | ),
93 | );
94 | }
95 | }
96 | _listWidget.add(
97 | Row(
98 | children: _listRows,
99 | ),
100 | );
101 | }
102 | return _listWidget;
103 | }
104 |
105 | @override
106 | Widget build(BuildContext context) {
107 | return Column(
108 | children: _buildColumns(context),
109 | );
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/lib/components/cate_card_item.dart:
--------------------------------------------------------------------------------
1 | /// 猫耳网格 item
2 | /// 作者:龙衣
3 |
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter_wanandroid/utils/style.dart';
6 |
7 | String _widgetName;
8 |
9 | class CateCardItem extends StatelessWidget {
10 | final String title;
11 | final VoidCallback onTap;
12 | final int index; //用于计算border
13 | final int totalCount;
14 | final int rowLength;
15 | final String textSize;
16 |
17 | CateCardItem(
18 | {this.title,
19 | this.onTap,
20 | this.index,
21 | this.totalCount,
22 | this.rowLength,
23 | this.textSize});
24 |
25 | Border _buildBorder(context) {
26 | Border _border;
27 | bool isRight = (index % rowLength) == (rowLength - 1); //是不是最右边的,决定是否有右侧边框
28 | var currentRow = (index + 1) % rowLength > 0
29 | ? (index + 1) ~/ rowLength + 1
30 | : (index + 1) ~/ rowLength;
31 | int totalRow = totalCount % rowLength > 0
32 | ? totalCount ~/ rowLength + 1
33 | : totalCount ~/ rowLength;
34 | if (currentRow < totalRow && isRight) {
35 | //不是最后一行,是最右边
36 | _border = Border(
37 | bottom: const BorderSide(
38 | width: 1.0, color: Color(CateCardColor.borderColor)),
39 | );
40 | }
41 | if (currentRow < totalRow && !isRight) {
42 | _border = Border(
43 | right: const BorderSide(
44 | width: 1.0, color: Color(CateCardColor.borderColor)),
45 | bottom: const BorderSide(
46 | width: 1.0, color: Color(CateCardColor.borderColor)),
47 | );
48 | }
49 | if (currentRow == totalRow && !isRight) {
50 | _border = Border(
51 | right: const BorderSide(
52 | width: 1.0, color: Color(CateCardColor.borderColor)),
53 | );
54 | }
55 | return _border;
56 | }
57 |
58 | @override
59 | Widget build(BuildContext context) {
60 | _widgetName = title.replaceFirst(
61 | //首字母转为大写
62 | title.substring(0, 1),
63 | title.substring(0, 1).toUpperCase());
64 | Icon widgetIcon;
65 | widgetIcon = Icon(Icons.link);
66 |
67 | final textStyle = (textSize == 'middle')
68 | ? TextStyle(fontSize: 13.8, fontFamily: 'MediumItalic')
69 | : TextStyle(fontSize: 16.0);
70 | return InkWell(
71 | onTap: onTap,
72 | child: Container(
73 | decoration: new BoxDecoration(
74 | border: _buildBorder(context),
75 | ),
76 | padding: const EdgeInsets.symmetric(vertical: 30.0, horizontal: 10.0),
77 | height: 150.0,
78 | child: Column(
79 | mainAxisAlignment: MainAxisAlignment.center,
80 | mainAxisSize: MainAxisSize.max,
81 | children: [
82 | widgetIcon,
83 | SizedBox(
84 | height: 8.0,
85 | ),
86 | Text(_widgetName, style: textStyle),
87 | ],
88 | ),
89 | ),
90 | );
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/lib/components/category.dart:
--------------------------------------------------------------------------------
1 | /// 从 猫耳Tab 进入的 二级分类页面
2 | /// 作者:龙衣
3 |
4 | import 'dart:async';
5 |
6 | import 'package:flutter/material.dart';
7 | import 'package:flutter_wanandroid/components/cate_card_container.dart';
8 | import 'package:flutter_wanandroid/model/article.dart';
9 | import 'package:flutter_wanandroid/model/cat.dart';
10 |
11 | import '../routers/application.dart';
12 |
13 |
14 | enum CategoryPage { Cat, WidgetDemo }
15 |
16 | class CategoryHome extends StatefulWidget {
17 | CategoryHome(this.id, this.title);
18 | final int id;
19 | final String title;
20 |
21 | @override
22 | _CategoryHome createState() => new _CategoryHome();
23 | }
24 |
25 | class _CategoryHome extends State {
26 | String title = '';
27 |
28 | List cats = [];
29 | /// 分类层级
30 | List catHistory = new List();
31 |
32 |
33 | @override
34 | void initState() {
35 | super.initState();
36 | // 初始化加入顶级的name
37 | /// 请求网络,通过 id 去获取,当前下面的 children 是否有数据
38 | // this.getCatByName(widget.name).then((Cat cat) {
39 | // catHistory.add(cat);
40 | // searchCatOrWigdet();
41 | // });
42 | }
43 |
44 |
45 | Future back() {
46 | if (catHistory.length == 1) {
47 | return Future.value(true);
48 | }
49 | catHistory.removeLast();
50 | searchCatOrWigdet();
51 | return Future.value(false);
52 | }
53 |
54 | void go(Cat cat) {
55 | catHistory.add(cat);
56 | searchCatOrWigdet();
57 | }
58 |
59 | void searchCatOrWigdet() async {
60 |
61 | List _cats = new List();
62 |
63 |
64 | this.setState(() {
65 | cats = _cats;
66 | });
67 | }
68 |
69 | void onCatgoryTap(Cat cat) {
70 | go(cat);
71 | }
72 |
73 | /// item 点击
74 | void onWidgetTap(Cat cat) {
75 | /// 如果 cats 不空
76 | /// 跳转 category 页面:传递 id ,title
77 | // Application.router.navigateTo(context, "$targetRouter");
78 | }
79 |
80 | /// 内容显示
81 | Widget _buildContent() {
82 | CateCardContainer wiContaienr = CateCardContainer(
83 | categories: cats,
84 | columnCount: 3,
85 | isWidgetPoint:true
86 | );
87 | return Container(
88 | padding: const EdgeInsets.only(bottom: 10.0, top: 5.0),
89 | decoration: BoxDecoration(
90 | color: Colors.white,
91 | image: DecorationImage(
92 | image: AssetImage('assets/images/paimaiLogo.png'),
93 | alignment: Alignment.bottomRight),
94 | ),
95 | child: wiContaienr,
96 | );
97 | }
98 |
99 | @override
100 | Widget build(BuildContext context) {
101 | return Scaffold(
102 | appBar: AppBar(
103 | title: Text(title),
104 | ),
105 | body: WillPopScope(
106 | onWillPop: () {
107 | return back();
108 | },
109 | child: ListView(
110 | children: [
111 | _buildContent(),
112 | ],
113 | ),
114 | // child: Container(color: Colors.blue,child: Text('123'),),
115 | ),
116 | );
117 | }
118 | }
119 |
120 |
--------------------------------------------------------------------------------
/lib/components/home_banner.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter_wanandroid/model/banner.dart';
5 |
6 |
7 |
8 | class HomeBanner extends StatefulWidget {
9 | final List bannerStories;
10 | final OnTapBannerItem onTap;
11 |
12 | HomeBanner(this.bannerStories, this.onTap, {Key key})
13 | :super(key: key);
14 |
15 | @override
16 | State createState() {
17 | return _BannerState();
18 | }
19 | }
20 |
21 | class _BannerState extends State {
22 | int virtualIndex = 0;
23 | int realIndex = 1;
24 | PageController controller;
25 | Timer timer;
26 |
27 | @override
28 | void initState() {
29 | super.initState();
30 | controller = PageController(initialPage: realIndex);
31 | timer = Timer.periodic(Duration(seconds: 5), (timer) { // 自动滚动
32 | /// print(realIndex);
33 | controller.animateToPage(realIndex + 1,
34 | duration: Duration(milliseconds: 300),
35 | curve: Curves.linear);
36 | });
37 | }
38 |
39 | @override
40 | void dispose() {
41 | super.dispose();
42 | controller.dispose();
43 | timer.cancel();
44 | }
45 |
46 | @override
47 | Widget build(BuildContext context) {
48 | return Container(
49 | height: 226.0,
50 | child: Stack(
51 | alignment: Alignment.bottomCenter,
52 | children: [
53 | PageView(
54 | controller: controller,
55 | onPageChanged: _onPageChanged,
56 | children: _buildItems(),),
57 | _buildIndicator(), // 下面的小点
58 | ]),
59 | );
60 | }
61 |
62 | List _buildItems() { // 排列轮播数组
63 | List items = [];
64 | if (widget.bannerStories.length > 0) {
65 | // 头部添加一个尾部Item,模拟循环
66 | items.add(
67 | _buildItem(widget.bannerStories[widget.bannerStories.length - 1]));
68 | // 正常添加Item
69 | items.addAll(
70 | widget.bannerStories.map((story) => _buildItem(story)).toList(
71 | growable: false));
72 | // 尾部
73 | items.add(
74 | _buildItem(widget.bannerStories[0]));
75 | }
76 | return items;
77 | }
78 |
79 | Widget _buildItem(BannerData story) {
80 | return GestureDetector(
81 | onTap: () { // 按下
82 | if (widget.onTap != null) {
83 | widget.onTap(story);
84 | }
85 | },
86 | child: Stack(
87 | fit: StackFit.expand,
88 | children: [
89 | Image.network(story.imagePath, fit: BoxFit.cover),
90 | _buildItemTitle(story.title), // 内容文字,大意
91 | ],),);
92 | }
93 |
94 | Widget _buildItemTitle(String title) {
95 | return Container(
96 | decoration: BoxDecoration( /// 背景的渐变色
97 | gradient: LinearGradient(
98 | begin: Alignment.bottomCenter,
99 | end: const Alignment(0.0, -0.8),
100 | colors: [const Color(0xa0000000), Colors.transparent],
101 | ),
102 | ),
103 | alignment: Alignment.bottomCenter,
104 | child: Container(
105 | margin: EdgeInsets.symmetric(vertical: 22.0, horizontal: 16.0),
106 | child: Text(
107 | title, style: TextStyle(color: Colors.white, fontSize: 18.0),),),
108 | );
109 | }
110 |
111 | Widget _buildIndicator() {
112 | List indicators = [];
113 | for (int i = 0; i < widget.bannerStories.length; i++) {
114 | indicators.add(Container(
115 | width: 6.0,
116 | height: 6.0,
117 | margin: EdgeInsets.symmetric(horizontal: 1.5, vertical: 10.0),
118 | decoration: BoxDecoration(
119 | shape: BoxShape.circle,
120 | color: i == virtualIndex ? Colors.white : Colors.grey)));
121 | }
122 | return Row(
123 | mainAxisAlignment: MainAxisAlignment.center,
124 | children: indicators);
125 | }
126 |
127 | _onPageChanged(int index) {
128 | realIndex = index;
129 | int count = widget.bannerStories.length;
130 | if (index == 0) {
131 | virtualIndex = count - 1;
132 | controller.jumpToPage(count);
133 | } else if (index == count + 1) {
134 | virtualIndex = 0;
135 | controller.jumpToPage(1);
136 | } else {
137 | virtualIndex = index - 1;
138 | }
139 | setState(() {});
140 | }
141 | }
142 |
143 | typedef void OnTapBannerItem(BannerData story);
--------------------------------------------------------------------------------
/lib/components/list_view_item.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_wanandroid/routers/router_path.dart';
3 | import '../routers/application.dart';
4 | import 'dart:core';
5 |
6 | /// 自定义组件,首页 card 中显示用
7 | class ListViewItem extends StatelessWidget {
8 | final int itemId;
9 | final String itemUrl;
10 | final String itemTitle;
11 | final String itemShareUser;
12 | final String itemNiceDate;
13 |
14 | const ListViewItem({Key key, this.itemId, this.itemUrl, this.itemTitle, this.itemShareUser,this.itemNiceDate})
15 | : super(key: key);
16 |
17 |
18 | @override
19 | Widget build(BuildContext context) {
20 | return Card(
21 | color: Colors.white,
22 | elevation: 4.0,
23 | margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
24 | child: ListTile(
25 | onTap: () {
26 | // _launchURL(itemUrl, context);
27 | Application.router.navigateTo(context, '${RouterPath.webViewPage}?id=${Uri.encodeComponent(itemId.toString())}&title=${Uri.encodeComponent(itemTitle)}&link=${Uri.encodeComponent(itemUrl)}');
28 | },
29 | title: Padding(
30 | child: Text(
31 | itemTitle,
32 | style: TextStyle(color: Colors.black, fontSize: 15.0),
33 | ),
34 | padding: EdgeInsets.only(top: 10.0),
35 | ),
36 | subtitle: Row(
37 | children: [
38 | Padding(
39 | child: Text(itemShareUser,
40 | style: TextStyle(color: Colors.black54, fontSize: 10.0)),
41 | padding: EdgeInsets.only(top: 10.0, bottom: 10.0),
42 | ),
43 | Padding(
44 | child: Text(itemNiceDate,
45 | style: TextStyle(color: Colors.black54, fontSize: 10.0)),
46 | padding: EdgeInsets.only(top: 10.0, bottom: 10.0, left: 10.0),
47 | )
48 | ],
49 | ),
50 | trailing:
51 | Icon(Icons.keyboard_arrow_right, color: Colors.grey, size: 30.0),
52 | ),
53 | );
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/lib/components/navi_list.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | /// 导航文章列表
4 |
5 | class NaviListPage extends StatefulWidget{
6 |
7 | final int id;
8 | final String title;
9 |
10 | NaviListPage(this.id, this.title);
11 | @override
12 | State createState() {
13 | return new NaviListPageState();
14 | }
15 |
16 | }
17 |
18 | class NaviListPageState extends State {
19 | @override
20 | Widget build(BuildContext context) {
21 | return Text("导航文章列表");
22 | }
23 | }
--------------------------------------------------------------------------------
/lib/components/pagination.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_wanandroid/api/Api.dart';
4 | import 'package:flutter_wanandroid/api/common_service.dart';
5 | import 'package:flutter_wanandroid/components/home_banner.dart';
6 | import 'package:flutter_wanandroid/model/banner.dart';
7 | import 'package:url_launcher/url_launcher.dart';
8 |
9 |
10 | // Banner
11 | class Pagination extends StatefulWidget {
12 | @override
13 | State createState() {
14 | return BannerState();
15 | }
16 | }
17 |
18 | class BannerState extends State {
19 | List _bannerList = new List();
20 |
21 | @override
22 | void initState() {
23 | _getBanner();
24 | }
25 |
26 | Future _getBanner() async{
27 | _bannerList.clear();
28 | CommonService().getBanner((BannerModel _bean) {
29 | if (_bean.data.length > 0) {
30 | if(mounted){
31 | setState(() {
32 | _bannerList = _bean.data;
33 | });
34 | }
35 | }
36 | });
37 | }
38 |
39 |
40 | /// 打开本地浏览器
41 | void _launchURL(String url) async {
42 | if (await canLaunch(url)) {
43 | await launch(url);
44 | } else {
45 | throw 'Could not launch $url';
46 | }
47 | }
48 |
49 | @override
50 | Widget build(BuildContext context) {
51 | return Column(
52 | key:Key('__header__'),
53 | //physics: AlwaysScrollableScrollPhysics(),
54 | //padding: EdgeInsets.only(),
55 | children: _pageSelector(context)
56 | );
57 | }
58 |
59 | List _pageSelector(BuildContext context) {
60 | List list = [];
61 | if (_bannerList.length > 0) {
62 | list.add(HomeBanner(_bannerList, (story) {
63 | _launchURL('${story.url}');
64 | }));
65 | }
66 | return list;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/lib/components/project_list.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | /// 项目列表
4 |
5 | class ProjectListPage extends StatefulWidget{
6 |
7 | final int id;
8 | final String title;
9 |
10 | ProjectListPage(this.id, this.title);
11 |
12 | @override
13 | State createState() {
14 | return new ProjectListPageState();
15 | }
16 |
17 | }
18 |
19 | class ProjectListPageState extends State {
20 | @override
21 | Widget build(BuildContext context) {
22 | return Text("项目列表");
23 | }
24 | }
--------------------------------------------------------------------------------
/lib/constant/color_config.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class ColorConfig{
4 | static Color BLUE_200 = Colors.blue[200];
5 | }
--------------------------------------------------------------------------------
/lib/constant/shared_preferences_keys.dart:
--------------------------------------------------------------------------------
1 | //enum DateType {
2 | // Int,
3 | // Double,
4 | // Bool,
5 | // String,
6 | // Dynamic
7 | //}
8 |
9 | //class spKey {
10 | // String name;
11 | // DateType type;
12 | //
13 | // spKey({this.name, this.type});
14 | //}
15 |
16 | class SharedPreferencesKeys {
17 | /// boolean
18 | /// 用于欢迎页面. 只有第一次访问才会显示. 或者手动将这个值设为false
19 | static String showWelcome = 'loginWelcone';
20 | /// json
21 | /// 用于存放搜索页的搜索数据.
22 | /// [{
23 | /// name: 'name'
24 | ///
25 | /// }]
26 | static String searchHistory = 'searchHistory';
27 | static String userName = 'userName';
28 |
29 | static String splash_date = "key_splash_date";
30 | static String splash_image = "key_splash_image";
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/lib/event/event_bus.dart:
--------------------------------------------------------------------------------
1 | import 'package:event_bus/event_bus.dart';
2 |
3 | class ApplicationEvent{
4 | static EventBus event;
5 | }
--------------------------------------------------------------------------------
/lib/event/event_model.dart:
--------------------------------------------------------------------------------
1 | class CollectionEvent{
2 | final String widgetName;
3 | final String router;
4 | final bool isRemove;
5 | // token uid...
6 | CollectionEvent(this.widgetName,this.router,this.isRemove);
7 | }
--------------------------------------------------------------------------------
/lib/event/event_theme.dart:
--------------------------------------------------------------------------------
1 | /// EventBus 消息数据类,用于更新主题颜色
2 | class ThemeEvent {
3 | final int themeColor;
4 | ThemeEvent(this.themeColor);
5 | }
--------------------------------------------------------------------------------
/lib/generated/i18n.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/foundation.dart';
4 | import 'package:flutter/material.dart';
5 |
6 | // ignore_for_file: non_constant_identifier_names
7 | // ignore_for_file: camel_case_types
8 | // ignore_for_file: prefer_single_quotes
9 |
10 | // This file is automatically generated. DO NOT EDIT, all your changes would be lost.
11 | class S implements WidgetsLocalizations {
12 | const S();
13 |
14 | static S current;
15 |
16 | static const GeneratedLocalizationsDelegate delegate =
17 | GeneratedLocalizationsDelegate();
18 |
19 | static S of(BuildContext context) => Localizations.of(context, S);
20 |
21 | @override
22 | TextDirection get textDirection => TextDirection.ltr;
23 |
24 | String get app_title => "app_title";
25 | String get main_title => "My Main Title";
26 | String message_tip(String count) => "You have pushed the button many times: $count";
27 | }
28 |
29 | class $en extends S {
30 | const $en();
31 | }
32 |
33 | class $zh extends S {
34 | const $zh();
35 |
36 | @override
37 | TextDirection get textDirection => TextDirection.ltr;
38 |
39 | @override
40 | String get app_title => "App标题";
41 | @override
42 | String get main_title => "主标题";
43 | @override
44 | String message_tip(String count) => "点击按钮次数: $count";
45 | }
46 |
47 | class GeneratedLocalizationsDelegate extends LocalizationsDelegate {
48 | const GeneratedLocalizationsDelegate();
49 |
50 | List get supportedLocales {
51 | return const [
52 | Locale("en", ""),
53 | Locale("zh", ""),
54 | ];
55 | }
56 |
57 | LocaleListResolutionCallback listResolution({Locale fallback, bool withCountry = true}) {
58 | return (List locales, Iterable supported) {
59 | if (locales == null || locales.isEmpty) {
60 | return fallback ?? supported.first;
61 | } else {
62 | return _resolve(locales.first, fallback, supported, withCountry);
63 | }
64 | };
65 | }
66 |
67 | LocaleResolutionCallback resolution({Locale fallback, bool withCountry = true}) {
68 | return (Locale locale, Iterable supported) {
69 | return _resolve(locale, fallback, supported, withCountry);
70 | };
71 | }
72 |
73 | @override
74 | Future load(Locale locale) {
75 | final String lang = getLang(locale);
76 | if (lang != null) {
77 | switch (lang) {
78 | case "en":
79 | S.current = const $en();
80 | return SynchronousFuture(S.current);
81 | case "zh":
82 | S.current = const $zh();
83 | return SynchronousFuture(S.current);
84 | default:
85 | // NO-OP.
86 | }
87 | }
88 | S.current = const S();
89 | return SynchronousFuture(S.current);
90 | }
91 |
92 | @override
93 | bool isSupported(Locale locale) => _isSupported(locale, true);
94 |
95 | @override
96 | bool shouldReload(GeneratedLocalizationsDelegate old) => false;
97 |
98 | ///
99 | /// Internal method to resolve a locale from a list of locales.
100 | ///
101 | Locale _resolve(Locale locale, Locale fallback, Iterable supported, bool withCountry) {
102 | if (locale == null || !_isSupported(locale, withCountry)) {
103 | return fallback ?? supported.first;
104 | }
105 |
106 | final Locale languageLocale = Locale(locale.languageCode, "");
107 | if (supported.contains(locale)) {
108 | return locale;
109 | } else if (supported.contains(languageLocale)) {
110 | return languageLocale;
111 | } else {
112 | final Locale fallbackLocale = fallback ?? supported.first;
113 | return fallbackLocale;
114 | }
115 | }
116 |
117 | ///
118 | /// Returns true if the specified locale is supported, false otherwise.
119 | ///
120 | bool _isSupported(Locale locale, bool withCountry) {
121 | if (locale != null) {
122 | for (Locale supportedLocale in supportedLocales) {
123 | // Language must always match both locales.
124 | if (supportedLocale.languageCode != locale.languageCode) {
125 | continue;
126 | }
127 |
128 | // If country code matches, return this locale.
129 | if (supportedLocale.countryCode == locale.countryCode) {
130 | return true;
131 | }
132 |
133 | // If no country requirement is requested, check if this locale has no country.
134 | if (true != withCountry && (supportedLocale.countryCode == null || supportedLocale.countryCode.isEmpty)) {
135 | return true;
136 | }
137 | }
138 | }
139 | return false;
140 | }
141 | }
142 |
143 | String getLang(Locale l) => l == null
144 | ? null
145 | : l.countryCode != null && l.countryCode.isEmpty
146 | ? l.languageCode
147 | : l.toString();
148 |
--------------------------------------------------------------------------------
/lib/init/app.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_localizations/flutter_localizations.dart';
4 | import 'package:flutter_wanandroid/generated/i18n.dart';
5 | import 'package:flutter_wanandroid/model/search_history.dart';
6 | import 'package:flutter_wanandroid/model/store.dart';
7 | import 'package:flutter_wanandroid/model/theme.dart';
8 | import 'package:flutter_wanandroid/routers/application.dart';
9 | import 'package:flutter_wanandroid/routers/navigation_service.dart';
10 | import 'package:flutter_wanandroid/routers/router.dart';
11 | import 'package:flutter_wanandroid/utils/bugly.dart';
12 | import 'package:flutter_wanandroid/utils/provider.dart';
13 | import 'package:flutter_wanandroid/utils/push.dart';
14 | import 'package:flutter_wanandroid/api/http.dart';
15 | import 'package:flutter_wanandroid/utils/shared_preferences.dart';
16 | import 'package:flutter_wanandroid/views/page_not_found.dart';
17 | import 'package:flutter_wanandroid/views/splash_page/SplashPage.dart';
18 | import 'package:provider/provider.dart';
19 |
20 | class App{
21 | //运行app
22 | static void run() {
23 | WidgetsFlutterBinding.ensureInitialized();
24 | /// 全局 provider 初始化
25 | SPUtils.init().then((value) => runApp(Store.init(MyApp())));
26 | initApp();
27 |
28 | }
29 |
30 |
31 |
32 | //程序初始化操作
33 | static void initApp() {
34 | // 搜索历史
35 | SearchHistoryList();
36 |
37 | DBProvider().init(true);
38 | Http.init();
39 | XRouter.init();
40 | XPush.init();
41 | Bugly.init();
42 | }
43 | }
44 |
45 |
46 | class MyApp extends StatelessWidget {
47 | // This widget is the root of your application.
48 | @override
49 | Widget build(BuildContext context) {
50 | return Consumer(
51 | builder: (context, appTheme, _) {
52 | return MaterialApp(
53 | title: 'Wan-Android',
54 | navigatorKey: NavigationService.navigatorKey,
55 | theme: appTheme.themeDate,//根据平台选择不同主题
56 | localizationsDelegates: [
57 | S.delegate,//应用程序的翻译回调
58 | // 本地化的代理类
59 | GlobalMaterialLocalizations.delegate,//Material组件的翻译回调
60 | GlobalWidgetsLocalizations.delegate,//普通Widget的翻译回调
61 | ],
62 | supportedLocales: S.delegate.supportedLocales,//支持语系
63 | // title的国际化回调
64 | onGenerateTitle: (context){ return S.of(context).app_title; },
65 | // 闪屏页
66 | home:Scaffold(body: SplashPage()),
67 | // 生成路由的回调函数,当导航的命名路由的时候,会使用这个来生成界面
68 | onGenerateRoute: Application.router.generator,
69 | // 页面找不到显示的 404 页面
70 | onUnknownRoute: (RouteSettings setting) =>
71 | MaterialPageRoute(builder: (context) => PageNotFound()),
72 | );
73 | },
74 | );
75 | }
76 | }
--------------------------------------------------------------------------------
/lib/init/app_init.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter_bugly/flutter_bugly.dart';
5 | import 'package:flutter_wanandroid/init/app.dart';
6 |
7 | /// 应用初始化
8 | class AppInit{
9 | static void run() {
10 | // catchException(() => App.run());
11 | // //Bugly的异常捕获上传
12 | // Bugly.postCatchedException(() => NormalApp.run());
13 |
14 | /// 程序的主入口
15 | FlutterBugly.postCatchedException((){
16 | /// bugly 数据上报
17 | App.run();
18 | });
19 |
20 | }
21 |
22 | /// 异常捕获处理
23 | static void catchException(T callback()) {
24 |
25 | /// 捕获异常的回调
26 | FlutterError.onError = (FlutterErrorDetails details) {
27 | reportErrorAndLog(details);
28 | };
29 | runZoned>(() async {
30 | callback();
31 | },
32 | zoneSpecification: ZoneSpecification(
33 | print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
34 | /// 收集日志
35 | collectLog(parent, zone, line);
36 | },
37 | ),
38 | /// 未捕获的异常的回调
39 | onError: (Object obj, StackTrace stack) {
40 | var details = makeDetails(obj, stack);
41 | reportErrorAndLog(details);
42 | },
43 | );
44 |
45 | /// 重写异常页面
46 | ErrorWidget.builder = (FlutterErrorDetails flutterErrorDetails) {
47 | print(flutterErrorDetails.toString());
48 | return Scaffold(
49 | body: Center(
50 | child: Text("出了点问题,我们马上修复~"),
51 | ));
52 | };
53 | }
54 |
55 |
56 | /// 日志拦截, 收集日志
57 | static void collectLog(ZoneDelegate parent, Zone zone, String line) {
58 | parent.print(zone, "日志拦截: $line");
59 | }
60 |
61 | /// 上报错误和日志逻辑
62 | static void reportErrorAndLog(FlutterErrorDetails details) {
63 | print('上报错误和日志逻辑: $details');
64 | print(details);
65 | }
66 |
67 | /// 构建错误信息
68 | static FlutterErrorDetails makeDetails(Object obj, StackTrace stack) {
69 | return FlutterErrorDetails(stack: stack);
70 | }
71 |
72 |
73 | }
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_wanandroid/init/app_init.dart';
2 |
3 | /// 程序的主入口
4 | void main() => AppInit.run();
5 |
--------------------------------------------------------------------------------
/lib/main_page.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter/rendering.dart';
4 | import 'package:flutter_screenutil/flutter_screenutil.dart';
5 | import 'package:flutter_wanandroid/routers/navigation_service.dart';
6 | import 'package:flutter_wanandroid/utils/shared_preferences.dart';
7 | import 'package:flutter_wanandroid/views/cat_page/cat_page.dart';
8 | import 'package:flutter_wanandroid/views/collection_page/collection_page.dart';
9 | import 'package:flutter_wanandroid/views/home_page/home_page.dart';
10 | import 'package:flutter_wanandroid/views/mine_page/mine_page.dart';
11 | import 'package:flutter_wanandroid/views/photo_page/photo_page.dart';
12 |
13 | import 'package:flutter_wanandroid/model/search_history.dart';
14 |
15 |
16 | const int ThemeColor = 0xFFC91B3A;
17 |
18 | class MainPage extends StatefulWidget {
19 | @override
20 | State createState() {
21 | return _MyHomePageState();
22 | }
23 | }
24 |
25 | class _MyHomePageState extends State with SingleTickerProviderStateMixin {
26 |
27 |
28 | TabController controller;
29 | SearchHistoryList searchHistoryList;
30 |
31 | String data = '无';
32 | String appBarTitle = tabData[0]['text'];
33 | static List tabData = [
34 | {'text': '首页', 'icon': new Icon(Icons.home)},
35 | {'text': '猫耳', 'icon': new Icon(Icons.category)},
36 | {'text': '收藏', 'icon': new Icon(Icons.favorite)},
37 | {'text': '图库', 'icon': new Icon(Icons.photo)},
38 | {'text': '我的', 'icon': new Icon(Icons.person)}
39 | ];
40 |
41 | List myTabs = [];
42 |
43 | @override
44 | void initState() {
45 | super.initState();
46 |
47 | controller = new TabController(
48 | initialIndex: 0, vsync: this, length: 5); // 这里的length 决定有多少个底导 submenus
49 | for (int i = 0; i < tabData.length; i++) {
50 | myTabs.add(new Tab(text: tabData[i]['text'], icon: tabData[i]['icon']));
51 | }
52 |
53 | /// 滑动监听
54 | controller.addListener(() {
55 | if (controller.indexIsChanging) {
56 | _onTabChange();
57 | }
58 | });
59 | }
60 |
61 | @override
62 | void dispose() {
63 | controller.dispose();
64 | super.dispose();
65 | }
66 |
67 |
68 |
69 |
70 | @override
71 | Widget build(BuildContext context) {
72 | //设置适配尺寸 (填入设计稿中设备的屏幕尺寸) 此处假如设计稿是按iPhone6的尺寸设计的(iPhone6 750*1334)
73 | //ScreenUtil.init(context, width: 750, height: 1334, allowFontScaling: false);
74 | ScreenUtil.init(context);
75 | /// 保存全局context
76 | NavigationService.mContext = context;
77 | return new Scaffold(
78 | body: new TabBarView(controller: controller, children: [
79 | new HomePage(),
80 | new CatPage(),
81 | new CollectionPage(),
82 | new PhotoPage(),
83 | new MinePage(),
84 | ]),
85 | bottomNavigationBar: Material(
86 | color: const Color(0xFFF0EEEF), //底部导航栏主题颜色
87 | child: SafeArea(
88 | child: Container(
89 | height: 65.0,
90 | /// 渐变效果
91 | decoration: BoxDecoration(
92 | color: const Color(0xFFF0F0F0),
93 | boxShadow: [
94 | BoxShadow(
95 | color: const Color(0xFFd0d0d0),
96 | blurRadius: 3.0,
97 | spreadRadius: 2.0,
98 | offset: Offset(-1.0, -1.0),
99 | ),
100 | ],
101 | ),
102 | child: TabBar(
103 | controller: controller,
104 | indicatorColor: Theme.of(context).primaryColor,
105 | //tab标签的下划线颜色
106 | // labelColor: const Color(0xFF000000),
107 | indicatorWeight: 3.0,
108 | labelColor: Theme.of(context).primaryColor,
109 | unselectedLabelColor: const Color(0xFF8E8E8E),
110 | tabs: myTabs),
111 | ),
112 | ),
113 | ),
114 | );
115 |
116 | }
117 |
118 | /// 底部tab点击
119 | void _onTabChange() {
120 | if (this.mounted) {
121 | this.setState(() {
122 | appBarTitle = tabData[controller.index]['text'];
123 | });
124 | }
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/lib/model/banner.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert' show json;
2 |
3 | class BannerModel {
4 |
5 | int errorCode;
6 | String errorMsg;
7 | List data;
8 |
9 | BannerModel.fromParams({this.errorCode, this.errorMsg, this.data});
10 |
11 | factory BannerModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new BannerModel.fromJson(json.decode(jsonStr)) : new BannerModel.fromJson(jsonStr);
12 |
13 | BannerModel.fromJson(jsonRes) {
14 | errorCode = jsonRes['errorCode'];
15 | errorMsg = jsonRes['errorMsg'];
16 | data = jsonRes['data'] == null ? null : [];
17 |
18 | for (var dataItem in data == null ? [] : jsonRes['data']){
19 | data.add(dataItem == null ? null : new BannerData.fromJson(dataItem));
20 | }
21 | }
22 |
23 | @override
24 | String toString() {
25 | return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
26 | }
27 | }
28 |
29 | class BannerData {
30 |
31 | int id;
32 | int isVisible;
33 | int order;
34 | int type;
35 | String desc;
36 | String imagePath;
37 | String title;
38 | String url;
39 |
40 | BannerData.fromParams({this.id, this.isVisible, this.order, this.type, this.desc, this.imagePath, this.title, this.url});
41 |
42 | BannerData.fromJson(jsonRes) {
43 | id = jsonRes['id'];
44 | isVisible = jsonRes['isVisible'];
45 | order = jsonRes['order'];
46 | type = jsonRes['type'];
47 | desc = jsonRes['desc'];
48 | imagePath = jsonRes['imagePath'];
49 | title = jsonRes['title'];
50 | url = jsonRes['url'];
51 | }
52 |
53 | @override
54 | String toString() {
55 | return '{"id": $id,"isVisible": $isVisible,"order": $order,"type": $type,"desc": ${desc != null?'${json.encode(desc)}':'null'},"imagePath": ${imagePath != null?'${json.encode(imagePath)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'},"url": ${url != null?'${json.encode(url)}':'null'}}';
56 | }
57 | }
58 |
59 |
--------------------------------------------------------------------------------
/lib/model/cat.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'dart:convert' show json;
3 |
4 | import 'package:flutter_wanandroid/model/article.dart';
5 |
6 | class CatModel{
7 |
8 | int errorCode;
9 | String errorMsg;
10 | List data;
11 |
12 | CatModel.fromParams({this.errorCode, this.errorMsg, this.data});
13 | factory CatModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new CatModel.fromJson(json.decode(jsonStr)) : new CatModel.fromJson(jsonStr);
14 |
15 | CatModel.fromJson(jsonRes) {
16 | errorCode = jsonRes['errorCode'];
17 | errorMsg = jsonRes['errorMsg'];
18 | data = jsonRes['data'] == null ? null :[];
19 |
20 | /// 项目和体系的集合
21 | for (var dataItem in data == null ? [] : jsonRes['data']){
22 | data.add(dataItem == null ? null : new Cat.fromJson(dataItem));
23 | }
24 |
25 | }
26 | @override
27 | String toString() {
28 | return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
29 | }
30 | }
31 |
32 | class Cat {
33 |
34 | int id;
35 | /// 导航的 id
36 | int cid;
37 | int courseId;
38 | int order;
39 | int superChapterId;
40 | int parentChapterId;
41 | int visible;
42 | bool userControlSetTop;
43 | String name;
44 | String title;
45 | String link;
46 | List cats;
47 |
48 |
49 | Cat.fromParams({this.id, this.cid, this.courseId, this.order, this.superChapterId, this.parentChapterId, this.visible, this.userControlSetTop, this.name, this.title, this.link});
50 | Cat.fromJson(jsonRes) {
51 | superChapterId = jsonRes['superChapterId'] == null ? -1 : jsonRes['superChapterId'];
52 | parentChapterId = jsonRes['parentChapterId'] == null ? -1 : jsonRes['parentChapterId'];
53 | order = jsonRes['order'];
54 | id = jsonRes['id'];
55 | cid = jsonRes['cid'] == null ? -1 : jsonRes['cid'];
56 | courseId = jsonRes['courseId'] == null ? -1 : jsonRes['courseId'];
57 | userControlSetTop = jsonRes['userControlSetTop'];
58 | visible = jsonRes['visible'];
59 | name = jsonRes['name'] == null ? null : jsonRes['name'];
60 | link = jsonRes['link'] == null ? null : jsonRes['link'];
61 | title = jsonRes['title'] == null ? null : jsonRes['title'];
62 | cats = jsonRes['children'] == null ? null :[];
63 |
64 |
65 | /// 获取项目、体系下的集合
66 | for (var dataItem in cats == null ? [] : jsonRes['children']){
67 | cats.add(dataItem == null ? null : new Cat.fromJson(dataItem));
68 | }
69 |
70 | }
71 |
72 | String toString() {
73 | return '{"superChapterId": $superChapterId,"parentChapterId": $parentChapterId,"order": $order,'
74 | '"id": $id,"courseId": ${courseId != null?'${json.encode(courseId)}':'-1'},"userControlSetTop": ${userControlSetTop != null?'${json.encode(userControlSetTop)}':'false'},'
75 | '"visible": ${visible != null?'${json.encode(visible)}':'0'},"link": ${link != null?'${json.encode(link)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'},'
76 | '"name": ${name != null?'${json.encode(name)}':'null'},"cats": $cats}';
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/lib/model/coin.dart:
--------------------------------------------------------------------------------
1 | class Coin {
2 | String errorMsg;
3 | int errorCode;
4 | DataBean data;
5 |
6 | Coin({this.errorMsg, this.errorCode, this.data});
7 |
8 | Coin.fromJson(Map json) {
9 | this.errorMsg = json['errorMsg'];
10 | this.errorCode = json['errorCode'];
11 | this.data = json['data'] != null ? DataBean.fromJson(json['data']) : null;
12 | }
13 |
14 | Map toJson() {
15 | final Map data = new Map();
16 | data['errorMsg'] = this.errorMsg;
17 | data['errorCode'] = this.errorCode;
18 | if (this.data != null) {
19 | data['data'] = this.data.toJson();
20 | }
21 | return data;
22 | }
23 |
24 | }
25 |
26 | class DataBean {
27 | bool over;
28 | int curPage;
29 | int offset;
30 | int pageCount;
31 | int size;
32 | int total;
33 | List datas;
34 |
35 | DataBean({this.over, this.curPage, this.offset, this.pageCount, this.size, this.total, this.datas});
36 |
37 | DataBean.fromJson(Map json) {
38 | this.over = json['over'];
39 | this.curPage = json['curPage'];
40 | this.offset = json['offset'];
41 | this.pageCount = json['pageCount'];
42 | this.size = json['size'];
43 | this.total = json['total'];
44 | this.datas = (json['datas'] as List)!=null?(json['datas'] as List).map((i) => CoinInfo.fromJson(i)).toList():null;
45 | }
46 |
47 | Map toJson() {
48 | final Map data = new Map();
49 | data['over'] = this.over;
50 | data['curPage'] = this.curPage;
51 | data['offset'] = this.offset;
52 | data['pageCount'] = this.pageCount;
53 | data['size'] = this.size;
54 | data['total'] = this.total;
55 | data['datas'] = this.datas != null?this.datas.map((i) => i.toJson()).toList():null;
56 | return data;
57 | }
58 | }
59 |
60 | class CoinInfo {
61 | String username;
62 | int coinCount;
63 | int level;
64 | String rank;
65 | int userId;
66 |
67 | CoinInfo({this.username, this.coinCount, this.level, this.rank, this.userId});
68 |
69 | CoinInfo.fromJson(Map json) {
70 | this.username = json['username'];
71 | this.coinCount = json['coinCount'];
72 | this.level = json['level'];
73 | this.rank = json['rank'];
74 | this.userId = json['userId'];
75 | }
76 |
77 | Map toJson() {
78 | final Map data = new Map();
79 | data['username'] = this.username;
80 | data['coinCount'] = this.coinCount;
81 | data['level'] = this.level;
82 | data['rank'] = this.rank;
83 | data['userId'] = this.userId;
84 | return data;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/lib/model/collect.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter_wanandroid/utils/sql.dart';
4 |
5 |
6 | abstract class CollectionInterface {
7 | String get id;
8 | String get title;
9 | String get link;
10 | }
11 |
12 | class Collection implements CollectionInterface {
13 | String id;
14 | String title;
15 | String link;
16 |
17 | Collection({this.id, this.title, this.link});
18 |
19 | factory Collection.fromJSON(Map json){
20 | return Collection(id: json['id'],title: json['title'],link: json['link']);
21 | }
22 |
23 | Object toMap() {
24 | return {'id': id, 'title': title, 'link':link};
25 | }
26 |
27 | }
28 |
29 | class CollectionControlModel {
30 | final String table = 'collection';
31 | Sql sql;
32 |
33 | CollectionControlModel() {
34 | sql = Sql.setTable(table);
35 | }
36 |
37 | // 获取所有的收藏
38 |
39 | // 插入新收藏
40 | Future insert(Collection collection) {
41 | var result =
42 | sql.insert({'id': collection.id, 'title': collection.title, 'link':collection.link});
43 | return result;
44 | }
45 |
46 | // 获取全部的收藏
47 | Future> getAllCollection() async {
48 | List list = await sql.getByCondition();
49 | List resultList = [];
50 | list.forEach((item){
51 | print(item);
52 | resultList.add(Collection.fromJSON(item));
53 | });
54 | return resultList;
55 | }
56 |
57 | // 通过 ID 获取router
58 | Future getRouterById(int id) async {
59 | List list = await sql.getByCondition(conditions: {'id': id});
60 | return list;
61 | }
62 |
63 | // 删除
64 | Future deleteById(int id) async{
65 | return await sql.delete(id.toString(),'id');
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/lib/model/constant.dart:
--------------------------------------------------------------------------------
1 | /// 常量类
2 | class Constant{
3 | static final String heroPhotoDetail = "hero_photo_detail";
4 | }
--------------------------------------------------------------------------------
/lib/model/provider/state_provider.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | /// 跨 widget 状态管理封装
4 | class IProvider extends InheritedWidget {
5 | // 数据
6 | final T data;
7 | // 方法
8 | final Function() doSomeThing;
9 |
10 | IProvider({Key key, Widget child, this.data, this.doSomeThing})
11 | : super(key: key, child: child);
12 |
13 | @override
14 | bool updateShouldNotify(IProvider oldWidget) {
15 | return data != oldWidget.data;
16 | }
17 | static IProvider of(BuildContext context) {
18 | return context.dependOnInheritedWidgetOfExactType>();
19 | }
20 | }
--------------------------------------------------------------------------------
/lib/model/search_history.dart:
--------------------------------------------------------------------------------
1 | /// target: 搜索WidgetDemo中的历史记录model
2 | import 'dart:convert';
3 |
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter_wanandroid/utils/shared_preferences.dart';
6 |
7 | import '../constant/shared_preferences_keys.dart';
8 |
9 |
10 | class SearchHistory {
11 | final String name;
12 | final String targetRouter;
13 |
14 | SearchHistory({@required this.name, @required this.targetRouter});
15 | }
16 |
17 | class SearchHistoryList {
18 | static SearchHistoryList _instance;
19 | static List _searchHistoryList = [];
20 |
21 | factory SearchHistoryList() {
22 | if (_instance == null) {
23 | print(new ArgumentError(['SearchHistoryList need instantiatied SpUtil at first timte ']));
24 | }
25 | return _getInstance();
26 | }
27 |
28 | static SearchHistoryList _getInstance() {
29 | if (_instance == null) {
30 | String json = SPUtils.get(SharedPreferencesKeys.searchHistory);
31 | print("SearchHistoryList json---->"+json.toString());
32 | _instance = new SearchHistoryList.fromJSON(json);
33 | }
34 | return _instance;
35 | }
36 |
37 |
38 | // 存放的最大数量
39 | int _count = 10;
40 |
41 | SearchHistoryList.fromJSON(String jsonData) {
42 | _searchHistoryList = [];
43 | if (jsonData == null) {
44 | return;
45 | }
46 | List jsonList = json.decode(jsonData);
47 | jsonList.forEach((value) {
48 | _searchHistoryList.add(SearchHistory(
49 | name: value['name'], targetRouter: value['targetRouter']));
50 | });
51 | }
52 |
53 | List getList() {
54 | return _searchHistoryList;
55 | }
56 |
57 | clear() {
58 | SPUtils.remove(SharedPreferencesKeys.searchHistory);
59 | _searchHistoryList = [];
60 | }
61 |
62 | save() {
63 | SPUtils.putString(SharedPreferencesKeys.searchHistory, this.toJson());
64 | }
65 |
66 | add(SearchHistory item) {
67 | print("_searchHistoryList> ${_searchHistoryList.length}");
68 | for (SearchHistory value in _searchHistoryList) {
69 | if (value.name == item.name) {
70 | return;
71 | }
72 | }
73 | if (_searchHistoryList.length > _count) {
74 | _searchHistoryList.removeAt(0);
75 | }
76 | _searchHistoryList.add(item);
77 | save();
78 | }
79 |
80 | toJson() {
81 | List