├── README.md
├── flutter_demo
├── .gitignore
├── .metadata
├── README.md
├── android
│ ├── app
│ │ ├── build.gradle
│ │ └── src
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── huan
│ │ │ │ └── io
│ │ │ │ └── flutterdemo
│ │ │ │ └── MainActivity.java
│ │ │ └── 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
│ │ │ └── values
│ │ │ └── styles.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ ├── key.properties
│ └── settings.gradle
├── images
│ ├── fiction_1.png
│ ├── fiction_2.png
│ ├── fiction_3.png
│ ├── fiction_4.png
│ ├── fiction_author.png
│ ├── fiction_header_icon.png
│ ├── icon_add_comment.png
│ ├── icon_back.png
│ ├── icon_back_pressed.png
│ ├── icon_coin.png
│ ├── icon_coin_bg.png
│ ├── icon_function_search.png
│ ├── icon_history_time.png
│ ├── icon_logo.png
│ ├── icon_main_tab_fiction_normal.png
│ ├── icon_main_tab_fiction_selected.png
│ ├── icon_main_tab_micro_normal.png
│ ├── icon_main_tab_micro_select.png
│ ├── icon_main_tab_news_normal.png
│ ├── icon_main_tab_news_selected.png
│ ├── icon_main_tab_person_normal.png
│ ├── icon_main_tab_person_selected.png
│ ├── icon_replace.png
│ ├── icon_right.png
│ ├── icon_share.png
│ ├── mine_apprentice_icon.png
│ ├── mine_cash_icon.png
│ ├── mine_code_icon.png
│ ├── mine_guess_icon.png
│ ├── mine_message_icon.png
│ ├── mine_read_icon.png
│ ├── mine_riddle_icon.png
│ ├── mine_wallet_icon.png
│ ├── mine_withdraw_icon.png
│ ├── personal_ava_default.png
│ ├── personal_heart_bg.png
│ └── setting.png
├── ios
│ ├── Flutter
│ │ ├── AppFrameworkInfo.plist
│ │ ├── Debug.xcconfig
│ │ └── Release.xcconfig
│ ├── Runner.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ └── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ ├── Runner.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── Runner
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.m
│ │ ├── 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
│ │ └── main.m
├── lib
│ ├── FictionDetailPage.dart
│ ├── FictionManFeatured.dart
│ ├── ImagePickerPage.dart
│ ├── NewsDetailPageView.dart
│ ├── PersonalPage.dart
│ ├── ScannerPage.dart
│ ├── SearchPage.dart
│ ├── bean
│ │ ├── BannerInfoResponse.dart
│ │ ├── ChannelResponse.dart
│ │ ├── FictionDetailResponse.dart
│ │ ├── FictionHomeInfoResponse.dart
│ │ ├── HotSearchResponse.dart
│ │ ├── NewsDetailResponse.dart
│ │ ├── NewsResData.dart
│ │ └── RelativeInfoResponse.dart
│ ├── channelView.dart
│ ├── controller
│ │ └── HttpController.dart
│ ├── fiction
│ │ └── mainFiction.dart
│ ├── homePage.dart
│ ├── main.dart
│ ├── news_detail_page.dart
│ ├── utils
│ │ ├── SpUtil.dart
│ │ └── functions.dart
│ ├── videoListPage.dart
│ └── view
│ │ ├── NewDetailWebview.dart
│ │ ├── SearchView.dart
│ │ └── StaticRatingBar.dart
├── pubspec.yaml
└── test
│ └── widget_test.dart
└── images
├── 1550481959(1).jpg
├── 1550481996(1).jpg
├── 1550482021(1).jpg
├── 1550482063(1).jpg
├── 1550482086(1).jpg
├── 1550482109(1).jpg
├── 1553766601(1).jpg
└── 1553766652(1).jpg
/README.md:
--------------------------------------------------------------------------------
1 | # Flutter_bwkd
2 | 本项目主要是用Flutter去实现“百万看点”app
3 |
4 | 自flutter发布正式版到现在已经过去两个多月了,当我看到它正式发布的消息时,简直就像是个拿到了玩具的小学鸡一样兴奋,迫不及待的想去玩玩。正好最近项目迭代完成比较闲游遍了各大论坛,最后决定试做一下资讯类的应用,选择了“百万看点”这个app试手,事不宜迟,马上开干。
5 |
6 | 预览:看看用flutter写的百万看点的界面,鉴于工程问题,我们只做主要的界面。
7 |
8 | .jpg)
9 | .jpg)
10 | .jpg)
11 | .jpg)
12 | .jpg)
13 | .jpg)
14 |
15 | 用到的开源库:
16 |
17 | cupertino_icons: ^0.1.2
18 |
19 | english_words: ^3.1.0
20 |
21 | dio: ^1.0.13
22 |
23 | webview_flutter: ^0.1.2
24 |
25 | flutter_webview_plugin: ^0.3.0+2
26 |
27 | chewie: ^0.8.0
28 |
29 | flutter_swiper: ^1.1.4
30 |
31 | pointycastle: ^1.0.0
32 |
33 | APK下载:
34 | 链接:https://pan.baidu.com/s/1OZQRT29eZWxbFmXl3ce50Q
35 | 提取码:2osd
36 |
37 | 心得体会:
38 |
39 | 可能一开始上手的话有点懵,但是玩过之后就是酸爽,谁用谁知道。有一点诟病就是嵌套太深了,所以一定要理清思路,尽量做到整洁,我这个项目其实也做得不好,大家以学习的态度去学就好了,正好可以看看哪些地方值得完善修改。
40 |
41 | 个人觉得Flutter既然都出来了,学客户端的同学还是有必要去学习研究一下的,或许flutter会成为下一代客户端的主流呢,谁也说不好,提前准备就好。
42 |
43 | 项目中关于网络的封装不是很好,后面完善再更新。
44 |
45 |
46 | 2019-03-28
47 | 新增了搜索页面,可保存删除搜索历史和获取当前热门搜索
48 |
49 | 增加的插件有:
50 |
51 | shared_preferences: ^0.5.1+2
52 |
53 | synchronized: ^2.1.0
54 |
55 | .jpg)
56 | .jpg)
57 |
58 |
59 | 说明:
60 |
61 | 本项目只做的百万看点的一些主要界面,鉴于百万看点api对用户信息的加密做得太好,还需要一点时间去研究,所以登录验证的相关信息就没做了。
62 | api 来自网络 ,【百万看点】是一款资讯类应用的app,非官方版本,仅作学习交流之用,数据来源于百万看点,数据接口均属于非正常渠道获取,请勿用于商业用途,一切解释权归百万看点官方所有。
63 |
--------------------------------------------------------------------------------
/flutter_demo/.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 |
--------------------------------------------------------------------------------
/flutter_demo/.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: 5391447fae6209bb21a89e6a5a6583cac1af9b4b
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/flutter_demo/README.md:
--------------------------------------------------------------------------------
1 | # flutter_demo
2 |
3 | A new Flutter application.
4 |
5 | ## Getting Started
6 |
7 | This project is a starting point for a Flutter application.
8 |
9 | A few resources to get you started if this is your first Flutter project:
10 |
11 | - [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab)
12 | - [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook)
13 |
14 | For help getting started with Flutter, view our
15 | [online documentation](https://flutter.io/docs), which offers tutorials,
16 | samples, guidance on mobile development, and a full API reference.
17 |
--------------------------------------------------------------------------------
/flutter_demo/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 GradleException("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 = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
26 |
27 | def keystorePropertiesFile = rootProject.file("key.properties")
28 | def keystoreProperties = new Properties()
29 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
30 |
31 | android {
32 | compileSdkVersion 27
33 |
34 | lintOptions {
35 | disable 'InvalidPackage'
36 | }
37 |
38 | defaultConfig {
39 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
40 | applicationId "com.huan.io.flutterdemo"
41 | minSdkVersion 16
42 | targetSdkVersion 27
43 | versionCode flutterVersionCode.toInteger()
44 | versionName flutterVersionName
45 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
46 | }
47 |
48 | signingConfigs {
49 | release {
50 | keyAlias keystoreProperties['keyAlias']
51 | keyPassword keystoreProperties['keyPassword']
52 | storeFile file(keystoreProperties['storeFile'])
53 | storePassword keystoreProperties['storePassword']
54 | }
55 | }
56 |
57 | buildTypes {
58 | release {
59 | // TODO: Add your own signing config for the release build.
60 | // Signing with the debug keys for now, so `flutter run --release` works.
61 | signingConfig signingConfigs.release
62 | }
63 | }
64 | }
65 |
66 | flutter {
67 | source '../..'
68 | }
69 |
70 | dependencies {
71 | testImplementation 'junit:junit:4.12'
72 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
73 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
74 | }
75 |
--------------------------------------------------------------------------------
/flutter_demo/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
10 |
15 |
19 |
26 |
30 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/flutter_demo/android/app/src/main/java/com/huan/io/flutterdemo/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.huan.io.flutterdemo;
2 |
3 | import android.os.Build;
4 | import android.os.Bundle;
5 | import io.flutter.app.FlutterActivity;
6 | import io.flutter.plugins.GeneratedPluginRegistrant;
7 |
8 | public class MainActivity extends FlutterActivity {
9 | @Override
10 | protected void onCreate(Bundle savedInstanceState) {
11 | super.onCreate(savedInstanceState);
12 | //fultter 默认的状态栏是半透明的,所以要判断5.0以上后要设置成透明才能让标题栏颜色和状态栏颜色一致
13 | if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP)
14 | {//API>21,设置状态栏颜色透明
15 | getWindow().setStatusBarColor(0);
16 | }
17 | GeneratedPluginRegistrant.registerWith(this);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/flutter_demo/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/flutter_demo/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter_demo/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter_demo/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter_demo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter_demo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter_demo/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/flutter_demo/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | /* google()
4 | jcenter()*/
5 | maven { url 'https://maven.aliyun.com/repository/google' }
6 | maven { url 'https://maven.aliyun.com/repository/jcenter' }
7 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
8 | }
9 |
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:3.2.1'
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | /* google()
18 | jcenter()*/
19 | maven { url 'https://maven.aliyun.com/repository/google' }
20 | maven { url 'https://maven.aliyun.com/repository/jcenter' }
21 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
22 | }
23 | }
24 |
25 | rootProject.buildDir = '../build'
26 | subprojects {
27 | project.buildDir = "${rootProject.buildDir}/${project.name}"
28 | }
29 | subprojects {
30 | project.evaluationDependsOn(':app')
31 | }
32 |
33 | task clean(type: Delete) {
34 | delete rootProject.buildDir
35 | }
36 |
--------------------------------------------------------------------------------
/flutter_demo/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 |
--------------------------------------------------------------------------------
/flutter_demo/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.10.2-all.zip
7 |
--------------------------------------------------------------------------------
/flutter_demo/android/key.properties:
--------------------------------------------------------------------------------
1 | storePassword=toutiao601
2 | keyPassword=123456
3 | keyAlias=toutiao
4 | storeFile=C:/Users/Administrator/Desktop/commonkey/toutiao.keystore
5 | flutter
--------------------------------------------------------------------------------
/flutter_demo/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 |
--------------------------------------------------------------------------------
/flutter_demo/images/fiction_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/fiction_1.png
--------------------------------------------------------------------------------
/flutter_demo/images/fiction_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/fiction_2.png
--------------------------------------------------------------------------------
/flutter_demo/images/fiction_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/fiction_3.png
--------------------------------------------------------------------------------
/flutter_demo/images/fiction_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/fiction_4.png
--------------------------------------------------------------------------------
/flutter_demo/images/fiction_author.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/fiction_author.png
--------------------------------------------------------------------------------
/flutter_demo/images/fiction_header_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/fiction_header_icon.png
--------------------------------------------------------------------------------
/flutter_demo/images/icon_add_comment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/icon_add_comment.png
--------------------------------------------------------------------------------
/flutter_demo/images/icon_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/icon_back.png
--------------------------------------------------------------------------------
/flutter_demo/images/icon_back_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/icon_back_pressed.png
--------------------------------------------------------------------------------
/flutter_demo/images/icon_coin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/icon_coin.png
--------------------------------------------------------------------------------
/flutter_demo/images/icon_coin_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/icon_coin_bg.png
--------------------------------------------------------------------------------
/flutter_demo/images/icon_function_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/icon_function_search.png
--------------------------------------------------------------------------------
/flutter_demo/images/icon_history_time.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/icon_history_time.png
--------------------------------------------------------------------------------
/flutter_demo/images/icon_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/icon_logo.png
--------------------------------------------------------------------------------
/flutter_demo/images/icon_main_tab_fiction_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/icon_main_tab_fiction_normal.png
--------------------------------------------------------------------------------
/flutter_demo/images/icon_main_tab_fiction_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/icon_main_tab_fiction_selected.png
--------------------------------------------------------------------------------
/flutter_demo/images/icon_main_tab_micro_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/icon_main_tab_micro_normal.png
--------------------------------------------------------------------------------
/flutter_demo/images/icon_main_tab_micro_select.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/icon_main_tab_micro_select.png
--------------------------------------------------------------------------------
/flutter_demo/images/icon_main_tab_news_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/icon_main_tab_news_normal.png
--------------------------------------------------------------------------------
/flutter_demo/images/icon_main_tab_news_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/icon_main_tab_news_selected.png
--------------------------------------------------------------------------------
/flutter_demo/images/icon_main_tab_person_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/icon_main_tab_person_normal.png
--------------------------------------------------------------------------------
/flutter_demo/images/icon_main_tab_person_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/icon_main_tab_person_selected.png
--------------------------------------------------------------------------------
/flutter_demo/images/icon_replace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/icon_replace.png
--------------------------------------------------------------------------------
/flutter_demo/images/icon_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/icon_right.png
--------------------------------------------------------------------------------
/flutter_demo/images/icon_share.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/icon_share.png
--------------------------------------------------------------------------------
/flutter_demo/images/mine_apprentice_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/mine_apprentice_icon.png
--------------------------------------------------------------------------------
/flutter_demo/images/mine_cash_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/mine_cash_icon.png
--------------------------------------------------------------------------------
/flutter_demo/images/mine_code_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/mine_code_icon.png
--------------------------------------------------------------------------------
/flutter_demo/images/mine_guess_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/mine_guess_icon.png
--------------------------------------------------------------------------------
/flutter_demo/images/mine_message_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/mine_message_icon.png
--------------------------------------------------------------------------------
/flutter_demo/images/mine_read_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/mine_read_icon.png
--------------------------------------------------------------------------------
/flutter_demo/images/mine_riddle_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/mine_riddle_icon.png
--------------------------------------------------------------------------------
/flutter_demo/images/mine_wallet_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/mine_wallet_icon.png
--------------------------------------------------------------------------------
/flutter_demo/images/mine_withdraw_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/mine_withdraw_icon.png
--------------------------------------------------------------------------------
/flutter_demo/images/personal_ava_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/personal_ava_default.png
--------------------------------------------------------------------------------
/flutter_demo/images/personal_heart_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/personal_heart_bg.png
--------------------------------------------------------------------------------
/flutter_demo/images/setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/images/setting.png
--------------------------------------------------------------------------------
/flutter_demo/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 |
--------------------------------------------------------------------------------
/flutter_demo/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/flutter_demo/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/flutter_demo/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 |
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : FlutterAppDelegate
5 |
6 | @end
7 |
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/AppDelegate.m:
--------------------------------------------------------------------------------
1 | #include "AppDelegate.h"
2 | #include "GeneratedPluginRegistrant.h"
3 |
4 | @implementation AppDelegate
5 |
6 | - (BOOL)application:(UIApplication *)application
7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
8 | [GeneratedPluginRegistrant registerWithRegistry:self];
9 | // Override point for customization after application launch.
10 | return [super application:application didFinishLaunchingWithOptions:launchOptions];
11 | }
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/flutter_demo/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 |
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/flutter_demo/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 |
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HWHUAN/Flutter_bwkd/20a4caa3ebca8e69d7b07d63a6b329229102fb2b/flutter_demo/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/flutter_demo/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.
--------------------------------------------------------------------------------
/flutter_demo/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 |
--------------------------------------------------------------------------------
/flutter_demo/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 |
--------------------------------------------------------------------------------
/flutter_demo/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_demo
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 |
--------------------------------------------------------------------------------
/flutter_demo/ios/Runner/main.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char* argv[]) {
6 | @autoreleasepool {
7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/flutter_demo/lib/FictionDetailPage.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'controller/HttpController.dart';
3 | import 'bean/FictionDetailResponse.dart';
4 | import 'view/StaticRatingBar.dart';
5 |
6 | class FictionDetailPage extends StatefulWidget{
7 | final int fictionId;
8 |
9 | FictionDetailPage({this.fictionId});
10 |
11 | @override
12 | State createState() {
13 | // TODO: implement createState
14 | return new FictionDetailPageState();
15 | }
16 |
17 | }
18 |
19 | class FictionDetailPageState extends State{
20 | HttpController mHttpController;
21 | @override
22 | void initState() {
23 | // TODO: implement initState
24 | super.initState();
25 | assert(widget.fictionId!=null);
26 | mHttpController=new HttpController();
27 |
28 | }
29 |
30 | @override
31 | Widget build(BuildContext context) {
32 | // TODO: implement build
33 | return Theme(
34 | data: ThemeData(
35 | primaryColor: Color(0xFFF5F5F5)
36 | ),
37 | child: Scaffold(
38 | body: Stack(
39 | children: [
40 | Positioned(
41 | top: 0.0,
42 | left: 0.0,
43 | child: Container(
44 | height: MediaQuery.of(context).padding.top,
45 | width: MediaQuery.of(context).size.width,
46 | )
47 | ),
48 | Positioned(
49 | left: 0.0,
50 | top: MediaQuery.of(context).padding.top,
51 | width: MediaQuery.of(context).size.width,
52 | height: 45.0,
53 | child: Container(
54 | color: Color(0xFFF5F5F5),
55 | padding: EdgeInsets.all(10.0),
56 | child: Row(
57 | crossAxisAlignment: CrossAxisAlignment.center,
58 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
59 | children: [
60 | InkWell(
61 | onTap: (){
62 | Navigator.pop(context);
63 | },
64 | child: Image.asset('images/icon_back.png',width: 24.0,height: 24.0,),
65 | ),
66 | InkWell(
67 | onTap: (){
68 | Navigator.pop(context);
69 | },
70 | child: Image.asset('images/icon_share.png',width: 20.0,height: 20.0,)
71 | ),
72 | ],
73 | ),
74 | )
75 | ),
76 | Positioned(
77 | left: 0.0,
78 | top: MediaQuery.of(context).padding.top+45.0,
79 | width: MediaQuery.of(context).size.width,
80 | height:MediaQuery.of(context).size.height- MediaQuery.of(context).padding.top-45.0-48.0,
81 | child: ListView(
82 | padding: EdgeInsets.only(top: 0.0), //ListView 的paddingTop 默认是有会有30左右的高度,所以这里一定要记得设置为0,一开始不知道的时候搞了好久都没明白
83 | children: [
84 | FutureBuilder(
85 | future: mHttpController.getFictionDetail(widget.fictionId),
86 | // future: mHttpController.getFictionDetail(434),
87 | builder: (BuildContext context, AsyncSnapshot snapshot){
88 | switch (snapshot.connectionState) {
89 | case ConnectionState.waiting:
90 | return Center(
91 | child: CircularProgressIndicator(),
92 | );
93 | case ConnectionState.done:
94 | if (snapshot.hasError) return Text('Error: ${snapshot.error}');
95 | return getFictionHomeContent(snapshot.data,context);
96 | default:
97 | return null;
98 | }
99 | }
100 | ),
101 | ],
102 | ),
103 | ),
104 | Positioned(
105 | left: 0.0,
106 | top: MediaQuery.of(context).size.height-48.0,
107 | width: MediaQuery.of(context).size.width,
108 | height: 48.0,
109 | child: Row(
110 | children: [
111 | Expanded(
112 | flex: 1,
113 | child: Container(
114 | color: Color(0xFFF5F5F5),
115 | child: Center(
116 | child: Text('加入书架',style: TextStyle(fontSize: 18.0,color: Color(0xFFFFB30A)),),
117 | ),
118 | )
119 | ),
120 | Expanded(
121 | flex: 1,
122 | child: Container(
123 | color: Color(0xFFFFB30A),
124 | /*child: Center(
125 | child: Text('开始阅读',style: TextStyle(fontSize: 18.0,color: Colors.white),),
126 | ),*/
127 | child: InkWell(
128 | onTap: (){
129 |
130 | },
131 | child: Center(
132 | child: Text('开始阅读',style: TextStyle(fontSize: 18.0,color: Colors.white),),
133 | ),
134 | ),
135 | )
136 | ),
137 | ],
138 | )
139 | )
140 | ],
141 | ),
142 | )
143 | );
144 | }
145 |
146 | void editComment(BuildContext context){
147 | showModalBottomSheet(
148 | context: context,
149 | builder: (BuildContext context){
150 | return Container(
151 | color: Color(0xFFF5F5F5),
152 | padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
153 | child: Column(
154 | mainAxisSize: MainAxisSize.min,
155 | crossAxisAlignment: CrossAxisAlignment.center,
156 | children: [
157 | Container(
158 | padding: EdgeInsets.only(left: 18.0,top: 18.0,right: 18.0,bottom: 12.0),
159 | child: TextField(
160 | autofocus: true,
161 | keyboardType: TextInputType.text,
162 | maxLines: 1,
163 | decoration: InputDecoration(
164 | hintText: "请文明发言,遵守评论规则",
165 | hintStyle: TextStyle(
166 | color: Color(0xFF999999),
167 | fontSize: 16.0,
168 | ),
169 | contentPadding: EdgeInsets.all(10.0),
170 | filled: true,
171 | fillColor: Colors.white,
172 | enabledBorder: OutlineInputBorder(
173 | borderRadius: BorderRadius.circular(5.0),
174 | borderSide: BorderSide(
175 | width: 0.0,
176 | color: Colors.white
177 | )
178 | ),
179 | focusedBorder: OutlineInputBorder(
180 | borderRadius: BorderRadius.circular(5.0),
181 | borderSide: BorderSide(
182 | width: 0.0,
183 | color: Colors.white
184 | )
185 | )
186 | ),
187 | ),
188 | ),
189 | Container(
190 | padding: EdgeInsets.only(left: 18.0,right: 18.0,bottom: 18.0),
191 | child: Row(
192 | children: [
193 | Container(
194 | child: Icon(
195 | Icons.sentiment_satisfied,
196 | )
197 | ),
198 | Container(
199 | margin: EdgeInsets.only(left: 20.0),
200 | child: Icon(
201 | Icons.copyright,
202 | )
203 | ),
204 |
205 | Expanded(
206 | flex: 1,
207 | child:Container() ,
208 | ),
209 |
210 | Container(
211 | width: 65.0,
212 | height: 30.0,
213 | decoration: BoxDecoration(
214 | borderRadius: BorderRadius.circular(5.0),
215 | color: Color(0xFFFFB30A)
216 | ),
217 | child: Center(
218 | child: Text("发送",style: TextStyle(
219 | fontSize: 14.0,color: Colors.white
220 | ),),
221 | ),
222 | )
223 |
224 | ],
225 | ),
226 | )
227 |
228 | ],
229 | ),
230 | );
231 | }
232 | );
233 | }
234 |
235 | Widget getFictionHomeContent(FictionDetailResponse fictionDetailResponse,BuildContext context){
236 | return Column(
237 | mainAxisAlignment: MainAxisAlignment.start,
238 | children: [
239 | getCoverWidget(fictionDetailResponse.data),
240 | getDescView(fictionDetailResponse.data),
241 | getCommentView(fictionDetailResponse.data,context),
242 | getHotPushWidgets(fictionDetailResponse.data.pushBookList),
243 | ],
244 | );
245 | }
246 |
247 | Widget getCoverWidget(FictionDetailBean fictionDetailBean) {
248 | return Container(
249 | padding: EdgeInsets.only(top: 10.0, bottom: 15.0),
250 | child: Row(
251 | mainAxisAlignment: MainAxisAlignment.center,
252 | children: [
253 | Image.network(
254 | fictionDetailBean.picture, width: 90.0, height: 120.0,),
255 | Container(
256 | padding: EdgeInsets.only(left: 10.0),
257 | child: Column(
258 | mainAxisAlignment: MainAxisAlignment.center,
259 | crossAxisAlignment: CrossAxisAlignment.start,
260 | children: [
261 | Text(fictionDetailBean.name, style: TextStyle(fontSize: 16.0,
262 | fontWeight: FontWeight.bold,
263 | color: Color(0xFF333333)),),
264 | Container(
265 | margin: EdgeInsets.only(top: 7.0),
266 | child: StaticRatingBar(
267 | size: 12.0,
268 | rate: fictionDetailBean.score.toDouble(),
269 | ),
270 | ),
271 | Container(
272 | margin: EdgeInsets.only(top: 7.0),
273 | child: Text(fictionDetailBean.author,style: TextStyle(fontSize: 12.0,color: Color(0xFF999999)),),
274 | ),
275 | Container(
276 | margin: EdgeInsets.only(top: 7.0),
277 | child: Row(
278 | mainAxisAlignment: MainAxisAlignment.start,
279 | children: [
280 | Text(fictionDetailBean.state,style: TextStyle(fontSize: 12.0,color: Color(0xFF999999)),),
281 | Container(
282 | padding: EdgeInsets.only(left: 10.0),
283 | child: Text(fictionDetailBean.wordCount.toString()+'万字',style: TextStyle(fontSize: 12.0,color: Color(0xFF999999)),),
284 | )
285 | ],
286 | )
287 | ),
288 | Container(
289 | margin: EdgeInsets.only(top: 7.0),
290 | child: Row(
291 | mainAxisAlignment: MainAxisAlignment.start,
292 | children: fictionDetailBean.tags.map((String table){
293 | return getTableView(table);
294 | }).toList(),
295 | ),
296 | ),
297 | ],
298 | ),
299 | ),
300 | ],
301 | )
302 | );
303 | }
304 |
305 | Widget getCommentView(FictionDetailBean fictionDetailBean,BuildContext context){
306 | if(fictionDetailBean.lastComment!=null){
307 | return Column(
308 | children: [
309 | Container(
310 | padding: EdgeInsets.all(12.0),
311 | color: Colors.white,
312 | child: Row(
313 | children: [
314 | Text('书友互动',style: TextStyle(fontSize: 16.0,fontWeight: FontWeight.bold,color: Color(0xFF333333)),),
315 | Container(
316 | margin: EdgeInsets.only(left: 5.0),
317 | child: Text(fictionDetailBean.commentCount.toString()+'评',style: TextStyle(fontSize: 12.0,color: Color(0xFF999999)),),
318 | ),
319 | Container(
320 | margin: EdgeInsets.only(left: 153.0),
321 | child: InkWell(
322 | onTap: (){
323 | editComment(context);
324 | },
325 | child: Image.asset('images/icon_add_comment.png',width: 87.0,height: 32.0,),
326 | )
327 | )
328 | ],
329 | ),
330 | ),
331 | Container(
332 | padding: EdgeInsets.only(left: 12.0,right: 12.0,bottom: 12.0),
333 | color: Colors.white,
334 | child: Row(
335 | crossAxisAlignment: CrossAxisAlignment.start,
336 | children: [
337 | ClipOval(
338 | child: Image.network(fictionDetailBean.lastComment.userAvatar,width: 36.0,height: 36.0,),
339 | ),
340 | Expanded(
341 | child: Container(
342 | margin: EdgeInsets.only(left: 10.0),
343 | child: Column(
344 | crossAxisAlignment: CrossAxisAlignment.start,
345 | mainAxisAlignment: MainAxisAlignment.start,
346 | children: [
347 | Text(fictionDetailBean.lastComment.userName,style: TextStyle(fontSize: 14.0,color: Color(0xFF333333)),),
348 | Container(
349 | margin: EdgeInsets.only(top: 3.0),
350 | child: StaticRatingBar(
351 | size: 12.0,
352 | rate: fictionDetailBean.lastComment.level.toDouble(),
353 | ),
354 | ),
355 | Container(
356 | margin: EdgeInsets.only(top: 10.0),
357 | child: Text(fictionDetailBean.lastComment.comment,style: TextStyle(fontSize: 14.0,color: Color(0xFF333333)),maxLines: 2,overflow: TextOverflow.ellipsis,),
358 | )
359 | ],
360 | ),
361 | )
362 | )
363 |
364 | ],
365 | ),
366 | ),
367 | Container(
368 | margin: EdgeInsets.only(top: 1.0),
369 | color: Colors.white,
370 | padding: EdgeInsets.all(12.0),
371 | child: Row(
372 | mainAxisAlignment: MainAxisAlignment.center,
373 | children: [
374 | Text('查看更多',style: TextStyle(fontSize: 14.0,color: Color(0xFFFFB30A)),),
375 | Container(
376 | margin: EdgeInsets.only(left: 5.0),
377 | child: Image.asset('images/icon_right.png',width: 6.0,height: 12.0,),
378 | )
379 | ],
380 | ),
381 | )
382 | ],
383 | );
384 | }else{
385 | return Container(
386 | color: Colors.white,
387 | child: Column(
388 | crossAxisAlignment: CrossAxisAlignment.center,
389 | children: [
390 | Container(
391 | padding: EdgeInsets.all(12.0),
392 | child: Row(
393 | children: [
394 | Text('书友互动',style: TextStyle(fontSize: 16.0,fontWeight: FontWeight.bold,color: Color(0xFF333333)),),
395 | ],
396 | ),
397 | ),
398 | Container(
399 | margin: EdgeInsets.only(top: 40.0,bottom: 10.0),
400 | child: Text('暂时还没有评论',style: TextStyle(fontSize: 12.0,color: Color(0xFF999999)),),
401 | ),
402 | Container(
403 | margin: EdgeInsets.only(bottom: 40.0),
404 | child: InkWell(
405 | onTap: (){
406 | editComment(context);
407 | },
408 | child: Image.asset('images/icon_add_comment.png',width: 87.0,height: 32.0,),
409 | )
410 | ),
411 | ],
412 | ),
413 | );
414 | }
415 | }
416 |
417 | Widget getDescView(FictionDetailBean fictionDetailBean){
418 | return Column(
419 | children: [
420 | Container(
421 | color: Colors.white,
422 | padding: EdgeInsets.all(12.0),
423 | child: Text(fictionDetailBean.description,style: TextStyle(fontSize: 14.0,color: Color(0xFF333333)),maxLines: 3,overflow: TextOverflow.ellipsis,),
424 | ),
425 | Container(
426 | height: 1.0,
427 | color: Color(0xFFF5F5F5),
428 | ),
429 | Container(
430 | padding: EdgeInsets.all(12.0),
431 | width: MediaQuery.of(context).size.width,
432 | color: Colors.white,
433 | child: Stack(
434 | alignment: AlignmentDirectional.center,
435 | children: [
436 | Row(
437 | crossAxisAlignment: CrossAxisAlignment.center,
438 | children: [
439 | Text('目录',style: TextStyle(fontSize: 16.0,color: Color(0xFF333333),fontWeight: FontWeight.bold),),
440 | Container(
441 | margin: EdgeInsets.only(left: 17.0),
442 | child: Text('连载至'+fictionDetailBean.chapterCount.toString()+'章',style: TextStyle(fontSize: 14.0,color: Color(0xFF666666)),),
443 | ),
444 |
445 | ],
446 | ),
447 | Row(
448 | textDirection: TextDirection.rtl,
449 | mainAxisAlignment: MainAxisAlignment.start,
450 | crossAxisAlignment: CrossAxisAlignment.center,
451 | children: [
452 | Image.asset('images/icon_right.png',width: 6.0,height: 12.0,)
453 | ],
454 | )
455 | ],
456 | ),
457 | ),
458 | Container(
459 | height: 12.0,
460 | color: Color(0xFFF5F5F5),
461 | ),
462 | ],
463 | );
464 | }
465 |
466 | Widget getTableView(String table){
467 | return Container(
468 | margin: EdgeInsets.only(right: 10.0),
469 | child: DecoratedBox(
470 | decoration: BoxDecoration(
471 | borderRadius: BorderRadius.circular(20.0),
472 | border: Border.all(
473 | color: Color(0xFFFFB30A),
474 | width: 1.0
475 | )
476 | ),
477 | child: Container(
478 | padding: EdgeInsets.fromLTRB(10.0, 2.0, 10.0, 2.0),
479 | child: Center(
480 | child: Text(table,style: TextStyle(fontSize: 12.0,color: Color(0xFFFFB30A)),),
481 | ),
482 | )
483 | ),
484 | );
485 | }
486 |
487 | //获取热门推荐
488 | Widget getHotPushWidgets(List hotPushLists){
489 | return Container(
490 | margin: EdgeInsets.only(top: 12.0,bottom: 12.0),
491 | padding: EdgeInsets.all(12.0),
492 | color: Colors.white,
493 | child: Column(
494 | crossAxisAlignment: CrossAxisAlignment.start,
495 | children: [
496 | Text('同类热门推荐',style: TextStyle(fontSize: 16.0,color: Colors.black,fontWeight: FontWeight.bold),),
497 | Container(
498 | padding: EdgeInsets.only(top: 10.0),
499 | child: Row(
500 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
501 | children: hotPushLists.map((FictionPushBook fictionPushBook){
502 | return getFictionNormalStyle(fictionPushBook);
503 | }).toList(),
504 | ),
505 | ),
506 | ],
507 | ),
508 | );
509 | }
510 |
511 | Widget getFictionNormalStyle(FictionPushBook fictionPushBook){
512 | return InkWell(
513 | onTap: (){
514 | Navigator.push(context,
515 | MaterialPageRoute(builder: (context){
516 |
517 | }));
518 | },
519 | child: Column(
520 | mainAxisSize: MainAxisSize.min,
521 | mainAxisAlignment: MainAxisAlignment.start,
522 | crossAxisAlignment: CrossAxisAlignment.start,
523 | children: [
524 | Image.network(fictionPushBook.picture,width: 90.0,height: 120.0,),
525 | Container(
526 | width: 90.0,
527 | margin: EdgeInsets.only(top: 5.0,bottom: 3.0),
528 | child: Text(fictionPushBook.name,style: TextStyle(fontSize: 14.0,color: Color(0xFF333333)),softWrap: false,overflow: TextOverflow.ellipsis,),
529 | ),
530 | Container(
531 | width: 90.0,
532 | child: Text(fictionPushBook.author,style: TextStyle(fontSize: 14.0,color: Color(0xFF999999)),softWrap: false,overflow: TextOverflow.ellipsis,),
533 | ),
534 | ],
535 | ),
536 | );
537 | }
538 |
539 | }
540 |
--------------------------------------------------------------------------------
/flutter_demo/lib/FictionManFeatured.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'bean/FictionHomeInfoResponse.dart';
3 | import 'controller/HttpController.dart';
4 |
5 | class FictionManFeatured extends StatefulWidget{
6 | List manLists;
7 | bool isMan;
8 |
9 | FictionManFeatured({this.manLists,this.isMan});
10 |
11 |
12 | @override
13 | State createState() {
14 | // TODO: implement createState
15 | return new FictionManFeaturedState();
16 | }
17 |
18 | }
19 |
20 | class FictionManFeaturedState extends State{
21 |
22 | HttpController mHttpController;
23 |
24 | @override
25 | void initState() {
26 | // TODO: implement initState
27 | super.initState();
28 | mHttpController=new HttpController();
29 | }
30 |
31 |
32 | @override
33 | Widget build(BuildContext context) {
34 | // TODO: implement build
35 | return getManFeaturedWidgets(widget.manLists);
36 | }
37 |
38 | Widget getManFeaturedWidgets(List manPushLists){
39 | return Column(
40 | crossAxisAlignment: CrossAxisAlignment.start,
41 | children: [
42 | Container(
43 | padding: EdgeInsets.only(top: 10.0),
44 | child: Text(widget.isMan ? '男生精选' : '女生精选',style: TextStyle(fontSize: 16.0,color: Colors.black,fontWeight: FontWeight.bold),),
45 | ),
46 | Container(
47 | padding: EdgeInsets.only(top: 10.0),
48 | child: Row(
49 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
50 | children: manPushLists.map((FictionIntroduction fictionIntroduction){
51 | return getFictionNormalStyle(fictionIntroduction);
52 | }).toList(),
53 | ),
54 | ),
55 | Container(
56 | margin: EdgeInsets.only(top: 10.0),
57 | height: 1.0,
58 | color: Color.fromARGB(150, 235, 235, 235),
59 | ),
60 | InkWell(
61 | onTap: (){
62 | getReplaceFiction(widget.isMan ? 'boy' : 'girl');
63 | },
64 | child: ConstrainedBox(
65 | constraints: BoxConstraints(minWidth: MediaQuery.of(context).size.width),
66 | child: Stack(
67 | fit: StackFit.loose,
68 | alignment: AlignmentDirectional.center,
69 | children: [
70 | Container(
71 | margin: EdgeInsets.only(top: 10.0,bottom: 10.0),
72 | child: Image.asset('images/icon_replace.png',width: 78.0,height: 22.0,),
73 | ),
74 | Text('换一换',style: TextStyle(fontSize: 14.0,color: Color(0xFFFFB30A)),)
75 | ],
76 | ),
77 | )
78 | ),
79 |
80 | ],
81 | );
82 | }
83 |
84 | Widget getFictionNormalStyle(FictionIntroduction fictionIntroduction){
85 | return Column(
86 | mainAxisSize: MainAxisSize.min,
87 | mainAxisAlignment: MainAxisAlignment.start,
88 | crossAxisAlignment: CrossAxisAlignment.start,
89 | children: [
90 | Image.network(fictionIntroduction.picture,width: 90.0,height: 120.0,),
91 | Container(
92 | width: 90.0,
93 | margin: EdgeInsets.only(top: 5.0,bottom: 3.0),
94 | child: Text(fictionIntroduction.name,style: TextStyle(fontSize: 14.0,color: Color(0xFF333333)),softWrap: false,overflow: TextOverflow.ellipsis,),
95 | ),
96 | Container(
97 | width: 90.0,
98 | child: Text(fictionIntroduction.author,style: TextStyle(fontSize: 14.0,color: Color(0xFF999999)),softWrap: false,overflow: TextOverflow.ellipsis,),
99 | ),
100 | ],
101 | );
102 | }
103 |
104 | void getReplaceFiction(String type) async{
105 | await mHttpController.getReplaceFiction(type,(replacePushResponse){
106 | if(replacePushResponse!=null){
107 | setState(() {
108 | widget.manLists=replacePushResponse.data;
109 | });
110 | }
111 | });
112 | }
113 |
114 | }
--------------------------------------------------------------------------------
/flutter_demo/lib/ImagePickerPage.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 | import 'package:flutter/material.dart';
3 | import 'package:image_picker/image_picker.dart';
4 |
5 | class ImagePickerPage extends StatefulWidget {
6 | @override
7 | ImagePickerPageState createState() => ImagePickerPageState();
8 | }
9 |
10 | class ImagePickerPageState extends State {
11 | File _image;
12 |
13 | Future getImage() async {
14 | var image = await ImagePicker.pickImage(source: ImageSource.gallery);
15 |
16 | setState(() {
17 | _image = image;
18 | });
19 | }
20 |
21 | @override
22 | Widget build(BuildContext context) {
23 | return Scaffold(
24 | appBar: AppBar(
25 | title: Text('Image Picker Example'),
26 | ),
27 | body: Center(
28 | child: _image == null
29 | ? Text('No image selected.')
30 | : Image.file(_image),
31 | ),
32 | floatingActionButton: FloatingActionButton(
33 | onPressed: getImage,
34 | tooltip: 'Pick Image',
35 | child: Icon(Icons.add_a_photo),
36 | ),
37 | );
38 | }
39 | }
--------------------------------------------------------------------------------
/flutter_demo/lib/NewsDetailPageView.dart:
--------------------------------------------------------------------------------
1 |
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter_demo/bean/NewsResData.dart';
5 | import 'package:flutter_demo/view/NewDetailWebview.dart';
6 |
7 | class NewsDetailPageView extends StatefulWidget{
8 | News mNews;
9 | NewsDetailPageView({this.mNews});
10 |
11 | @override
12 | State createState() {
13 | // TODO: implement createState
14 | return new NewsDetailPageViewState();
15 | }
16 |
17 | }
18 |
19 | class NewsDetailPageViewState extends State{
20 | @override
21 | Widget build(BuildContext context) {
22 | // TODO: implement build
23 | return new Theme(
24 | data: ThemeData(
25 | primaryColor: Color(0xFFF5F5F5)
26 | ),
27 | child: Scaffold(
28 | body: Column(
29 | children: [
30 | Container(
31 | height: 40.0,
32 | child: Text('中国联通中国联通中国联通'),
33 | ),
34 | Transform(transform: null),
35 | Container(
36 | height: MediaQuery.of(context).size.height-150.0,
37 | child: NewDetailWebview(mNews: widget.mNews),
38 | ),
39 |
40 | ],
41 | ),
42 | )
43 | );
44 | }
45 |
46 | }
--------------------------------------------------------------------------------
/flutter_demo/lib/PersonalPage.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class PersonalPage extends StatefulWidget{
4 | @override
5 | State createState() {
6 | // TODO: implement createState
7 | return new PersonalPageState();
8 | }
9 |
10 | }
11 |
12 | class PersonalPageState extends State{
13 | @override
14 | Widget build(BuildContext context) {
15 | // TODO: implement build
16 | return Scaffold(
17 | body: Column(
18 | children: [
19 | getHeartView(),
20 | ],
21 | ),
22 | );
23 | }
24 |
25 | Widget getHeartView(){
26 | return Stack(
27 | children: [
28 | Image.asset('images/personal_heart_bg.png',),
29 | Column(
30 | children: [
31 | Row(
32 | textDirection: TextDirection.rtl,
33 | mainAxisAlignment: MainAxisAlignment.start,
34 | crossAxisAlignment: CrossAxisAlignment.center,
35 | children: [
36 | Container(
37 | padding: EdgeInsets.all(2.0),
38 | margin: EdgeInsets.only(top: MediaQuery.of(context).padding.top,right: 8.0),
39 | child: Image.asset('images/setting.png',width: 20.0,height: 20.0,),
40 | )
41 | ],
42 | ),
43 |
44 | Container(
45 | margin: EdgeInsets.only(left: 20.0),
46 | child: Row(
47 | mainAxisAlignment: MainAxisAlignment.start,
48 | crossAxisAlignment: CrossAxisAlignment.center,
49 | children: [
50 | Image.asset('images/personal_ava_default.png',width: 72.0,height: 72.0,),
51 | Container(
52 | margin: EdgeInsets.only(left: 8.0),
53 | child: Column(
54 | mainAxisAlignment: MainAxisAlignment.center,
55 | crossAxisAlignment: CrossAxisAlignment.start,
56 | children: [
57 | Text('Betty',style: TextStyle(fontSize: 16.0,color: Color(0xFF333333),),),
58 | Text('ID:12345678',style: TextStyle(fontSize: 16.0,color: Color(0xFF333333),),),
59 | ],
60 | ),
61 | )
62 | ],
63 | ),
64 | ),
65 |
66 | Container(
67 | padding: EdgeInsets.fromLTRB(30.0, 30.0, 30.0, 0.0),
68 | child: Row(
69 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
70 | crossAxisAlignment: CrossAxisAlignment.center,
71 | children: [
72 | Column(
73 | mainAxisSize: MainAxisSize.min,
74 | crossAxisAlignment: CrossAxisAlignment.center,
75 | children: [
76 | Text('5000',style: TextStyle(fontSize: 20.0,color: Color(0xFF333333),),),
77 | Padding(
78 | padding: EdgeInsets.only(top: 3.0),
79 | child: Text('我的金币',style: TextStyle(fontSize: 14.0,color: Color(0xFF333333)),),
80 | )
81 | ],
82 | ),
83 | Container(
84 | width: 1.0,
85 | height: 27.0,
86 | color: Color(0xFF999999),
87 | ),
88 | Column(
89 | mainAxisSize: MainAxisSize.min,
90 | crossAxisAlignment: CrossAxisAlignment.center,
91 | children: [
92 | Text('10',style: TextStyle(fontSize: 20.0,color: Color(0xFF333333),),),
93 | Padding(
94 | padding: EdgeInsets.only(top: 3.0),
95 | child: Text('我的零钱',style: TextStyle(fontSize: 14.0,color: Color(0xFF333333)),),
96 | )
97 | ],
98 | ),
99 | Container(
100 | width: 1.0,
101 | height: 27.0,
102 | color: Color(0xFF999999),
103 | ),
104 | Column(
105 | mainAxisSize: MainAxisSize.min,
106 | crossAxisAlignment: CrossAxisAlignment.center,
107 | children: [
108 | Text('7',style: TextStyle(fontSize: 20.0,color: Color(0xFF333333),),),
109 | Padding(
110 | padding: EdgeInsets.only(top: 3.0),
111 | child: Text('收徒人数',style: TextStyle(fontSize: 14.0,color: Color(0xFF333333)),),
112 | )
113 | ],
114 | )
115 | ],
116 | ),
117 | ),
118 |
119 | Container(
120 | padding: EdgeInsets.fromLTRB(30.0, 35.0, 30.0, 15.0),
121 | child: Row(
122 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
123 | crossAxisAlignment: CrossAxisAlignment.center,
124 | children: [
125 | Column(
126 | mainAxisSize: MainAxisSize.min,
127 | crossAxisAlignment: CrossAxisAlignment.center,
128 | children: [
129 | Image.asset('images/mine_withdraw_icon.png',width: 24.0,height: 24.0,),
130 | Padding(
131 | padding: EdgeInsets.only(top: 3.0),
132 | child: Text('提现',style: TextStyle(fontSize: 14.0,color: Color(0xFF333333)),),
133 | )
134 | ],
135 | ),
136 | Column(
137 | mainAxisSize: MainAxisSize.min,
138 | crossAxisAlignment: CrossAxisAlignment.center,
139 | children: [
140 | Image.asset('images/mine_cash_icon.png',width: 24.0,height: 24.0,),
141 | Padding(
142 | padding: EdgeInsets.only(top: 3.0),
143 | child: Text('明细',style: TextStyle(fontSize: 14.0,color: Color(0xFF333333)),),
144 | )
145 | ],
146 | ),
147 | Column(
148 | mainAxisSize: MainAxisSize.min,
149 | crossAxisAlignment: CrossAxisAlignment.center,
150 | children: [
151 | Image.asset('images/mine_apprentice_icon.png',width: 24.0,height: 24.0,),
152 | Padding(
153 | padding: EdgeInsets.only(top: 3.0),
154 | child: Text('收徒',style: TextStyle(fontSize: 14.0,color: Color(0xFF333333)),),
155 | )
156 | ],
157 | ),
158 | Column(
159 | mainAxisSize: MainAxisSize.min,
160 | crossAxisAlignment: CrossAxisAlignment.center,
161 | children: [
162 | Image.asset('images/mine_message_icon.png',width: 24.0,height: 24.0,),
163 | Padding(
164 | padding: EdgeInsets.only(top: 3.0),
165 | child: Text('消息',style: TextStyle(fontSize: 14.0,color: Color(0xFF333333)),),
166 | )
167 | ],
168 | ),
169 | ],
170 | ),
171 | ),
172 |
173 | Container(
174 | width: MediaQuery.of(context).size.width,
175 | height: 10.0,
176 | color: Color(0xFFEEEEEE),
177 | ),
178 |
179 | Container(
180 | padding: EdgeInsets.all(12.0),
181 | width: MediaQuery.of(context).size.width,
182 | color: Colors.white,
183 | child: Stack(
184 | alignment: AlignmentDirectional.center,
185 | children: [
186 | Row(
187 | crossAxisAlignment: CrossAxisAlignment.center,
188 | children: [
189 | Image.asset('images/mine_code_icon.png',width: 20.0,height: 20.0,),
190 | Container(
191 | padding: EdgeInsets.only(left: 10.0),
192 | child: Text('面对面收徒',style: TextStyle(fontSize: 16.0,color: Color(0xFF333333)),),
193 | )
194 |
195 | ],
196 | ),
197 | Row(
198 | textDirection: TextDirection.rtl,
199 | mainAxisAlignment: MainAxisAlignment.start,
200 | crossAxisAlignment: CrossAxisAlignment.center,
201 | children: [
202 | Image.asset('images/icon_right.png',width: 6.0,height: 12.0,)
203 | ],
204 | )
205 | ],
206 | ),
207 | ),
208 |
209 | Container(
210 | padding: EdgeInsets.all(12.0),
211 | margin: EdgeInsets.only(top: 1.0),
212 | width: MediaQuery.of(context).size.width,
213 | color: Colors.white,
214 | child: Stack(
215 | alignment: AlignmentDirectional.center,
216 | children: [
217 | Row(
218 | crossAxisAlignment: CrossAxisAlignment.center,
219 | children: [
220 | Image.asset('images/mine_riddle_icon.png',width: 20.0,height: 20.0,),
221 | Container(
222 | padding: EdgeInsets.only(left: 10.0),
223 | child: Text('答题解谜',style: TextStyle(fontSize: 16.0,color: Color(0xFF333333)),),
224 | )
225 |
226 | ],
227 | ),
228 | Row(
229 | textDirection: TextDirection.rtl,
230 | mainAxisAlignment: MainAxisAlignment.start,
231 | crossAxisAlignment: CrossAxisAlignment.center,
232 | children: [
233 | Image.asset('images/icon_right.png',width: 6.0,height: 12.0,)
234 | ],
235 | )
236 | ],
237 | ),
238 | ),
239 |
240 | Container(
241 | padding: EdgeInsets.all(12.0),
242 | margin: EdgeInsets.only(top: 1.0),
243 | width: MediaQuery.of(context).size.width,
244 | color: Colors.white,
245 | child: Stack(
246 | alignment: AlignmentDirectional.center,
247 | children: [
248 | Row(
249 | crossAxisAlignment: CrossAxisAlignment.center,
250 | children: [
251 | Image.asset('images/mine_guess_icon.png',width: 20.0,height: 20.0,),
252 | Container(
253 | padding: EdgeInsets.only(left: 10.0),
254 | child: Text('趣味竞猜',style: TextStyle(fontSize: 16.0,color: Color(0xFF333333)),),
255 | )
256 |
257 | ],
258 | ),
259 | Row(
260 | textDirection: TextDirection.rtl,
261 | mainAxisAlignment: MainAxisAlignment.start,
262 | crossAxisAlignment: CrossAxisAlignment.center,
263 | children: [
264 | Image.asset('images/icon_right.png',width: 6.0,height: 12.0,)
265 | ],
266 | )
267 | ],
268 | ),
269 | ),
270 |
271 | Container(
272 | width: MediaQuery.of(context).size.width,
273 | height: 10.0,
274 | color: Color(0xFFEEEEEE),
275 | ),
276 |
277 | Container(
278 | padding: EdgeInsets.all(12.0),
279 | margin: EdgeInsets.only(top: 1.0),
280 | width: MediaQuery.of(context).size.width,
281 | color: Colors.white,
282 | child: Stack(
283 | alignment: AlignmentDirectional.center,
284 | children: [
285 | Row(
286 | crossAxisAlignment: CrossAxisAlignment.center,
287 | children: [
288 | Image.asset('images/mine_wallet_icon.png',width: 20.0,height: 20.0,),
289 | Container(
290 | padding: EdgeInsets.only(left: 10.0),
291 | child: Text('赚钱攻略',style: TextStyle(fontSize: 16.0,color: Color(0xFF333333)),),
292 | )
293 |
294 | ],
295 | ),
296 | Row(
297 | textDirection: TextDirection.rtl,
298 | mainAxisAlignment: MainAxisAlignment.start,
299 | crossAxisAlignment: CrossAxisAlignment.center,
300 | children: [
301 | Image.asset('images/icon_right.png',width: 6.0,height: 12.0,),
302 | Container(
303 | padding: EdgeInsets.only(right: 10.0),
304 | child: Text('教你玩转百万头条',style: TextStyle(fontSize: 13.0,color: Color(0xFFFF9600)),),
305 | ),
306 | ],
307 | )
308 | ],
309 | ),
310 | ),
311 |
312 | ],
313 | )
314 | ],
315 | );
316 | }
317 |
318 | }
--------------------------------------------------------------------------------
/flutter_demo/lib/ScannerPage.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 | import 'dart:typed_data';
3 |
4 | import 'package:flutter/material.dart';
5 | import 'package:pointycastle/asymmetric/pkcs1.dart';
6 | import 'package:pointycastle/asymmetric/rsa.dart';
7 | import 'dart:async';
8 | import 'package:qrcode_reader/qrcode_reader.dart';
9 | import 'package:pointycastle/pointycastle.dart';
10 |
11 | class ScannerPage extends StatefulWidget {
12 |
13 | final Map pluginParameters = {
14 | };
15 |
16 | @override
17 | ScannerPageState createState() => new ScannerPageState();
18 | }
19 |
20 | class ScannerPageState extends State {
21 | Future _barcodeString;
22 |
23 | @override
24 | Widget build(BuildContext context) {
25 | return new Scaffold(
26 | appBar: new AppBar(
27 | title: const Text('QRCode Reader Example'),
28 | ),
29 | body: new Center(
30 | child: new FutureBuilder(
31 | future: _barcodeString,
32 | builder: (BuildContext context, AsyncSnapshot snapshot) {
33 | return new Text(snapshot.data != null ? snapshot.data : '');
34 | })),
35 | floatingActionButton: new FloatingActionButton(
36 | onPressed: () {
37 | // getHuText();
38 | setState(() {
39 | _barcodeString = new QRCodeReader()
40 | .setAutoFocusIntervalInMs(200)
41 | .setForceAutoFocus(true)
42 | .setTorchEnabled(true)
43 | .setHandlePermissions(true)
44 | .setExecuteAfterPermissionGranted(true)
45 | .scan();
46 | });
47 | },
48 | tooltip: 'Reader the QRCode',
49 | child: new Icon(Icons.add_a_photo),
50 | ),
51 | );
52 | }
53 |
54 |
55 | getHuText(){
56 | var text = "3112003057";
57 | String key="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1nMYS0QLT6yAgHM1d+pqYhRRhTABXp/kq0W7nIUT3etjSWi8JfoqvkfShINF4CovBSTJ7sNko7j3yKEFn5HzaF1INKWTVfZprpEyFBnAa+ydBiVHKQ85vRyyoX67lMSKOrnq7B37h5bdnE7faoajsaOCnx5wtlya7AGVB4fxfOQIDAQAB";
58 | BigInt modulus = BigInt.parse(key,radix: 16);
59 | BigInt exponent = BigInt.from(65537);
60 | var pubKey = RSAPublicKey(modulus, exponent);
61 | AsymmetricBlockCipher cipher = PKCS1Encoding(RSAEngine());
62 | cipher.init(true, PublicKeyParameter(pubKey));
63 | Uint8List output = cipher.process(utf8.encode(text));
64 | var base64EncodedText = base64Encode(output);
65 | print("base64EncodedText="+base64EncodedText);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/flutter_demo/lib/SearchPage.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'package:flutter_demo/bean/ChannelResponse.dart';
4 | import 'package:flutter_demo/bean/HotSearchResponse.dart';
5 | import 'package:flutter_demo/channelView.dart';
6 | import 'package:flutter_demo/controller/HttpController.dart';
7 | import 'package:flutter_demo/utils/SpUtil.dart';
8 | import 'package:flutter_demo/view/SearchView.dart';
9 |
10 | class SearchPage extends StatefulWidget{
11 |
12 | @override
13 | State createState() {
14 | // TODO: implement createState
15 | return new SearchPageSate();
16 | }
17 | }
18 |
19 | class SearchPageSate extends State{
20 |
21 | HttpController mHttpController;
22 |
23 | List historySearchList= [];
24 | bool mShowSearchContent=false;
25 |
26 | FocusNode _focusNode = FocusNode();
27 | TextEditingController _controller = new TextEditingController();
28 |
29 | String mSearchText="";
30 |
31 | @override
32 | void initState() {
33 | // TODO: implement initState
34 | super.initState();
35 | mHttpController=new HttpController();
36 | getHistory();
37 | }
38 |
39 | void getHistory(){
40 | List data=SpUtil.getStringList("historySearch",defValue : []);
41 | setState(() {
42 | historySearchList.addAll(data);
43 | });
44 | }
45 |
46 | @override
47 | Widget build(BuildContext context) {
48 | // TODO: implement build
49 | // return layout(context);
50 | return Theme(
51 | data: ThemeData(
52 | primaryColor: Color(0xFFF5F5F5)
53 | ),
54 | child: Scaffold(
55 | body: Stack(
56 | children: [
57 | Positioned(
58 | top: 0.0,
59 | left: 0.0,
60 | child: Container(
61 | color: Color(0xFFFFFFFF),
62 | height: MediaQuery.of(context).padding.top,
63 | width: MediaQuery.of(context).size.width,
64 | )
65 | ),
66 | Positioned(
67 | top: MediaQuery.of(context).padding.top,
68 | left: 0.0,
69 | child: new Container(
70 | color: Color(0xFFFFFFFF),
71 | height: 40.0,
72 | width: MediaQuery.of(context).size.width,
73 | padding: EdgeInsets.only(left: 12.0,right: 12.0),
74 | child: Row(
75 | mainAxisAlignment: MainAxisAlignment.start,
76 | crossAxisAlignment: CrossAxisAlignment.center,
77 | children: [
78 | Expanded(
79 | flex: 5,
80 | child: new SearchView(
81 | focusNode: _focusNode,
82 | controller: _controller,
83 | inputFormatters: [
84 | LengthLimitingTextInputFormatter(50),
85 | ],
86 | onChangedCallback: () {
87 | onSearchTextChangeCallBack();
88 | },
89 | onEditingComplete: () => _checkInput()
90 | )
91 | ),
92 | Expanded(
93 | flex: 1,
94 | child: InkWell(
95 | onTap: (){
96 | Navigator.pop(context);
97 | },
98 | child: Container(
99 | padding: EdgeInsets.only(left: 10.0),
100 | child: Text('取消',style: TextStyle(fontSize: 16.0,color: Color(0xFF333333)),),
101 | ),
102 | )
103 | )
104 | ],
105 | ),
106 | ),
107 | ),
108 | Positioned(
109 | top: MediaQuery.of(context).padding.top + 40.0,
110 | left: 0.0,
111 | height: MediaQuery.of(context).size.height-40.0-MediaQuery.of(context).padding.top,
112 | width: MediaQuery.of(context).size.width,
113 | child: Container(
114 | color: Color(0xFFFFFFFF),
115 | padding: EdgeInsets.only(top: 5.0),
116 | child: layout(context)
117 | )
118 | )
119 | ],
120 | )
121 | )
122 | );
123 | }
124 |
125 | Widget layout(BuildContext context){
126 | if(!mShowSearchContent){
127 | return Column(
128 | children: [
129 | getHeadView(),
130 | Container(
131 | width: MediaQuery.of(context).size.width,
132 | color: Color(0xFFFFFFFF),
133 | padding: EdgeInsets.all(12.0),
134 | child: Text('热门搜索',style: TextStyle(fontSize: 16.0,color: Color(0xFF000000),fontWeight: FontWeight.bold),),
135 | ),
136 | Container(
137 | width: MediaQuery.of(context).size.width,
138 | height: 300.0,
139 | child: FutureBuilder(
140 | future: mHttpController.getHotSearchKeyWord(),
141 | builder: (BuildContext context, AsyncSnapshot snapshot){
142 | switch (snapshot.connectionState) {
143 | case ConnectionState.waiting:
144 | return Center(
145 | child: CircularProgressIndicator(),
146 | );
147 | case ConnectionState.done:
148 | if (snapshot.hasError) return Text('Error: ${snapshot.error}');
149 | return getHotSearchContent(snapshot.data);
150 | default:
151 | return null;
152 | }
153 | }
154 | ),
155 | ),
156 | ],
157 | );
158 | }else{
159 | return NewsListView(mChannelCode: 0.toString(),mSearchText: mSearchText,);
160 | }
161 | }
162 |
163 | void _checkInput() {
164 | String searchText = _controller.text;
165 | if (searchText.isEmpty) {
166 | FocusScope.of(context).requestFocus(_focusNode);
167 | return;
168 | }
169 |
170 | setState(() {
171 | mSearchText=searchText;
172 | mShowSearchContent=true;
173 | historySearchList.insert(0, mSearchText);
174 | SpUtil.putStringList('historySearch', historySearchList);
175 |
176 | });
177 |
178 | }
179 |
180 | void onSearchTextChangeCallBack(){
181 | String searchText = _controller.text;
182 | if (searchText.isEmpty) {
183 | setState(() {
184 | mSearchText="";
185 | mShowSearchContent=false;
186 | });
187 | }
188 | }
189 |
190 | Widget getHotSearchContent(HotSearchResponse response){
191 | List data=response.data;
192 | return new GridView.builder(
193 | padding: const EdgeInsets.only(left: 12.0),
194 | gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
195 | mainAxisSpacing: 5.0,
196 | crossAxisSpacing: 10.0,
197 | crossAxisCount: 2,
198 | childAspectRatio: 4.0
199 | ),
200 | itemBuilder: (BuildContext context, int index) {
201 | return InkWell(
202 | onTap: (){
203 | setState(() {
204 | mSearchText=data[index].name;
205 | mShowSearchContent=true;
206 | _controller.text=mSearchText;
207 | });
208 | },
209 | child: Container(
210 | child: Row(
211 | mainAxisAlignment: MainAxisAlignment.start,
212 | crossAxisAlignment: CrossAxisAlignment.center,
213 | children: [
214 | Text((index+1).toString()+".",style: TextStyle(fontSize: 16.0,color: Color(0xFFFFB30A)),),
215 | Text(data[index].name,style: TextStyle(fontSize: 16.0,color: Color(0xFF333333)),),
216 | ],
217 | ),
218 | ),
219 | );
220 | },
221 | itemCount: data.length,
222 | );
223 | }
224 |
225 |
226 |
227 | Widget getHeadView(){
228 | return Column(
229 | children: [
230 | Container(
231 | height: 40.0,
232 | color: Color(0xFFF5F5F5),
233 | padding: EdgeInsets.only(left: 12.0,right: 12.0),
234 | child: Row(
235 | crossAxisAlignment: CrossAxisAlignment.center,
236 | children: [
237 | Expanded(
238 | flex: 5,
239 | child: Text('最近搜索',style: TextStyle(fontSize: 14.0,color: Color(0xFF999999)),)
240 | ),
241 | Expanded(
242 | flex: 1,
243 | child: InkWell(
244 | onTap: (){
245 | setState(() {
246 | historySearchList.clear();
247 | SpUtil.putStringList('historySearch', historySearchList);
248 | });
249 | },
250 | child: Text('清空记录',style: TextStyle(fontSize: 14.0,color: Color(0xFF999999)),),
251 | )
252 | )
253 | ],
254 | ),
255 | ),
256 | Column(
257 | mainAxisAlignment: MainAxisAlignment.start,
258 | crossAxisAlignment: CrossAxisAlignment.start,
259 | children: historySearchList.map((String history){
260 | return Column(
261 | crossAxisAlignment: CrossAxisAlignment.start,
262 | children: [
263 | Container(
264 | height: 40.0,
265 | color: Color(0xFFFFFFFF),
266 | padding: EdgeInsets.only(left: 12.0,right: 12.0),
267 | child: Row(
268 | crossAxisAlignment: CrossAxisAlignment.center,
269 | children: [
270 | Expanded(
271 | flex: 8,
272 | child: InkWell(
273 | onTap: (){
274 | setState(() {
275 | mSearchText=history;
276 | mShowSearchContent=true;
277 | _controller.text=mSearchText;
278 | });
279 | },
280 | child: Container(
281 | padding: EdgeInsets.only(top: 5.0,bottom: 5.0),
282 | child: Text(history,style: TextStyle(fontSize: 14.0,color: Color(0xFF333333)),),
283 | ),
284 | )
285 | ),
286 | Expanded(
287 | flex: 1,
288 | child: InkWell(
289 | onTap: (){
290 | setState(() {
291 | historySearchList.remove(history);
292 | });
293 | },
294 | child: Icon(
295 | Icons.clear,
296 | size: 18.0,
297 | color: Colors.grey,
298 | ),
299 | )
300 | )
301 | ],
302 | )
303 | ),
304 | Container(
305 | margin: EdgeInsets.only(left: 12.0,right: 12.0),
306 | child: Divider(height: 2.0,),
307 | )
308 | ],
309 | );
310 | }).toList(),
311 | )
312 | ],
313 | );
314 | }
315 |
316 | }
--------------------------------------------------------------------------------
/flutter_demo/lib/bean/BannerInfoResponse.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert' show json;
2 |
3 | class BannerInfoResponse {
4 |
5 | int result;
6 | String msg;
7 | List data;
8 |
9 | BannerInfoResponse.fromParams({this.result, this.msg, this.data});
10 |
11 | factory BannerInfoResponse(jsonStr) => jsonStr == null ? null : jsonStr is String ? new BannerInfoResponse.fromJson(json.decode(jsonStr)) : new BannerInfoResponse.fromJson(jsonStr);
12 |
13 | BannerInfoResponse.fromJson(jsonRes) {
14 | result = jsonRes['result'];
15 | msg = jsonRes['msg'];
16 | data = jsonRes['data'] == null ? null : [];
17 |
18 | for (var dataItem in data == null ? [] : jsonRes['data']){
19 | data.add(dataItem == null ? null : new DataBean.fromJson(dataItem));
20 | }
21 | }
22 |
23 | @override
24 | String toString() {
25 | return '{"result": $result,"msg": ${msg != null?'${json.encode(msg)}':'null'},"data": $data}';
26 | }
27 | }
28 |
29 | class DataBean {
30 |
31 | String redirctUrl;
32 | int flagId;
33 | String infoType;
34 | String pictureUrl;
35 | String redirectType;
36 |
37 | DataBean.fromParams({this.redirctUrl, this.flagId, this.infoType, this.pictureUrl, this.redirectType});
38 |
39 | DataBean.fromJson(jsonRes) {
40 | redirctUrl = jsonRes['redirctUrl'];
41 | flagId = jsonRes['flagId'];
42 | infoType = jsonRes['infoType'];
43 | pictureUrl = jsonRes['pictureUrl'];
44 | redirectType = jsonRes['redirectType'];
45 | }
46 |
47 | @override
48 | String toString() {
49 | return '{"redirctUrl": ${redirctUrl != null?'${json.encode(redirctUrl)}':'null'},"flagId": $flagId,"infoType": ${infoType != null?'${json.encode(infoType)}':'null'},"pictureUrl": ${pictureUrl != null?'${json.encode(pictureUrl)}':'null'},"redirectType": ${redirectType != null?'${json.encode(redirectType)}':'null'}}';
50 | }
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/flutter_demo/lib/bean/ChannelResponse.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert' show json;
2 |
3 | class ChannelResponse {
4 |
5 | int result;
6 | String msg;
7 | List data;
8 |
9 | ChannelResponse.fromParams({this.result, this.msg, this.data});
10 |
11 | factory ChannelResponse(jsonStr) => jsonStr == null ? null : jsonStr is String ? new ChannelResponse.fromJson(json.decode(jsonStr)) : new ChannelResponse.fromJson(jsonStr);
12 |
13 | ChannelResponse.fromJson(jsonRes) {
14 | result = jsonRes['result'];
15 | msg = jsonRes['msg'];
16 | data = jsonRes['data'] == null ? null : [];
17 |
18 | for (var dataItem in data == null ? [] : jsonRes['data']){
19 | data.add(dataItem == null ? null : new Channel.fromJson(dataItem));
20 | }
21 | }
22 |
23 | @override
24 | String toString() {
25 | return '{"result": $result,"msg": ${msg != null?'${json.encode(msg)}':'null'},"data": $data}';
26 | }
27 | }
28 |
29 | class Channel {
30 |
31 | int code;
32 | int sortIndex;
33 | bool isUserTag;
34 | String name;
35 |
36 | Channel.fromParams({this.code, this.sortIndex, this.isUserTag, this.name});
37 |
38 | Channel.fromJson(jsonRes) {
39 | code = jsonRes['code'];
40 | sortIndex = jsonRes['sortIndex'];
41 | isUserTag = jsonRes['isUserTag'];
42 | name = jsonRes['name'];
43 | }
44 |
45 | @override
46 | String toString() {
47 | return '{"code": $code,"sortIndex": $sortIndex,"isUserTag": $isUserTag,"name": ${name != null?'${json.encode(name)}':'null'}}';
48 | }
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/flutter_demo/lib/bean/FictionDetailResponse.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert' show json;
2 |
3 | class FictionDetailResponse {
4 |
5 | int result;
6 | String msg;
7 | FictionDetailBean data;
8 |
9 | FictionDetailResponse.fromParams({this.result, this.msg, this.data});
10 |
11 | factory FictionDetailResponse(jsonStr) => jsonStr == null ? null : jsonStr is String ? new FictionDetailResponse.fromJson(json.decode(jsonStr)) : new FictionDetailResponse.fromJson(jsonStr);
12 |
13 | FictionDetailResponse.fromJson(jsonRes) {
14 | result = jsonRes['result'];
15 | msg = jsonRes['msg'];
16 | data = jsonRes['data'] == null ? null : new FictionDetailBean.fromJson(jsonRes['data']);
17 | }
18 |
19 | @override
20 | String toString() {
21 | return '{"result": $result,"msg": ${msg != null?'${json.encode(msg)}':'null'},"data": $data}';
22 | }
23 | }
24 |
25 | class FictionDetailBean {
26 |
27 | int chapterCount;
28 | int commentCount;
29 | int id;
30 | int score;
31 | int wordCount;
32 | bool isFavorite;
33 | String author;
34 | String cp;
35 | String description;
36 | String lastChapter;
37 | String name;
38 | String picture;
39 | String state;
40 | List pushBookList;
41 | List tags;
42 | LastComment lastComment;
43 |
44 | FictionDetailBean.fromParams({this.chapterCount, this.commentCount, this.id, this.score, this.wordCount, this.isFavorite, this.author, this.cp, this.description, this.lastChapter, this.name, this.picture, this.state, this.pushBookList, this.tags, this.lastComment});
45 |
46 | FictionDetailBean.fromJson(jsonRes) {
47 | chapterCount = jsonRes['chapterCount'];
48 | commentCount = jsonRes['commentCount'];
49 | id = jsonRes['id'];
50 | score = jsonRes['score'];
51 | wordCount = jsonRes['wordCount'];
52 | isFavorite = jsonRes['isFavorite'];
53 | author = jsonRes['author'];
54 | cp = jsonRes['cp'];
55 | description = jsonRes['description'];
56 | lastChapter = jsonRes['lastChapter'];
57 | name = jsonRes['name'];
58 | picture = jsonRes['picture'];
59 | state = jsonRes['state'];
60 | pushBookList = jsonRes['pushBookList'] == null ? null : [];
61 |
62 | for (var pushBookListItem in pushBookList == null ? [] : jsonRes['pushBookList']){
63 | pushBookList.add(pushBookListItem == null ? null : new FictionPushBook.fromJson(pushBookListItem));
64 | }
65 |
66 | tags = jsonRes['tags'] == null ? null : [];
67 |
68 | for (var tagsItem in tags == null ? [] : jsonRes['tags']){
69 | tags.add(tagsItem);
70 | }
71 |
72 | lastComment = jsonRes['lastComment'] == null ? null : new LastComment.fromJson(jsonRes['lastComment']);
73 | }
74 |
75 | @override
76 | String toString() {
77 | return '{"chapterCount": $chapterCount,"commentCount": $commentCount,"id": $id,"score": $score,"wordCount": $wordCount,"isFavorite": $isFavorite,"author": ${author != null?'${json.encode(author)}':'null'},"cp": ${cp != null?'${json.encode(cp)}':'null'},"description": ${description != null?'${json.encode(description)}':'null'},"lastChapter": ${lastChapter != null?'${json.encode(lastChapter)}':'null'},"name": ${name != null?'${json.encode(name)}':'null'},"picture": ${picture != null?'${json.encode(picture)}':'null'},"state": ${state != null?'${json.encode(state)}':'null'},"pushBookList": $pushBookList,"tags": $tags,"lastComment": $lastComment}';
78 | }
79 | }
80 |
81 | class LastComment {
82 |
83 | int level;
84 | String comment;
85 | String userAvatar;
86 | String userName;
87 |
88 | LastComment.fromParams({this.level, this.comment, this.userAvatar, this.userName});
89 |
90 | LastComment.fromJson(jsonRes) {
91 | level = jsonRes['level'];
92 | comment = jsonRes['comment'];
93 | userAvatar = jsonRes['userAvatar'];
94 | userName = jsonRes['userName'];
95 | }
96 |
97 | @override
98 | String toString() {
99 | return '{"level": $level,"comment": ${comment != null?'${json.encode(comment)}':'null'},"userAvatar": ${userAvatar != null?'${json.encode(userAvatar)}':'null'},"userName": ${userName != null?'${json.encode(userName)}':'null'}}';
100 | }
101 | }
102 |
103 | class FictionPushBook {
104 |
105 | int id;
106 | String author;
107 | String name;
108 | String picture;
109 |
110 | FictionPushBook.fromParams({this.id, this.author, this.name, this.picture});
111 |
112 | FictionPushBook.fromJson(jsonRes) {
113 | id = jsonRes['id'];
114 | author = jsonRes['author'];
115 | name = jsonRes['name'];
116 | picture = jsonRes['picture'];
117 | }
118 |
119 | @override
120 | String toString() {
121 | return '{"id": $id,"author": ${author != null?'${json.encode(author)}':'null'},"name": ${name != null?'${json.encode(name)}':'null'},"picture": ${picture != null?'${json.encode(picture)}':'null'}}';
122 | }
123 | }
124 |
125 |
--------------------------------------------------------------------------------
/flutter_demo/lib/bean/FictionHomeInfoResponse.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert' show json;
2 |
3 | class FictionHomeInfoResponse {
4 |
5 | List other;
6 | HotPushResponse editerPush;
7 | HotPushResponse freeTime;
8 | HotPushResponse hotPush;
9 |
10 | FictionHomeInfoResponse.fromParams({this.other, this.editerPush, this.freeTime, this.hotPush});
11 |
12 | factory FictionHomeInfoResponse(jsonStr) => jsonStr == null ? null : jsonStr is String ? new FictionHomeInfoResponse.fromJson(json.decode(jsonStr)) : new FictionHomeInfoResponse.fromJson(jsonStr);
13 |
14 | FictionHomeInfoResponse.fromJson(jsonRes) {
15 | other = jsonRes['other'] == null ? null : [];
16 |
17 | for (var otherItem in other == null ? [] : jsonRes['other']){
18 | other.add(otherItem == null ? null : new HotPushResponse.fromJson(otherItem));
19 | }
20 |
21 | editerPush = jsonRes['editerPush'] == null ? null : new HotPushResponse.fromJson(jsonRes['editerPush']);
22 | freeTime = jsonRes['freeTime'] == null ? null : new HotPushResponse.fromJson(jsonRes['freeTime']);
23 | hotPush = jsonRes['hotPush'] == null ? null : new HotPushResponse.fromJson(jsonRes['hotPush']);
24 | }
25 |
26 | @override
27 | String toString() {
28 | return '{"other": $other,"editerPush": $editerPush,"freeTime": $freeTime,"hotPush": $hotPush}';
29 | }
30 | }
31 |
32 | class HotPushResponse{
33 | int result;
34 | String msg;
35 | String type;
36 | String title;
37 | List data;
38 |
39 | HotPushResponse.fromParams({this.result, this.msg, this.type, this.title, this.data});
40 |
41 | factory HotPushResponse(jsonStr) => jsonStr == null ? null : jsonStr is String ? new HotPushResponse.fromJson(json.decode(jsonStr)) : new HotPushResponse.fromJson(jsonStr);
42 |
43 | HotPushResponse.fromJson(jsonRes) {
44 | result = jsonRes['result'];
45 | msg = jsonRes['msg'];
46 | type = jsonRes['type'];
47 | title = jsonRes['title'];
48 | data = jsonRes['data'] == null ? null : [];
49 |
50 | for (var dataItem in data == null ? [] : jsonRes['data']){
51 | data.add(dataItem == null ? null : new FictionIntroduction.fromJson(dataItem));
52 | }
53 | }
54 |
55 | @override
56 | String toString() {
57 | return '{"result": $result,"msg": ${msg != null?'${json.encode(msg)}':'null'},"type": ${type != null?'${json.encode(type)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'},"data": $data}';
58 | }
59 |
60 | }
61 |
62 | class FictionIntroduction {
63 |
64 | int bookId;
65 | String author;
66 | String description;
67 | String name;
68 | String picture;
69 | String pushDescription;
70 |
71 | FictionIntroduction.fromParams({this.bookId, this.author, this.description, this.name, this.picture, this.pushDescription});
72 |
73 | FictionIntroduction.fromJson(jsonRes) {
74 | bookId = jsonRes['bookId'];
75 | author = jsonRes['author'];
76 | description = jsonRes['description'];
77 | name = jsonRes['name'];
78 | picture = jsonRes['picture'];
79 | pushDescription = jsonRes['pushDescription'];
80 | }
81 |
82 | @override
83 | String toString() {
84 | return '{"bookId": $bookId,"author": ${author != null?'${json.encode(author)}':'null'},"description": ${description != null?'${json.encode(description)}':'null'},"name": ${name != null?'${json.encode(name)}':'null'},"picture": ${picture != null?'${json.encode(picture)}':'null'},"pushDescription": ${pushDescription != null?'${json.encode(pushDescription)}':'null'}}';
85 | }
86 | }
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/flutter_demo/lib/bean/HotSearchResponse.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert' show json;
2 |
3 | class HotSearchResponse {
4 |
5 | int result;
6 | String msg;
7 | List data;
8 |
9 | HotSearchResponse.fromParams({this.result, this.msg, this.data});
10 |
11 | factory HotSearchResponse(jsonStr) => jsonStr == null ? null : jsonStr is String ? new HotSearchResponse.fromJson(json.decode(jsonStr)) : new HotSearchResponse.fromJson(jsonStr);
12 |
13 | HotSearchResponse.fromJson(jsonRes) {
14 | result = jsonRes['result'];
15 | msg = jsonRes['msg'];
16 | data = jsonRes['data'] == null ? null : [];
17 |
18 | for (var dataItem in data == null ? [] : jsonRes['data']){
19 | data.add(dataItem == null ? null : new HotSearchBean.fromJson(dataItem));
20 | }
21 | }
22 |
23 | @override
24 | String toString() {
25 | return '{"result": $result,"msg": ${msg != null?'${json.encode(msg)}':'null'},"data": $data}';
26 | }
27 | }
28 |
29 | class HotSearchBean {
30 |
31 | int code;
32 | String name;
33 |
34 | HotSearchBean.fromParams({this.code, this.name});
35 |
36 | HotSearchBean.fromJson(jsonRes) {
37 | code = jsonRes['code'];
38 | name = jsonRes['name'];
39 | }
40 |
41 | @override
42 | String toString() {
43 | return '{"code": $code,"name": ${name != null?'${json.encode(name)}':'null'}}';
44 | }
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/flutter_demo/lib/bean/NewsDetailResponse.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert' show json;
2 |
3 | class NewsDetailResponse {
4 |
5 | int result;
6 | String msg;
7 | NewsDetail data;
8 |
9 | NewsDetailResponse.fromParams({this.result, this.msg, this.data});
10 |
11 | factory NewsDetailResponse(jsonStr) => jsonStr == null ? null : jsonStr is String ? new NewsDetailResponse.fromJson(json.decode(jsonStr)) : new NewsDetailResponse.fromJson(jsonStr);
12 |
13 | NewsDetailResponse.fromJson(jsonRes) {
14 | result = jsonRes['result'];
15 | msg = jsonRes['msg'];
16 | data = jsonRes['data'] == null ? null : new NewsDetail.fromJson(jsonRes['data']);
17 | }
18 |
19 | @override
20 | String toString() {
21 | return '{"result": $result,"msg": ${msg != null?'${json.encode(msg)}':'null'},"data": $data}';
22 | }
23 | }
24 |
25 | class NewsDetail {
26 |
27 | int FPS;
28 | int addTime;
29 | int bitRate;
30 | int commentCount;
31 | int id;
32 | int likes;
33 | int readcount;
34 | int videoSize;
35 | bool enableComment;
36 | bool isFavorite;
37 | bool isNoneImg;
38 | String addTimeStr;
39 | String author;
40 | String content;
41 | String description;
42 | String src;
43 | String timeLong;
44 | String title;
45 | String videoSrc;
46 | String xcShareId;
47 | String xcSharePath;
48 | List pictureList;
49 | List tagList;
50 |
51 | NewsDetail.fromParams({this.FPS, this.addTime, this.bitRate, this.commentCount, this.id, this.likes, this.readcount, this.videoSize, this.enableComment, this.isFavorite, this.isNoneImg, this.addTimeStr, this.author, this.content, this.description, this.src, this.timeLong, this.title, this.videoSrc, this.xcShareId, this.xcSharePath, this.pictureList, this.tagList});
52 |
53 | NewsDetail.fromJson(jsonRes) {
54 | FPS = jsonRes['FPS'];
55 | addTime = jsonRes['addTime'];
56 | bitRate = jsonRes['bitRate'];
57 | commentCount = jsonRes['commentCount'];
58 | id = jsonRes['id'];
59 | likes = jsonRes['likes'];
60 | readcount = jsonRes['readcount'];
61 | videoSize = jsonRes['videoSize'];
62 | enableComment = jsonRes['enableComment'];
63 | isFavorite = jsonRes['isFavorite'];
64 | isNoneImg = jsonRes['isNoneImg'];
65 | addTimeStr = jsonRes['addTimeStr'];
66 | author = jsonRes['author'];
67 | content = jsonRes['content'];
68 | description = jsonRes['description'];
69 | src = jsonRes['src'];
70 | timeLong = jsonRes['timeLong'];
71 | title = jsonRes['title'];
72 | videoSrc = jsonRes['videoSrc'];
73 | xcShareId = jsonRes['xcShareId'];
74 | xcSharePath = jsonRes['xcSharePath'];
75 | pictureList = jsonRes['pictureList'] == null ? null : [];
76 |
77 | for (var pictureListItem in pictureList == null ? [] : jsonRes['pictureList']){
78 | pictureList.add(pictureListItem);
79 | }
80 |
81 | tagList = jsonRes['tagList'] == null ? null : [];
82 |
83 | for (var tagListItem in tagList == null ? [] : jsonRes['tagList']){
84 | tagList.add(tagListItem);
85 | }
86 | }
87 |
88 | @override
89 | String toString() {
90 | return '{"FPS": $FPS,"addTime": $addTime,"bitRate": $bitRate,"commentCount": $commentCount,"id": $id,"likes": $likes,"readcount": $readcount,"videoSize": $videoSize,"enableComment": $enableComment,"isFavorite": $isFavorite,"isNoneImg": $isNoneImg,"addTimeStr": ${addTimeStr != null?'${json.encode(addTimeStr)}':'null'},"author": ${author != null?'${json.encode(author)}':'null'},"content": ${content != null?'${json.encode(content)}':'null'},"description": ${description != null?'${json.encode(description)}':'null'},"src": ${src != null?'${json.encode(src)}':'null'},"timeLong": ${timeLong != null?'${json.encode(timeLong)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'},"videoSrc": ${videoSrc != null?'${json.encode(videoSrc)}':'null'},"xcShareId": ${xcShareId != null?'${json.encode(xcShareId)}':'null'},"xcSharePath": ${xcSharePath != null?'${json.encode(xcSharePath)}':'null'},"pictureList": $pictureList,"tagList": $tagList}';
91 | }
92 | }
93 |
94 |
--------------------------------------------------------------------------------
/flutter_demo/lib/bean/NewsResData.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert' show json;
2 |
3 | class NewsResData {
4 |
5 | int result;
6 | String msg;
7 | NewsObject data;
8 |
9 | NewsResData.fromParams({this.result, this.msg, this.data});
10 |
11 | factory NewsResData(jsonStr) => jsonStr == null ? null : jsonStr is String ? new NewsResData.fromJson(json.decode(jsonStr)) : new NewsResData.fromJson(jsonStr);
12 |
13 | NewsResData.fromJson(jsonRes) {
14 | result = jsonRes['result'];
15 | msg = jsonRes['msg'];
16 | data = jsonRes['data'] == null ? null : new NewsObject.fromJson(jsonRes['data']);
17 | }
18 |
19 | @override
20 | String toString() {
21 | return '{"result": $result,"msg": ${msg != null?'${json.encode(msg)}':'null'},"data": $data}';
22 | }
23 | }
24 |
25 | class NewsObject {
26 |
27 | String search;
28 | Object toplist;
29 | int currentindex;
30 | int currentpage;
31 | int lasttime;
32 | int tag;
33 | List list;
34 |
35 | NewsObject.fromParams({this.search, this.toplist, this.currentindex, this.currentpage, this.lasttime, this.tag, this.list});
36 |
37 | NewsObject.fromJson(jsonRes) {
38 | search = jsonRes['search'];
39 | toplist = jsonRes['toplist'];
40 | currentindex = jsonRes['currentindex'];
41 | currentpage = jsonRes['currentpage'];
42 | lasttime = jsonRes['lasttime'];
43 | tag = jsonRes['tag'];
44 | list = jsonRes['list'] == null ? null : [];
45 |
46 | for (var listItem in list == null ? [] : jsonRes['list']){
47 | list.add(listItem == null ? null : new News.fromJson(listItem));
48 | }
49 | }
50 |
51 | @override
52 | String toString() {
53 | return '{"search": ${search != null?'${json.encode(search)}':'null'},"toplist": $toplist,"currentindex": $currentindex,"currentpage": $currentpage,"lasttime": $lasttime,"tag": $tag,"list": $list}';
54 | }
55 | }
56 |
57 | class News {
58 |
59 | int addTime;
60 | int commentCount;
61 | int flagId;
62 | int id;
63 | int likes;
64 | int pictureCount;
65 | int readcount;
66 | bool isBigIcon;
67 | bool isHot;
68 | bool isSpecial;
69 | bool isTop;
70 | String author;
71 | String description;
72 | String infoType;
73 | String redirectType;
74 | String src;
75 | String timeLong;
76 | String title;
77 | List pictureList;
78 |
79 | News.fromParams({this.addTime, this.commentCount, this.flagId, this.id, this.likes, this.pictureCount, this.readcount, this.isBigIcon, this.isHot, this.isSpecial, this.isTop, this.author, this.description, this.infoType, this.redirectType, this.src, this.timeLong, this.title, this.pictureList});
80 |
81 | News.fromJson(jsonRes) {
82 | addTime = jsonRes['addTime'];
83 | commentCount = jsonRes['commentCount'];
84 | flagId = jsonRes['flagId'];
85 | id = jsonRes['id'];
86 | likes = jsonRes['likes'];
87 | pictureCount = jsonRes['pictureCount'];
88 | readcount = jsonRes['readcount'];
89 | isBigIcon = jsonRes['isBigIcon'];
90 | isHot = jsonRes['isHot'];
91 | isSpecial = jsonRes['isSpecial'];
92 | isTop = jsonRes['isTop'];
93 | author = jsonRes['author'];
94 | description = jsonRes['description'];
95 | infoType = jsonRes['infoType'];
96 | redirectType = jsonRes['redirectType'];
97 | src = jsonRes['src'];
98 | timeLong = jsonRes['timeLong'];
99 | title = jsonRes['title'];
100 | pictureList = jsonRes['pictureList'] == null ? null : [];
101 |
102 | for (var pictureListItem in pictureList == null ? [] : jsonRes['pictureList']){
103 | pictureList.add(pictureListItem);
104 | }
105 | }
106 |
107 | @override
108 | String toString() {
109 | return '{"addTime": $addTime,"commentCount": $commentCount,"flagId": $flagId,"id": $id,"likes": $likes,"pictureCount": $pictureCount,"readcount": $readcount,"isBigIcon": $isBigIcon,"isHot": $isHot,"isSpecial": $isSpecial,"isTop": $isTop,"author": ${author != null?'${json.encode(author)}':'null'},"description": ${description != null?'${json.encode(description)}':'null'},"infoType": ${infoType != null?'${json.encode(infoType)}':'null'},"redirectType": ${redirectType != null?'${json.encode(redirectType)}':'null'},"src": ${src != null?'${json.encode(src)}':'null'},"timeLong": ${timeLong != null?'${json.encode(timeLong)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'},"pictureList": $pictureList}';
110 | }
111 | }
112 |
113 |
--------------------------------------------------------------------------------
/flutter_demo/lib/bean/RelativeInfoResponse.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert' show json;
2 |
3 | class RelativeInfoResponse {
4 |
5 | int result;
6 | String msg;
7 | List data;
8 |
9 | RelativeInfoResponse.fromParams({this.result, this.msg, this.data});
10 |
11 | factory RelativeInfoResponse(jsonStr) => jsonStr == null ? null : jsonStr is String ? new RelativeInfoResponse.fromJson(json.decode(jsonStr)) : new RelativeInfoResponse.fromJson(jsonStr);
12 |
13 | RelativeInfoResponse.fromJson(jsonRes) {
14 | result = jsonRes['result'];
15 | msg = jsonRes['msg'];
16 | data = jsonRes['data'] == null ? null : [];
17 |
18 | for (var dataItem in data == null ? [] : jsonRes['data']){
19 | data.add(dataItem == null ? null : new RelativeNews.fromJson(dataItem));
20 | }
21 | }
22 |
23 | @override
24 | String toString() {
25 | return '{"result": $result,"msg": ${msg != null?'${json.encode(msg)}':'null'},"data": $data}';
26 | }
27 | }
28 |
29 | class RelativeNews {
30 |
31 | int addTime;
32 | int commentCount;
33 | int id;
34 | int likes;
35 | String author;
36 | String description;
37 | String infoType;
38 | String src;
39 | String timeLong;
40 | String title;
41 | List pictureList;
42 | List tagList;
43 |
44 | RelativeNews.fromParams({this.addTime, this.commentCount, this.id, this.likes, this.author, this.description, this.infoType, this.src, this.timeLong, this.title, this.pictureList, this.tagList});
45 |
46 | RelativeNews.fromJson(jsonRes) {
47 | addTime = jsonRes['addTime'];
48 | commentCount = jsonRes['commentCount'];
49 | id = jsonRes['id'];
50 | likes = jsonRes['likes'];
51 | author = jsonRes['author'];
52 | description = jsonRes['description'];
53 | infoType = jsonRes['infoType'];
54 | src = jsonRes['src'];
55 | timeLong = jsonRes['timeLong'];
56 | title = jsonRes['title'];
57 | pictureList = jsonRes['pictureList'] == null ? null : [];
58 |
59 | for (var pictureListItem in pictureList == null ? [] : jsonRes['pictureList']){
60 | pictureList.add(pictureListItem);
61 | }
62 |
63 | tagList = jsonRes['tagList'] == null ? null : [];
64 |
65 | for (var tagListItem in tagList == null ? [] : jsonRes['tagList']){
66 | tagList.add(tagListItem);
67 | }
68 | }
69 |
70 | @override
71 | String toString() {
72 | return '{"addTime": $addTime,"commentCount": $commentCount,"id": $id,"likes": $likes,"author": ${author != null?'${json.encode(author)}':'null'},"description": ${description != null?'${json.encode(description)}':'null'},"infoType": ${infoType != null?'${json.encode(infoType)}':'null'},"src": ${src != null?'${json.encode(src)}':'null'},"timeLong": ${timeLong != null?'${json.encode(timeLong)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'},"pictureList": $pictureList,"tagList": $tagList}';
73 | }
74 | }
75 |
76 |
--------------------------------------------------------------------------------
/flutter_demo/lib/channelView.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_demo/NewsDetailPageView.dart';
3 | import 'package:flutter_demo/view/NewDetailWebview.dart';
4 | import 'bean/ChannelResponse.dart';
5 | import 'bean/NewsResData.dart';
6 | import 'controller/HttpController.dart';
7 | import 'news_detail_page.dart';
8 | import 'videoListPage.dart';
9 |
10 | class NewsListView extends StatefulWidget{
11 | final String mChannelCode;
12 | final String mSearchText;
13 | NewsListView({this.mChannelCode,this.mSearchText});
14 |
15 | @override
16 | State createState() {
17 | // TODO: implement createState
18 | return new NewsListViewState();
19 | }
20 |
21 | }
22 |
23 | class NewsListViewState extends State with AutomaticKeepAliveClientMixin{
24 |
25 | HttpController mHttpController;
26 | NewsResData mNewsResData;
27 | List mNewsList = [];
28 | Map newsDataMap=new Map();
29 | ScrollController _scrollController=new ScrollController();
30 | bool isLoadMore=false;//是否正在加载更多数据
31 | bool isFirstLoadData=true; //是否是第一次加载数据
32 |
33 | @override
34 | void initState() {
35 | // TODO: implement initState
36 | super.initState();
37 | assert(widget.mChannelCode!=null);
38 | mHttpController=new HttpController();
39 | getData(widget.mChannelCode,widget.mSearchText,2,0);
40 | _scrollController.addListener((){
41 | if(_scrollController.position.pixels == _scrollController.position.maxScrollExtent){
42 | if(!isLoadMore && mNewsList.length>1){
43 | setState(() {
44 | isLoadMore=true;
45 | });
46 | getData(widget.mChannelCode,widget.mSearchText,mNewsResData.data.currentpage,mNewsResData.data.currentindex);
47 | }
48 |
49 | }
50 | });
51 | }
52 |
53 | @override
54 | Widget build(BuildContext context) {
55 | // TODO: implement build
56 | return layout(context);
57 | }
58 |
59 | Widget layout(BuildContext context){
60 | if(isFirstLoadData){
61 | return Center(
62 | child: CircularProgressIndicator(
63 | backgroundColor: Colors.blue,
64 | strokeWidth: 4,
65 | )
66 | );
67 | }else{
68 | return Container(
69 | child: RefreshIndicator(
70 | child: ListView.builder(itemCount:mNewsList.length,itemBuilder: itemView,controller: _scrollController,padding: EdgeInsets.only(top: 0.0), ),
71 | onRefresh: _onRefresh),
72 | );
73 | }
74 | }
75 |
76 |
77 | Future _onRefresh() async{
78 | if(mNewsResData!=null){
79 | await getData(widget.mChannelCode,widget.mSearchText,mNewsResData.data.currentpage,mNewsResData.data.currentindex);
80 | }
81 | }
82 |
83 | void getData(String tag,String searchText,int page,int currentIndex) async{
84 | Map dataMap = new Map();
85 | dataMap["tag"]=tag;
86 | dataMap["search"]=searchText;
87 | dataMap["page"]=page.toString();
88 | dataMap["currentindex"]=currentIndex.toString();
89 | await mHttpController.getNewsList("https://app.tenyou0574.com/App/Info/InfoList",(data){
90 | if(data!=null){
91 | setState(() {
92 | isLoadMore=false;
93 | isFirstLoadData=false;
94 | mNewsResData=data;
95 | mNewsList.addAll(mNewsResData.data.list);
96 | for(News news in mNewsResData.data.list){
97 | newsDataMap[news.id]=news;
98 | }
99 | });
100 | }
101 | },params: dataMap);
102 | }
103 |
104 | Route _getRoute(RouteSettings settings) {
105 | // Routes, by convention, are split on slashes, like filesystem paths.
106 | final List path = settings.name.split('/');
107 | if (path[0] != '')
108 | return null;
109 | if (path[1].startsWith('newsDetail:')) {
110 | if (path.length != 3)
111 | return null;
112 | final String infoId = path[1].substring(11);
113 | final String index = path[2];
114 | return MaterialPageRoute(
115 | settings: settings,
116 | builder: (BuildContext context) => NewsDetailPage(mNews:mNewsList[int.parse(index)]),
117 | );
118 | }
119 | // The other paths we support are in the routes table.
120 | return null;
121 | }
122 |
123 |
124 | Widget itemView(BuildContext context,int index){
125 | News news=this.mNewsList[index];
126 |
127 | if(news.pictureList==null){
128 | return Expanded(child: Text(news.title));
129 | }
130 |
131 | if(news.pictureList.length>=1 && news.pictureList.length<3){
132 | return InkWell(
133 | onTap: (){
134 | // Navigator.pushNamed(context, '/newsDetail:${news.id}/${index}');
135 | Navigator.push(
136 | context,
137 | MaterialPageRoute(builder: (context){
138 | if(news.infoType=="Article"){
139 | return NewsDetailPage(mNews:mNewsList[index]);
140 | // return NewsDetailPageView(mNews:mNewsList[index]);
141 | }else{
142 | return VideoListPage(mNews:mNewsList[index]);
143 | }
144 | })
145 | );
146 | },
147 | child: Column(
148 | crossAxisAlignment: CrossAxisAlignment.start,
149 | children: [
150 | Container(
151 | padding: EdgeInsets.all(10.0),
152 | child: Text(news.title,style: TextStyle(
153 | fontSize: 16.0
154 | ),),
155 | ),
156 | Row(
157 | mainAxisAlignment: MainAxisAlignment.start,
158 | children: [
159 | Expanded(
160 | child: Container(
161 | padding: EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
162 | child: Image.network(news.pictureList[0],height: 199.0,fit: BoxFit.cover,) ,
163 | ),
164 | ),
165 | ],
166 | ),
167 | Container(
168 | margin: EdgeInsets.only(top: 8.0),
169 | child: Divider(height: 2.0,),
170 | ),
171 |
172 | ],
173 | ),
174 | );
175 | }
176 |
177 | if(news.pictureList.length>=3){
178 | return InkWell(
179 | onTap: (){
180 | // Navigator.pushNamed(context, '/newsDetail:${news.id}/${index}');
181 | Navigator.push(
182 | context,
183 | MaterialPageRoute(builder: (context){
184 | if(news.infoType=="Article"){
185 | return NewsDetailPage(mNews:mNewsList[index]);
186 | // return NewsDetailPageView(mNews:mNewsList[index]);
187 | }else{
188 | return VideoListPage(mNews:mNewsList[index]);
189 | }
190 | })
191 | );
192 | },
193 | child: Column(
194 | crossAxisAlignment: CrossAxisAlignment.start,
195 | children: [
196 | Container(
197 | padding: EdgeInsets.all(10.0),
198 | child: Text(news.title,style: TextStyle(
199 | fontSize: 16.0,
200 | ),),
201 | ),
202 | Container(
203 | padding: EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
204 | child: Row(
205 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
206 | children: [
207 | Expanded(
208 | flex: 1,
209 | child: Container(
210 | margin: EdgeInsets.only(right: 5.0),
211 | child: Image.network(news.pictureList[0],height: 78.0,fit: BoxFit.cover,) ,
212 | )
213 | ),
214 | Expanded(
215 | flex: 1,
216 | child: Container(
217 | margin: EdgeInsets.only(right: 5.0),
218 | child: Image.network(news.pictureList[1],height: 78.0,fit: BoxFit.cover,) ,
219 | )
220 | ),
221 | Expanded(
222 | flex: 1,
223 | child: Image.network(news.pictureList[2],height: 78.0,fit: BoxFit.cover,) ,
224 | ),
225 | ],
226 | )
227 | ),
228 | Container(
229 | margin: EdgeInsets.only(top: 8.0),
230 | child: Divider(height: 2.0,),
231 | ),
232 | ],
233 | ),
234 | );
235 | }
236 | }
237 |
238 | @override
239 | void dispose() {
240 | // TODO: implement dispose
241 | super.dispose();
242 | _scrollController.dispose();
243 | }
244 |
245 | @override
246 | // TODO: implement wantKeepAlive
247 | bool get wantKeepAlive => true;
248 | }
--------------------------------------------------------------------------------
/flutter_demo/lib/controller/HttpController.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:flutter_demo/bean/HotSearchResponse.dart';
3 | import 'dart:async';
4 | import 'package:flutter_demo/bean/NewsResData.dart';
5 | import 'package:flutter_demo/bean/ChannelResponse.dart';
6 | import 'package:flutter_demo/bean/RelativeInfoResponse.dart';
7 | import 'package:flutter_demo/bean/BannerInfoResponse.dart';
8 | import 'package:flutter_demo/bean/FictionHomeInfoResponse.dart';
9 | import 'package:flutter_demo/bean/NewsDetailResponse.dart';
10 | import 'package:flutter_demo/bean/FictionDetailResponse.dart';
11 |
12 | class HttpController{
13 | Dio dio;
14 | HttpController(){
15 | dio=new Dio();
16 | }
17 | void getNewsList(String url,Function callBack,{Map params,Function errorCallback}){
18 | dio.get(url,data: params).then((Response response){
19 | print(response.data.toString());
20 | NewsResData newsResData=new NewsResData.fromJson(response.data);
21 | if(newsResData.result==200){
22 | callBack(newsResData);
23 | print("数据大小="+newsResData.data.list.length.toString());
24 | }
25 | });
26 | }
27 |
28 | //获取channel频道
29 | void getChannelList(Function callBack,{Function errorCallBack}){
30 | dio.get("https://app.tenyou0574.com/App/Info/GetDefaultTags").then((Response response){
31 | try {
32 | ChannelResponse channelResponse=new ChannelResponse.fromJson(response.data);
33 | if(channelResponse.result==200){
34 | callBack(channelResponse.data);
35 | }else{
36 | errorCallBack(channelResponse.msg);
37 | }
38 | } catch (e) {
39 | errorCallBack(e.toString());
40 | }
41 | });
42 | }
43 |
44 | void getRelativeInfo(int infoId,Function callBack,{Function errorCallBack}) {
45 | Map dataMap=new Map();
46 | dataMap["id"]=infoId.toString();
47 | dio.get("https://app.tenyou0574.com/App/Info/GetRelationInfo",data: dataMap).then((Response response){
48 | RelativeInfoResponse relativeInfoResponse=new RelativeInfoResponse.fromJson(response.data);
49 | if(relativeInfoResponse.result==200){
50 | RelativeNews relativeNews=new RelativeNews.fromParams(infoType: "videoTitle");
51 | relativeInfoResponse.data.insert(0, relativeNews);
52 | callBack(relativeInfoResponse);
53 | }else{
54 | errorCallBack(relativeInfoResponse.msg);
55 | }
56 | });
57 | }
58 |
59 | void getNewsDetail(int infoId,Function callBack,{Function errorCallBack}){
60 | Map dataMap=new Map();
61 | dataMap["id"]=infoId.toString();
62 | dio.get("https://app.tenyou0574.com/App/Info/GetDetailInfo",data: dataMap).then((Response response){
63 | NewsDetailResponse newsDetailResponse=new NewsDetailResponse.fromJson(response.data);
64 | if(newsDetailResponse.result==200){
65 | callBack(newsDetailResponse.data);
66 | print("NewsDetailResponse="+newsDetailResponse.toString());
67 | }else{
68 | errorCallBack(newsDetailResponse.msg);
69 | }
70 | });
71 | }
72 |
73 | Future> getBannerInfo(String type,{Function errorCallBack}) async{
74 | Map dataMap=new Map();
75 | dataMap["type"]=type;
76 | /*await dio.get("https://app.tenyou0574.com/App/Common/GetBannerInfo",data: dataMap).then((Response response){
77 | BannerInfoResponse bannerInfoResponse=new BannerInfoResponse.fromJson(response.data);
78 | return bannerInfoResponse.data;
79 | });*/
80 | Response response=await dio.get("https://app.tenyou0574.com/App/Common/GetBannerInfo",data: dataMap);
81 | BannerInfoResponse bannerInfoResponse=new BannerInfoResponse.fromJson(response.data);
82 | return bannerInfoResponse.data;
83 | }
84 |
85 | //获取小说首页内容
86 | Future getFictionHomePageInfo () async{
87 | Response response=await dio.get("https://app.tenyou0574.com/App/Book/HomePageBook");
88 | FictionHomeInfoResponse fictionHomeInfoResponse=new FictionHomeInfoResponse.fromJson(response.data);
89 | return fictionHomeInfoResponse;
90 | }
91 |
92 | void getReplaceFiction(String type,Function callBack,{Function errorCallBack}) {
93 | Map dataMap=new Map();
94 | dataMap["type"]=type;
95 | dio.get("https://app.tenyou0574.com/App/Book/GetOtherPush",data: dataMap).then((Response response){
96 | HotPushResponse replacePushResponse=new HotPushResponse.fromJson(response.data);
97 | if(replacePushResponse.result==200){
98 | callBack(replacePushResponse);
99 | }else{
100 | errorCallBack(replacePushResponse.msg);
101 | }
102 | });
103 | }
104 |
105 | Future getFictionDetail(int fictionId) async{
106 | Map dataMap=new Map();
107 | dataMap["bookid"]=fictionId.toString();
108 | Response response=await dio.get("https://app.tenyou0574.com/App/Book/GetBookDetail",data: dataMap);
109 | FictionDetailResponse fictionDetailResponse =FictionDetailResponse.fromJson(response.data);
110 | return fictionDetailResponse;
111 | }
112 |
113 | //获取所搜热词
114 | Future getHotSearchKeyWord () async{
115 | Response response=await dio.get("https://app.tenyou0574.com/App/Info/GetHotSearchKeyWord");
116 | HotSearchResponse hotSearchResponse=new HotSearchResponse.fromJson(response.data);
117 | /* HotSearchBean hotSearchBean=HotSearchBean.fromParams(code: -1,name: "热门搜索");
118 | hotSearchResponse.data.insert(0, hotSearchBean);*/
119 | return hotSearchResponse;
120 | }
121 |
122 | }
--------------------------------------------------------------------------------
/flutter_demo/lib/fiction/mainFiction.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_swiper/flutter_swiper.dart';
3 | import 'package:flutter_demo/controller/HttpController.dart';
4 | import 'package:flutter_demo/bean/BannerInfoResponse.dart';
5 | import 'package:flutter_demo/bean/FictionHomeInfoResponse.dart';
6 | import 'package:flutter_demo/FictionManFeatured.dart';
7 | import 'package:flutter_demo/FictionDetailPage.dart';
8 |
9 | class mainFiction extends StatefulWidget{
10 |
11 | @override
12 | State createState() {
13 | // TODO: implement createState
14 | return new mainFictionState();
15 | }
16 | }
17 |
18 | class mainFictionState extends State with AutomaticKeepAliveClientMixin{
19 | HttpController mHttpController;
20 |
21 | @override
22 | void initState() {
23 | // TODO: implement initState
24 | super.initState();
25 | mHttpController=new HttpController();
26 | }
27 |
28 | @override
29 | Widget build(BuildContext context) {
30 | // TODO: implement build
31 | return Theme(
32 | data: ThemeData(
33 | primaryColor: Colors.white
34 | ),
35 | child: Scaffold(
36 | appBar: AppBar(
37 | leading: Container(
38 | padding: EdgeInsets.only(left: 10.0),
39 | child: ClipOval(
40 | child: Image.asset('images/fiction_header_icon.png'),
41 | )
42 | ),
43 | title: DecoratedBox(
44 | decoration: BoxDecoration(
45 | color: Color.fromARGB(150, 235, 235, 235),
46 | borderRadius: BorderRadius.circular(20.0),
47 | border: Border.all(color: Color(0xFFC90E),width: 1.0)
48 | ),
49 | child: Row(
50 | mainAxisSize: MainAxisSize.min,
51 | mainAxisAlignment: MainAxisAlignment.start,
52 | crossAxisAlignment: CrossAxisAlignment.center,
53 | children: [
54 | Padding(
55 | padding: EdgeInsets.only(left: 10.0),
56 | child: Image.asset('images/icon_function_search.png',width: 14.0,height: 14.0,),
57 | ),
58 | Padding(
59 | padding: EdgeInsets.fromLTRB(10.0, 5.0, 100.0, 5.0),
60 | child: Text('搜索书名或者作者名',style: TextStyle(fontSize: 14.0,color: Colors.black),),
61 | )
62 | ],
63 | ),
64 | ),
65 | ),
66 |
67 | body: ListView(
68 | children: [
69 | getHeadView(),
70 | FutureBuilder(
71 | future: mHttpController.getFictionHomePageInfo(),
72 | builder: (BuildContext context, AsyncSnapshot snapshot){
73 | switch (snapshot.connectionState) {
74 | case ConnectionState.waiting:
75 | return Center(
76 | child: CircularProgressIndicator(),
77 | );
78 | case ConnectionState.done:
79 | if (snapshot.hasError) return Text('Error: ${snapshot.error}');
80 | return getFictionHomeContent(snapshot.data);
81 | default:
82 | return null;
83 | }
84 | }
85 | ),
86 | ],
87 | )
88 | ),
89 | );
90 | }
91 |
92 | Widget getHeadView(){
93 | return Column(
94 | crossAxisAlignment: CrossAxisAlignment.start,
95 | children: [
96 | Container(
97 | width: MediaQuery.of(context).size.width,
98 | height: 142.0,
99 | child: FutureBuilder>(
100 | future: mHttpController.getBannerInfo('BookTop'),
101 | builder: _buildFuture
102 | ),
103 | ),
104 | Padding(
105 | padding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
106 | child: Row(
107 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
108 | crossAxisAlignment: CrossAxisAlignment.center,
109 | children: [
110 | Column(
111 | mainAxisSize: MainAxisSize.min,
112 | crossAxisAlignment: CrossAxisAlignment.center,
113 | children: [
114 | Image.asset('images/fiction_1.png',width: 42.0,height: 42.0,),
115 | Padding(
116 | padding: EdgeInsets.only(top: 3.0),
117 | child: Text('书架',style: TextStyle(fontSize: 14.0,color: Color(0xFF333333)),),
118 | )
119 | ],
120 | ),
121 | Column(
122 | mainAxisSize: MainAxisSize.min,
123 | crossAxisAlignment: CrossAxisAlignment.center,
124 | children: [
125 | Image.asset('images/fiction_2.png',width: 42.0,height: 42.0,),
126 | Padding(
127 | padding: EdgeInsets.only(top: 3.0),
128 | child: Text('排行',style: TextStyle(fontSize: 14.0,color: Color(0xFF333333)),),
129 | )
130 | ],
131 | ),
132 | Column(
133 | mainAxisSize: MainAxisSize.min,
134 | crossAxisAlignment: CrossAxisAlignment.center,
135 | children: [
136 | Image.asset('images/fiction_3.png',width: 42.0,height: 42.0,),
137 | Padding(
138 | padding: EdgeInsets.only(top: 3.0),
139 | child: Text('专题',style: TextStyle(fontSize: 14.0,color: Color(0xFF333333)),),
140 | )
141 | ],
142 | ),
143 | Column(
144 | mainAxisSize: MainAxisSize.min,
145 | crossAxisAlignment: CrossAxisAlignment.center,
146 | children: [
147 | Image.asset('images/fiction_4.png',width: 42.0,height: 42.0,),
148 | Padding(
149 | padding: EdgeInsets.only(top: 3.0),
150 | child: Text('书库',style: TextStyle(fontSize: 14.0,color: Color(0xFF333333)),),
151 | )
152 | ],
153 | ),
154 | ],
155 | ),
156 | ),
157 | Container(
158 | height: 15.0,
159 | color: Color.fromARGB(150, 235, 235, 235),
160 | )
161 |
162 | ],
163 | );
164 | }
165 |
166 | ///snapshot就是_calculation在时间轴上执行过程的状态快照
167 | Widget _buildFuture(BuildContext context, AsyncSnapshot snapshot) {
168 | switch (snapshot.connectionState) {
169 | case ConnectionState.none:
170 | print('还没有开始网络请求');
171 | return Text('还没有开始网络请求');
172 | case ConnectionState.active:
173 | print('active');
174 | return Text('ConnectionState.active');
175 | case ConnectionState.waiting:
176 | print('waiting');
177 | return Center(
178 | child: CircularProgressIndicator(),
179 | );
180 | case ConnectionState.done:
181 | print('done');
182 | if (snapshot.hasError) return Text('Error: ${snapshot.error}');
183 | return getBannerView(snapshot.data);
184 | default:
185 | return null;
186 | }
187 | }
188 |
189 | Widget getBannerView(List banners){
190 | return Swiper(
191 | itemCount: banners.length,
192 | itemBuilder: (context,index){
193 | return Image.network(banners[index].pictureUrl,fit:BoxFit.fill);
194 | },
195 | pagination: new SwiperPagination(
196 | builder: DotSwiperPaginationBuilder(
197 | color: Colors.black54,
198 | activeColor: Colors.white,
199 | )),
200 | control: new SwiperControl(),
201 | scrollDirection: Axis.horizontal,
202 | autoplay: true,
203 | onTap: (index) => print('点击了第$index个'),
204 | );
205 | }
206 |
207 | Widget getFictionHomeContent(FictionHomeInfoResponse response){
208 | List hotPushLists=response.hotPush.data;
209 | List editPushLists=response.editerPush.data;
210 | List manLists=response.other[0].data;
211 | List girlLists=response.other[1].data;
212 | return Container(
213 | padding: EdgeInsets.all(10.0),
214 | child: Column(
215 | crossAxisAlignment: CrossAxisAlignment.start,
216 | children: [
217 | getHotPushWidgets(hotPushLists),
218 | getEditPushWidgets(editPushLists),
219 | FictionManFeatured(manLists:manLists,isMan: true,),
220 | FictionManFeatured(manLists:girlLists,isMan: false,),
221 | ],
222 | ),
223 | );
224 | }
225 |
226 | //获取热门推荐
227 | Widget getHotPushWidgets(List hotPushLists){
228 | return Column(
229 | crossAxisAlignment: CrossAxisAlignment.start,
230 | children: [
231 | Text('热门精选',style: TextStyle(fontSize: 16.0,color: Colors.black,fontWeight: FontWeight.bold),),
232 | getFictionDetailStyle(hotPushLists[0]),
233 | Container(
234 | padding: EdgeInsets.only(top: 10.0),
235 | child: Row(
236 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
237 | children: hotPushLists.sublist(1,4).map((FictionIntroduction fictionIntroduction){
238 | return getFictionNormalStyle(fictionIntroduction);
239 | }).toList(),
240 | ),
241 | ),
242 | Container(
243 | margin: EdgeInsets.only(top: 10.0),
244 | height: 15.0,
245 | color: Color.fromARGB(150, 235, 235, 235),
246 | )
247 |
248 | ],
249 | );
250 | }
251 |
252 | //获取主编力推
253 | Widget getEditPushWidgets(List editPushLists){
254 | return Column(
255 | crossAxisAlignment: CrossAxisAlignment.start,
256 | children: [
257 | Container(
258 | padding: EdgeInsets.only(top: 10.0),
259 | child: Text('主编力推',style: TextStyle(fontSize: 16.0,color: Colors.black,fontWeight: FontWeight.bold),),
260 | ),
261 | Column(
262 | crossAxisAlignment: CrossAxisAlignment.start,
263 | children: editPushLists.map((FictionIntroduction fictionIntroduction){
264 | return getFictionDetailStyle(fictionIntroduction);
265 | }).toList(),
266 | ),
267 | Container(
268 | margin: EdgeInsets.only(top: 10.0),
269 | height: 15.0,
270 | color: Color.fromARGB(150, 235, 235, 235),
271 | )
272 | ],
273 | );
274 | }
275 |
276 | Widget getFictionDetailStyle(FictionIntroduction fictionIntroduction){
277 | return InkWell(
278 | onTap: (){
279 | Navigator.push(context,
280 | MaterialPageRoute(builder: (context){
281 | return FictionDetailPage(fictionId : fictionIntroduction.bookId);
282 | // return ImagePickerPage();
283 | // return ScannerPage();
284 | }));
285 | },
286 | child: Container(
287 | padding: EdgeInsets.only(top: 10.0),
288 | child: Row(
289 | mainAxisAlignment: MainAxisAlignment.start,
290 | crossAxisAlignment: CrossAxisAlignment.center,
291 | children: [
292 | Image.network(fictionIntroduction.picture,width: 90.0,height: 120.0,),
293 | Expanded(
294 | child: Container(
295 | padding: EdgeInsets.only(left: 10.0),
296 | child: Column(
297 | mainAxisSize: MainAxisSize.min,
298 | mainAxisAlignment: MainAxisAlignment.start,
299 | crossAxisAlignment: CrossAxisAlignment.start,
300 | children: [
301 | Text(fictionIntroduction.name,style: TextStyle(fontSize: 16.0,color: Colors.black,fontWeight: FontWeight.w500),),
302 | Container(
303 | padding: EdgeInsets.only(top: 15.0,bottom: 15.0),
304 | child: Text(fictionIntroduction.description,style: TextStyle(fontSize: 14.0,color: Color(0xFF999999)),maxLines: 2,overflow: TextOverflow.ellipsis,),
305 | ),
306 |
307 | Row(
308 | mainAxisSize: MainAxisSize.min,
309 | mainAxisAlignment: MainAxisAlignment.start,
310 | children: [
311 | Image.asset('images/fiction_author.png',width: 18.0,height: 18.0,),
312 | Container(
313 | padding: EdgeInsets.only(left: 10.0),
314 | child: Text(fictionIntroduction.author,style: TextStyle(fontSize: 14.0,color: Color(0xFF999999))),
315 | )
316 | ],
317 | )
318 | ],
319 | ),
320 | )
321 | ),
322 |
323 | ],
324 | ),
325 | ),
326 | );
327 | }
328 |
329 | Widget getFictionNormalStyle(FictionIntroduction fictionIntroduction){
330 | return InkWell(
331 | onTap: (){
332 | Navigator.push(context,
333 | MaterialPageRoute(builder: (context){
334 | return FictionDetailPage(fictionId : fictionIntroduction.bookId);
335 | }));
336 | },
337 | child: Column(
338 | mainAxisSize: MainAxisSize.min,
339 | mainAxisAlignment: MainAxisAlignment.start,
340 | crossAxisAlignment: CrossAxisAlignment.start,
341 | children: [
342 | Image.network(fictionIntroduction.picture,width: 90.0,height: 120.0,),
343 | Container(
344 | width: 90.0,
345 | margin: EdgeInsets.only(top: 5.0,bottom: 3.0),
346 | child: Text(fictionIntroduction.name,style: TextStyle(fontSize: 14.0,color: Color(0xFF333333)),softWrap: false,overflow: TextOverflow.ellipsis,),
347 | ),
348 | Container(
349 | width: 90.0,
350 | child: Text(fictionIntroduction.author,style: TextStyle(fontSize: 14.0,color: Color(0xFF999999)),softWrap: false,overflow: TextOverflow.ellipsis,),
351 | ),
352 | ],
353 | ),
354 | );
355 | }
356 |
357 | @override
358 | // TODO: implement wantKeepAlive
359 | bool get wantKeepAlive => true;
360 |
361 | }
--------------------------------------------------------------------------------
/flutter_demo/lib/homePage.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_demo/SearchPage.dart';
3 | import 'controller/HttpController.dart';
4 | import 'bean/ChannelResponse.dart';
5 | import 'channelView.dart';
6 |
7 | class HomePage extends StatefulWidget{
8 | @override
9 | State createState() {
10 | // TODO: implement createState
11 | return new HomePageState();
12 | }
13 | }
14 |
15 | class HomePageState extends State with AutomaticKeepAliveClientMixin{
16 |
17 | HttpController mHttpController;
18 | bool isLoadChannel=true;//是否在加载channel
19 |
20 | List channels=[];
21 |
22 | @override
23 | Widget build(BuildContext context) {
24 | // TODO: implement build
25 | return layout(context);
26 | /* return MaterialApp(
27 | routes: {
28 | '/': (BuildContext context) => layout(context),
29 | },
30 | );*/
31 | }
32 |
33 | @override
34 | void initState() {
35 | // TODO: implement initState
36 | super.initState();
37 | mHttpController=new HttpController();
38 | getChannel();
39 | }
40 |
41 | void getChannel() async{
42 | await mHttpController.getChannelList((data){
43 | if(data!=null){
44 | setState(() {
45 | isLoadChannel=false;
46 | channels.addAll(data);
47 | print("channel data="+channels.toString());
48 | });
49 | }
50 | });
51 | }
52 |
53 |
54 | Widget layout(BuildContext context){
55 |
56 | if(isLoadChannel){
57 | return Theme(
58 | data: ThemeData(
59 | primaryColor: Colors.white
60 | ),
61 | child: Scaffold(
62 | appBar: AppBar(
63 | leading: Container(
64 | padding: EdgeInsets.only(left: 5.0),
65 | child: Image.asset('images/icon_logo.png',width: 63.0,height: 15.0,),
66 | ),
67 | title:DecoratedBox(
68 | decoration: BoxDecoration(
69 | color: Color.fromARGB(150, 245, 245, 245),
70 | borderRadius: BorderRadius.circular(20.0),
71 | border: Border.all(color: Color(0xFFC90E),width: 1.0)
72 | ),
73 | child: Row(
74 | mainAxisSize: MainAxisSize.min,
75 | mainAxisAlignment: MainAxisAlignment.start,
76 | crossAxisAlignment: CrossAxisAlignment.center,
77 | children: [
78 | Padding(
79 | padding: EdgeInsets.only(left: 10.0),
80 | child: Image.asset('images/icon_function_search.png',width: 14.0,height: 14.0,),
81 | ),
82 | Padding(
83 | padding: EdgeInsets.fromLTRB(10.0, 5.0, 80.0, 5.0),
84 | child: Text('搜索你感兴趣的内容',style: TextStyle(fontSize: 14.0,color: Colors.black),),
85 | ),
86 | ],
87 | ),
88 | ),
89 | ),
90 | body: Center(
91 | child: CircularProgressIndicator(
92 | backgroundColor: Colors.blue,
93 | strokeWidth: 4,
94 | )
95 | ),
96 | )
97 | );
98 | }
99 |
100 | return Theme(
101 | data: ThemeData(
102 | primaryColor: Colors.white
103 | ),
104 | child: DefaultTabController(
105 | length: channels.length,
106 | child: Scaffold(
107 | appBar: AppBar(
108 | leading: Container(
109 | padding: EdgeInsets.only(left: 5.0),
110 | child: Image.asset('images/icon_logo.png',width: 63.0,height: 15.0,),
111 | ),
112 | title: DecoratedBox(
113 | decoration: BoxDecoration(
114 | color: Color.fromARGB(150, 245, 245, 245),
115 | borderRadius: BorderRadius.circular(20.0),
116 | // border: Border.all(color: Color(0xFFFFC90E),width: 1.0)
117 | ),
118 | child: InkWell(
119 | onTap: (){
120 | Navigator.push(
121 | context,
122 | MaterialPageRoute(builder: (context){
123 | return SearchPage();
124 | })
125 | );
126 |
127 | },
128 |
129 | child: Row(
130 | mainAxisSize: MainAxisSize.min,
131 | mainAxisAlignment: MainAxisAlignment.start,
132 | crossAxisAlignment: CrossAxisAlignment.center,
133 | children: [
134 | Padding(
135 | padding: EdgeInsets.only(left: 10.0),
136 | child: Image.asset('images/icon_function_search.png',width: 14.0,height: 14.0,),
137 | ),
138 | Padding(
139 | padding: EdgeInsets.fromLTRB(10.0, 5.0, 80.0, 5.0),
140 | child: Text('搜索你感兴趣的内容',style: TextStyle(fontSize: 14.0,color: Colors.black),),
141 | ),
142 | ],
143 | ),
144 | ),
145 | ),
146 | bottom: TabBar(
147 | isScrollable: true,
148 | indicatorColor: Color(0xFFFFB40C),
149 | labelColor: Colors.black,
150 | labelStyle: TextStyle(fontSize: 16.0,fontWeight: FontWeight.bold),
151 | unselectedLabelColor: Color(0xFF666666),
152 | unselectedLabelStyle: TextStyle(fontSize: 14.0),
153 | tabs: channels.map((Channel channel){
154 | return Tab(
155 | text: channel.name,
156 | );
157 | }).toList(),
158 | ),
159 | ),
160 | body: TabBarView(
161 | children: channels.map((Channel channel){
162 | return Container(
163 | /*child: RefreshIndicator(
164 | child: ListView.builder(itemCount:mNewsList.length,itemBuilder: itemView,controller: _scrollController, ),
165 | onRefresh: _onRefresh),*/
166 | child: _buildChannelTab(context,channel),
167 | );
168 | }).toList(),
169 | ),
170 | ),
171 | )
172 | );
173 | }
174 |
175 | Widget _buildChannelTab(BuildContext context,Channel channel){
176 | return NewsListView(mChannelCode: channel.code.toString(),mSearchText: "",);
177 | }
178 |
179 | @override
180 | // TODO: implement wantKeepAlive
181 | bool get wantKeepAlive => true;
182 |
183 |
184 | }
--------------------------------------------------------------------------------
/flutter_demo/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:english_words/english_words.dart';
3 | import 'package:flutter_demo/utils/SpUtil.dart';
4 | import 'homePage.dart';
5 | import 'PersonalPage.dart';
6 | import 'fiction/mainFiction.dart';
7 |
8 | void main() => runApp(AppHome());
9 |
10 | class AppHome extends StatelessWidget{
11 | @override
12 | Widget build(BuildContext context) {
13 | // TODO: implement build
14 | return MaterialApp(
15 | home: MainPage()
16 | );
17 | }
18 | }
19 |
20 |
21 | class MainPage extends StatefulWidget{
22 | @override
23 | State createState() {
24 | // TODO: implement createState
25 | return new MainPageState();
26 | }
27 | }
28 |
29 | class MainPageState extends State{
30 | int _tabIndex = 0;
31 | var _pageList;
32 | var tabImages;
33 | var appBarTitles= ['新闻','小说','中心'];
34 |
35 | var _pageController = new PageController(initialPage: 0);
36 |
37 | @override
38 | Widget build(BuildContext context) {
39 | _initData();
40 | return Scaffold(
41 | body: PageView(
42 | scrollDirection: Axis.horizontal,
43 | physics: NeverScrollableScrollPhysics(),
44 | controller: _pageController,
45 | children: _pageList,
46 | ),
47 | bottomNavigationBar: BottomNavigationBar(
48 | items: [
49 | BottomNavigationBarItem(
50 | icon: getTabIcon(0),
51 | title: getTabTitle(0)
52 | ),
53 | BottomNavigationBarItem(
54 | icon: getTabIcon(1),
55 | title: getTabTitle(1)
56 | ),
57 | BottomNavigationBarItem(
58 | icon: getTabIcon(2),
59 | title: getTabTitle(2)
60 | ),
61 | ],
62 | type: BottomNavigationBarType.fixed,
63 | currentIndex: _tabIndex,
64 | iconSize: 24.0,
65 | onTap: (index){
66 | if(index==_tabIndex)
67 | return;
68 |
69 | setState(() {
70 | _tabIndex=index;
71 | });
72 |
73 | _pageController.jumpToPage(index);
74 | },
75 | ),
76 | );
77 | }
78 |
79 | @override
80 | void initState() {
81 | // TODO: implement initState
82 | super.initState();
83 | _initAsync();
84 | }
85 |
86 |
87 | //初始化sp
88 | void _initAsync() async {
89 | await SpUtil.getInstance();
90 | }
91 |
92 | void _initData(){
93 | _pageList = [
94 | new HomePage(),
95 | new mainFiction(),
96 | new PersonalPage(),
97 | ];
98 |
99 | tabImages=[
100 | [getTabImage('images/icon_main_tab_news_normal.png'),getTabImage('images/icon_main_tab_news_selected.png')],
101 | [getTabImage('images/icon_main_tab_micro_normal.png'),getTabImage('images/icon_main_tab_micro_select.png')],
102 | [getTabImage('images/icon_main_tab_person_normal.png'),getTabImage('images/icon_main_tab_person_selected.png')],
103 |
104 | ];
105 | }
106 |
107 | Image getTabImage(path) {
108 | return new Image.asset(path, width: 24.0, height: 24.0,fit: BoxFit.contain,);
109 | }
110 |
111 | Image getTabIcon(int index){
112 | if(index==_tabIndex){
113 | return tabImages[index][1];
114 | }else{
115 | return tabImages[index][0];
116 | }
117 | }
118 |
119 | //获取tab的文字
120 | Text getTabTitle(int index){
121 | if(index == _tabIndex){
122 | return Text(
123 | appBarTitles[index],
124 | style: TextStyle(fontSize: 14.0,color: Color(0xFFFFCA12)),
125 | );
126 | }else{
127 | return Text(
128 | appBarTitles[index],
129 | style: TextStyle(fontSize: 14.0,color: Color(0xFF999999)),
130 | );
131 | }
132 | }
133 |
134 | }
135 |
136 |
137 |
--------------------------------------------------------------------------------
/flutter_demo/lib/news_detail_page.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'bean/NewsResData.dart';
5 | import 'package:webview_flutter/webview_flutter.dart';
6 | import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
7 |
8 | class NewsDetailPage extends StatelessWidget{
9 |
10 | final Completer _controller = Completer();
11 |
12 | NewsDetailPage({this.mNews});
13 | final News mNews;
14 |
15 | @override
16 | Widget build(BuildContext context) {
17 | assert(mNews!=null);
18 | return WebviewScaffold(
19 | url: mNews.src,
20 | appBar: new AppBar(
21 | title: Text('${mNews.title}'),
22 | ),
23 | hidden: true,
24 | initialChild: Container(
25 | child: const Center(
26 | child: Text('Waiting.....'),
27 | ),
28 | ),
29 | );
30 | // TODO: implement build
31 | /*return Scaffold(
32 | appBar: AppBar(
33 | title: Text('${mNews.title}'),
34 | // This drop down menu demonstrates that Flutter widgets can be shown over the web view.
35 | actions: [
36 | NavigationControls(_controller.future),
37 | const SampleMenu(),
38 | ],
39 | ),
40 | body: WebView(
41 | initialUrl: mNews.src,
42 | javaScriptMode: JavaScriptMode.unrestricted,
43 | onWebViewCreated: (WebViewController webViewController) {
44 | _controller.complete(webViewController);
45 | },
46 | ),
47 | floatingActionButton: favoriteButton(),
48 | );*/
49 | }
50 |
51 | Widget favoriteButton() {
52 | return FutureBuilder(
53 | future: _controller.future,
54 | builder: (BuildContext context,
55 | AsyncSnapshot controller) {
56 | if (controller.hasData) {
57 | return FloatingActionButton(
58 | onPressed: () async {
59 | final String url = await controller.data.currentUrl();
60 | Scaffold.of(context).showSnackBar(
61 | SnackBar(content: Text("Favorited $url")),
62 | );
63 | },
64 | child: const Icon(Icons.favorite),
65 | );
66 | }
67 | return Container();
68 | });
69 | }
70 | }
71 |
72 | class SampleMenu extends StatelessWidget {
73 | const SampleMenu();
74 |
75 | @override
76 | Widget build(BuildContext context) {
77 | return PopupMenuButton(
78 | onSelected: (String value) {
79 | Scaffold.of(context)
80 | .showSnackBar(SnackBar(content: Text('You selected: $value')));
81 | },
82 | itemBuilder: (BuildContext context) => >[
83 | const PopupMenuItem(
84 | value: 'Item 1',
85 | child: Text('Item 1'),
86 | ),
87 | const PopupMenuItem(
88 | value: 'Item 2',
89 | child: Text('Item 2'),
90 | ),
91 | ],
92 | );
93 | }
94 | }
95 |
96 | class NavigationControls extends StatelessWidget {
97 | const NavigationControls(this._webViewControllerFuture)
98 | : assert(_webViewControllerFuture != null);
99 |
100 | final Future _webViewControllerFuture;
101 |
102 | @override
103 | Widget build(BuildContext context) {
104 | return FutureBuilder(
105 | future: _webViewControllerFuture,
106 | builder:
107 | (BuildContext context, AsyncSnapshot snapshot) {
108 | final bool webViewReady =
109 | snapshot.connectionState == ConnectionState.done;
110 | final WebViewController controller = snapshot.data;
111 | return Row(
112 | children: [
113 | IconButton(
114 | icon: const Icon(Icons.arrow_back_ios),
115 | onPressed: !webViewReady
116 | ? null
117 | : () async {
118 | if (await controller.canGoBack()) {
119 | controller.goBack();
120 | } else {
121 | Scaffold.of(context).showSnackBar(
122 | const SnackBar(content: Text("No back history item")),
123 | );
124 | return;
125 | }
126 | },
127 | ),
128 | IconButton(
129 | icon: const Icon(Icons.arrow_forward_ios),
130 | onPressed: !webViewReady
131 | ? null
132 | : () async {
133 | if (await controller.canGoForward()) {
134 | controller.goForward();
135 | } else {
136 | Scaffold.of(context).showSnackBar(
137 | const SnackBar(
138 | content: Text("No forward history item")),
139 | );
140 | return;
141 | }
142 | },
143 | ),
144 | IconButton(
145 | icon: const Icon(Icons.replay),
146 | onPressed: !webViewReady
147 | ? null
148 | : () {
149 | controller.reload();
150 | },
151 | ),
152 | ],
153 | );
154 | },
155 | );
156 | }
157 | }
--------------------------------------------------------------------------------
/flutter_demo/lib/utils/SpUtil.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:convert';
3 |
4 | import 'package:shared_preferences/shared_preferences.dart';
5 | import 'package:synchronized/synchronized.dart';
6 |
7 | /**
8 | * @Author: thl
9 | * @GitHub: https://github.com/Sky24n
10 | * @Email: 863764940@qq.com
11 | * @Email: sky24no@gmail.com
12 | * @Description: Sp Util.
13 | * @Date: 2018/9/8
14 | */
15 |
16 | /// SharedPreferences Util.
17 | class SpUtil {
18 | static SpUtil _singleton;
19 | static SharedPreferences _prefs;
20 | static Lock _lock = Lock();
21 |
22 | static Future getInstance() async {
23 | if (_singleton == null) {
24 | await _lock.synchronized(() async {
25 | if (_singleton == null) {
26 | // keep local instance till it is fully initialized.
27 | // 保持本地实例直到完全初始化。
28 | var singleton = SpUtil._();
29 | await singleton._init();
30 | _singleton = singleton;
31 | }
32 | });
33 | }
34 | return _singleton;
35 | }
36 |
37 | SpUtil._();
38 |
39 | Future _init() async {
40 | _prefs = await SharedPreferences.getInstance();
41 | }
42 |
43 | /// put object.
44 | static Future putObject(String key, Object value) {
45 | if (_prefs == null) return null;
46 | return _prefs.setString(key, value == null ? "" : json.encode(value));
47 | }
48 |
49 | /// get object.
50 | static Map getObject(String key) {
51 | if (_prefs == null) return null;
52 | String _data = _prefs.getString(key);
53 | return (_data == null || _data.isEmpty) ? null : json.decode(_data);
54 | }
55 |
56 | /// put object list.
57 | static Future putObjectList(String key, List