Repository: ngu2008/wanandroid
Branch: master
Commit: a42574101ad1
Files: 86
Total size: 234.2 KB
Directory structure:
gitextract_ft2s6f_c/
├── .gitignore
├── .metadata
├── README.md
├── android/
│ ├── app/
│ │ ├── build.gradle
│ │ └── src/
│ │ └── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── ngu/
│ │ │ └── wanandroidngu/
│ │ │ └── MainActivity.java
│ │ └── res/
│ │ ├── drawable/
│ │ │ └── launch_background.xml
│ │ └── values/
│ │ └── styles.xml
│ ├── build.gradle
│ ├── gradle/
│ │ └── wrapper/
│ │ └── gradle-wrapper.properties
│ ├── gradle.properties
│ ├── key.properties
│ ├── settings.gradle
│ └── wandroid_ngu.jks
├── interview.md
├── ios/
│ ├── Flutter/
│ │ ├── AppFrameworkInfo.plist
│ │ ├── Debug.xcconfig
│ │ └── Release.xcconfig
│ ├── Runner/
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.m
│ │ ├── Assets.xcassets/
│ │ │ ├── AppIcon.appiconset/
│ │ │ │ └── Contents.json
│ │ │ └── LaunchImage.imageset/
│ │ │ ├── Contents.json
│ │ │ └── README.md
│ │ ├── Base.lproj/
│ │ │ ├── LaunchScreen.storyboard
│ │ │ └── Main.storyboard
│ │ ├── Info.plist
│ │ └── main.m
│ ├── Runner.xcodeproj/
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace/
│ │ │ └── contents.xcworkspacedata
│ │ └── xcshareddata/
│ │ └── xcschemes/
│ │ └── Runner.xcscheme
│ └── Runner.xcworkspace/
│ └── contents.xcworkspacedata
├── lib/
│ ├── app.dart
│ ├── base/
│ │ └── _base_widget.dart
│ ├── common/
│ │ ├── application.dart
│ │ └── user.dart
│ ├── db/
│ │ └── db_helper.dart
│ ├── event/
│ │ ├── change_theme_event.dart
│ │ └── login_event.dart
│ ├── http/
│ │ ├── api.dart
│ │ ├── api_service.dart
│ │ └── dio_manager.dart
│ ├── loading.dart
│ ├── main.dart
│ ├── model/
│ │ ├── article_model.dart
│ │ ├── banner_model.dart
│ │ ├── base_model.dart
│ │ ├── collection_model.dart
│ │ ├── common_websit_model.dart
│ │ ├── common_website_model.dart
│ │ ├── hotword_model.dart
│ │ ├── hotword_result_model.dart
│ │ ├── navi_model.dart
│ │ ├── pretty_model.dart
│ │ ├── project_tree_model.dart
│ │ ├── projectlist_model.dart
│ │ ├── system_tree_content_model.dart
│ │ ├── system_tree_model.dart
│ │ ├── todo_item.dart
│ │ ├── todolist_model.dart
│ │ ├── user_model.dart
│ │ ├── website_collection_model.dart
│ │ ├── wx_article_content_model.dart
│ │ └── wx_article_title_model.dart
│ ├── splash_screen.dart
│ ├── ui/
│ │ ├── drawer/
│ │ │ ├── about.dart
│ │ │ ├── collctions.dart
│ │ │ ├── common_website.dart
│ │ │ ├── drawer.dart
│ │ │ └── pretty.dart
│ │ ├── home/
│ │ │ ├── banner.dart
│ │ │ └── home_page.dart
│ │ ├── knowledge/
│ │ │ ├── knowledge.dart
│ │ │ └── knowledge_content.dart
│ │ ├── login/
│ │ │ └── login_page.dart
│ │ ├── navigation/
│ │ │ └── navigation.dart
│ │ ├── project/
│ │ │ └── project.dart
│ │ ├── public_ui/
│ │ │ └── webview_page.dart
│ │ ├── publicc/
│ │ │ └── publicc.dart
│ │ └── search/
│ │ ├── hot_search_result.dart
│ │ └── search.dart
│ └── util/
│ ├── bubble_indication_painter.dart
│ ├── style_util.dart
│ ├── theme_util.dart
│ └── utils.dart
├── pubspec.yaml
└── test/
└── widget_test.dart
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Miscellaneous
*.class
*.lock
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# Visual Studio Code related
.vscode/
# Flutter/Dart/Pub related
**/doc/api/
.dart_tool/
.flutter-plugins
.packages
.pub-cache/
.pub/
build/
# Android related
**/android/**/gradle-wrapper.jar
**/android/.gradle
**/android/captures/
**/android/gradlew
**/android/gradlew.bat
**/android/local.properties
**/android/**/GeneratedPluginRegistrant.java
# iOS/XCode related
**/ios/**/*.mode1v3
**/ios/**/*.mode2v3
**/ios/**/*.moved-aside
**/ios/**/*.pbxuser
**/ios/**/*.perspectivev3
**/ios/**/*sync/
**/ios/**/.sconsign.dblite
**/ios/**/.tags*
**/ios/**/.vagrant/
**/ios/**/DerivedData/
**/ios/**/Icon?
**/ios/**/Pods/
**/ios/**/.symlinks/
**/ios/**/profile
**/ios/**/xcuserdata
**/ios/.generated/
**/ios/Flutter/App.framework
**/ios/Flutter/Flutter.framework
**/ios/Flutter/Generated.xcconfig
**/ios/Flutter/app.flx
**/ios/Flutter/app.zip
**/ios/Flutter/flutter_assets/
**/ios/ServiceDefinitions.json
**/ios/Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!**/ios/**/default.mode1v3
!**/ios/**/default.mode2v3
!**/ios/**/default.pbxuser
!**/ios/**/default.perspectivev3
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
================================================
FILE: .metadata
================================================
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b
channel: stable
project_type: app
================================================
FILE: README.md
================================================
## Flutter学习资源汇总持续更新中......
- [Flutter官方网站](https://flutter.dev/)
- [Flutter中文网](https://flutterchina.club/)
- wendux的[Flutter实战](https://book.flutterchina.club/)
- Flutter官方example[flutter_gallery](https://github.com/flutter/flutter/tree/master/examples/flutter_gallery)
- [阿里巴巴咸鱼团队系列文章](https://www.yuque.com/xytech/flutter)
- [阿里巴巴flutter-go](https://github.com/alibaba/flutter-go),flutter 开发者帮助 APP,包含 flutter 常用 140+ 组件的demo 演示与中文文档
- [awesome-flutter](https://github.com/Solido/awesome-flutter)包含居多优秀的Flutter库,工具,教程,文章等
- [玩Android跨平台项目](https://www.wanandroid.com/project/list/1?cid=402)
- 非常有用的[Json转Model插件](https://github.com/neverwoodsS/idea_dart_json_format)
- [Flutter-Notebook](https://github.com/OpenFlutter/Flutter-Notebook),提供了很多优秀样例和Demo
- [Flutter-plugins](https://github.com/flutter/plugins),flutter官方插件,提供了众多优秀插件
- 掘金作者[恋猫de小郭系列文章](https://juejin.im/user/582aca2ba22b9d006b59ae68/posts)
## 前言
- 这是一款使用Flutter写的WanAndroid客户端应用,在Android和IOS都完美运行
- ~~可以用来入门Flutter,简单明了,适合初学者~~
- [项目完全开源](https://github.com/ngu2008/wanandroid_ngu),如果本项目确实能够帮助到你学习Flutter,谢谢start一下,有问题请提交Issues,我会及时回复
## 环境搭建
- 根据[Flutter中文网](https://flutterchina.club/get-started/install)搭建开发环境,使用Android Studio安装Flutter插件,点击pubspec.yaml的package get,然后运行
## APP下载
- Android[点击下载](https://www.pgyer.com/haFL),或者扫描下方二维码下载

- 暂不支持IOS版本下载,请自行clone项目代码运行。
## App目录结构
>- |--lib
> - |-- main (入口类)
> - |-- loading (启动页)
> - |-- splash_screen (引导页)
> - |-- util (工具类)
> - |-- base (基类,封装基类BaseWidget和BaseWidgetState)
> - |-- http (网络请求相关类)
> - |-- common (常用类)
> - |-- event (事件类)
> - |-- model (实体类)
> - |-- ui (界面相关)
> - |-- util (工具类)
## 功能介绍
#### V1.5版本
- 常用网站增加数据库[sqflite](https://pub.flutter-io.cn/packages/sqflite)功能
- 修复注册登录按钮颜色与主题色不一致的问题
#### V1.4版本
- 增加切换主题
- 封装基类BaseWidget和BaseWidgetState
- 显示隐藏AppBar
- 增加状态页切换(数据加载中,数据加载失败,空数据)
#### V1.3版本
- 新增搜索和搜索结果列表
- 新增页面正在加载...
- 整个界面UI风格修改
#### V1.2版本
- 新增福利,妹子图,使用[photo_view](https://pub.flutter-io.cn/packages/photo_view),你懂得
- 新增分享[share](https://pub.flutter-io.cn/packages/share)
- 新增常用网站
- 新增关于作者,退出登录
#### V1.1版本
- 新增引导页[flutter-intro-slider](https://github.com/duytq94/flutter-intro-slider)
- 列表页悬浮FloatingActionButton,点击迅速回到顶部
- 新增注册、登录、我的收藏,增加侧滑抽屉,详见截图
#### V1.0版本
- 项目首页、知识体系、公众号、导航、项目、各个页面,和详情页面
- 主要的UI包括首页轮播图和列表,体系流式布局,公众号导航TabBar,以及下拉刷新和加载更多
- 轮播图使用的是开源库[flutter_swiper](https://github.com/best-flutter/flutter_swiper)
- 网络请求使用的是开源库[dio](https://github.com/flutterchina/dio)
## 我的主页
- [掘金](https://juejin.im/user/5b319afee51d455e2c32fb5b/posts)
- [CSDN](https://blog.csdn.net/zw2008224044)
## 应用截图
|
|
|
|
| :--: | :--: | :--: |
| 福利,妹子图 | 导航页 | 导航页 |
|
|
|
|
| :--: | :--: | :--: |
| 登录 | 注册 | 分享 |
|
|
|
|
| :--: | :--: | :--: |
| 关于作者 | 常用网站 | 侧滑抽屉 |
|
|
|
|
| :--: | :--: | :--: |
| 首页 | 体系 | 公众号 |
|
|
|
|
| :--: | :--: | :--: |
| 导航 | 项目 | 基础知识 |
|
|
|
|
| :--: | :--: |:--: |
| 我的收藏 | 详情页 | 热门搜索 |
|
|
|
|
| :--: | :--: |:--: |
| 搜索列表 | 正在加载 |加载错误 |
|
|
| |
| :--: | :--: |:--: |
| 数据为空 | 切换主题 | |
## 感谢
1. 特别感谢github开源作者[shijiacheng](https://github.com/shijiacheng/wanandroid_flutter)
2. 感谢鸿洋大神及[玩Android官网](http://www.wanandroid.com/)提供的[开放API](http://www.wanandroid.com/blog/show/2)
3. 感谢[干货集中营 API](http://gank.io/api)
## 使用开源库
- [shared_preferences](https://pub.dartlang.org/packages/shared_preferences)
- [fluttertoast](https://pub.dartlang.org/packages/fluttertoast)
- [share](https://pub.flutter-io.cn/packages/share)
- [flutter_swiper](https://pub.flutter-io.cn/packages/flutter_swiper)
- [cupertino_icons](https://pub.flutter-io.cn/packages/cupertino_icons)
- [flutter_webview_plugin](https://pub.flutter-io.cn/packages/flutter_webview_plugin)
- [dio](https://pub.flutter-io.cn/packages/dio)
- [flutter-intro-slider](https://github.com/duytq94/flutter-intro-slider)
- [photo_view](https://pub.flutter-io.cn/packages/photo_view)
- [sqflite](https://pub.flutter-io.cn/packages/sqflite)
- [path_provider ](https://pub.flutter-io.cn/packages/path_provider#-installing-tab-)
## 欢迎关注我的微信公众号

================================================
FILE: android/app/build.gradle
================================================
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
def keystorePropertiesFile = rootProject.file("key.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android {
compileSdkVersion 28
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.ngu.wanandroidngu"
minSdkVersion 16
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
flutter {
source '../..'
}
dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
}
================================================
FILE: android/app/src/main/AndroidManifest.xml
================================================
================================================
FILE: android/app/src/main/java/com/ngu/wanandroidngu/MainActivity.java
================================================
package com.ngu.wanandroidngu;
import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
}
}
================================================
FILE: android/app/src/main/res/drawable/launch_background.xml
================================================
================================================
FILE: android/app/src/main/res/values/styles.xml
================================================
================================================
FILE: android/build.gradle
================================================
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
================================================
FILE: android/gradle/wrapper/gradle-wrapper.properties
================================================
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
================================================
FILE: android/gradle.properties
================================================
android.enableJetifier=true
android.useAndroidX=true
org.gradle.jvmargs=-Xmx1536M
================================================
FILE: android/key.properties
================================================
storePassword=wandroid_ngu
keyPassword=wandroid_ngu
keyAlias=wandroid_ngu
storeFile=../wandroid_ngu.jks
================================================
FILE: android/settings.gradle
================================================
include ':app'
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}
================================================
FILE: interview.md
================================================
# 一道面试题
> 分享一道面试题,结果有点出乎意料
代码如下:输出结果是什么?
public class Test {
public static void main(String[] args) {
Set stack = new HashSet<>();
for (Short i = 0; i < 100; i++) {
stack.add(i);
stack.remove(i - 1);
}
System.out.println(stack.size());
}
- 答案是100,i-1这里用到了隐式类型转换i-1会转成int型的减法,所以在remove时,根本没有那个对象,所以无论怎么调stack.remove(i-1)都不会有元素移出,所以答案是100.
================================================
FILE: ios/Flutter/AppFrameworkInfo.plist
================================================
CFBundleDevelopmentRegion
en
CFBundleExecutable
App
CFBundleIdentifier
io.flutter.flutter.app
CFBundleInfoDictionaryVersion
6.0
CFBundleName
App
CFBundlePackageType
FMWK
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1.0
MinimumOSVersion
8.0
================================================
FILE: ios/Flutter/Debug.xcconfig
================================================
#include "Generated.xcconfig"
================================================
FILE: ios/Flutter/Release.xcconfig
================================================
#include "Generated.xcconfig"
================================================
FILE: ios/Runner/AppDelegate.h
================================================
#import
#import
@interface AppDelegate : FlutterAppDelegate
@end
================================================
FILE: ios/Runner/AppDelegate.m
================================================
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
================================================
FILE: ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
================================================
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
================================================
FILE: ios/Runner/Base.lproj/LaunchScreen.storyboard
================================================
================================================
FILE: ios/Runner/Base.lproj/Main.storyboard
================================================
================================================
FILE: ios/Runner/Info.plist
================================================
CFBundleDevelopmentRegion
en
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
$(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
wanandroid_ngu
CFBundlePackageType
APPL
CFBundleShortVersionString
$(FLUTTER_BUILD_NAME)
CFBundleSignature
????
CFBundleVersion
$(FLUTTER_BUILD_NUMBER)
LSRequiresIPhoneOS
UILaunchStoryboardName
LaunchScreen
UIMainStoryboardFile
Main
UISupportedInterfaceOrientations
UIInterfaceOrientationPortrait
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
UISupportedInterfaceOrientations~ipad
UIInterfaceOrientationPortrait
UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
UIViewControllerBasedStatusBarAppearance
================================================
FILE: ios/Runner/main.m
================================================
#import
#import
#import "AppDelegate.h"
int main(int argc, char* argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
================================================
FILE: ios/Runner.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
2D5378251FAA1A9400D5DBA9 /* flutter_assets */,
3B80C3931E831B6300D905FE /* App.framework */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEBA1CF902C7004384FC /* Flutter.framework */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
CF3B75C9A7D2FA2A4C99F110 /* Frameworks */,
);
sourceTree = "";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
);
name = Products;
sourceTree = "";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
97C146F11CF9000F007C117D /* Supporting Files */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
);
path = Runner;
sourceTree = "";
};
97C146F11CF9000F007C117D /* Supporting Files */ = {
isa = PBXGroup;
children = (
97C146F21CF9000F007C117D /* main.m */,
);
name = "Supporting Files";
sourceTree = "";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0910;
ORGANIZATIONNAME = "The Chromium Authors";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
97C146F31CF9000F007C117D /* main.m in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = S8QB4VV633;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.ngu.wanandroidNgu;
PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.ngu.wanandroidNgu;
PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.ngu.wanandroidNgu;
PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
================================================
FILE: ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
================================================
FILE: ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
================================================
================================================
FILE: ios/Runner.xcworkspace/contents.xcworkspacedata
================================================
================================================
FILE: lib/app.dart
================================================
import 'package:flutter/material.dart';
import 'package:wanandroid_ngu/ui/drawer/drawer.dart';
import 'package:wanandroid_ngu/ui/home/home_page.dart';
import 'package:wanandroid_ngu/ui/knowledge/knowledge.dart';
import 'package:wanandroid_ngu/ui/navigation/navigation.dart';
import 'package:wanandroid_ngu/ui/project/project.dart';
import 'package:wanandroid_ngu/ui/publicc/publicc.dart';
import 'package:wanandroid_ngu/ui/search/search.dart';
//应用页面使用有状态Widget
class App extends StatefulWidget {
App({Key key}) : super(key: key);
@override
AppState createState() => AppState();
}
//应用页面状态实现类
class AppState extends State {
int _selectedIndex = 0; //当前选中项的索引
final appBarTitles = ['玩Android', '体系', '公众号', '导航', "项目"];
int elevation = 4;
var pages = [
HomePage(),
KnowledgePage(),
PubliccPage(),
NavigationPage(),
ProjectPage()
];
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: _onWillPop,
child: Scaffold(
drawer: DrawerPage(),
appBar: AppBar(
title: new Text(appBarTitles[_selectedIndex]),
bottom: null,
elevation: 0,
actions: [
IconButton(
icon: Icon(Icons.search),
onPressed: () {
Navigator.of(context)
.push(new MaterialPageRoute(builder: (context) {
return new SearchPage();
}));
})
],
),
body: new IndexedStack(children: pages, index: _selectedIndex),
//底部导航按钮 包含图标及文本
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('首页')),
BottomNavigationBarItem(
icon: Icon(Icons.assignment), title: Text('体系')),
BottomNavigationBarItem(icon: Icon(Icons.chat), title: Text('公众号')),
BottomNavigationBarItem(
icon: Icon(Icons.navigation), title: Text('导航')),
BottomNavigationBarItem(icon: Icon(Icons.book), title: Text('项目'))
],
type: BottomNavigationBarType.fixed, //设置显示的模式
currentIndex: _selectedIndex, //当前选中项的索引
onTap: _onItemTapped, //选择按下处理
),
),
);
}
//选择按下处理 设置当前索引为index值
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
if (index == 2 || index == 4) {
elevation = 0;
} else {
elevation = 4;
}
});
}
Future _onWillPop() {
return showDialog(
context: context,
builder: (context) => new AlertDialog(
title: new Text('提示'),
content: new Text('确定退出应用吗?'),
actions: [
new FlatButton(
onPressed: () => Navigator.of(context).pop(false),
child: new Text('再看一会'),
),
new FlatButton(
onPressed: () => Navigator.of(context).pop(true),
child: new Text('退出'),
),
],
),
) ??
false;
}
}
================================================
FILE: lib/base/_base_widget.dart
================================================
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
abstract class BaseWidget extends StatefulWidget {
BaseWidgetState baseWidgetState;
@override
BaseWidgetState createState() {
baseWidgetState = getState();
return baseWidgetState;
}
BaseWidgetState getState();
}
abstract class BaseWidgetState extends State {
bool _isAppBarShow = true; //导航栏是否显示
bool _isErrorWidgetShow = false; //错误信息是否显示
String _errorContentMesage = "网络请求失败,请检查您的网络";
String _errImgPath = "images/ic_error.png";
bool _isLoadingWidgetShow = false;
bool _isEmptyWidgetShow = false;
String _emptyWidgetContent = "暂无数据~";
String _emptyImgPath = "images/ic_empty.png"; //自己根据需求变更
FontWeight _fontWidget = FontWeight.w600; //错误页面和空页面的字体粗度
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _getBaseAppBar(),
body: Container(
color: Colors.white, //背景颜色,可自己变更
child: Stack(
children: [
getContentWidget(context),
_getBaseErrorWidget(),
_getBaseEmptyWidget(),
_getBassLoadingWidget(),
],
),
));
}
@override
void dispose() {
super.dispose();
}
Widget getContentWidget(BuildContext context);
///暴露的错误页面方法,可以自己重写定制
Widget getErrorWidget() {
return Container(
//错误页面中心可以自己调整
padding: EdgeInsets.fromLTRB(0, 0, 0, 80),
color: Colors.white,
width: double.infinity,
height: double.infinity,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image(
image: AssetImage(_errImgPath),
width: 120,
height: 120,
),
Container(
margin: EdgeInsets.fromLTRB(0, 20, 0, 0),
child: Text(_errorContentMesage,
style: TextStyle(
color: Colors.grey,
fontWeight: _fontWidget,
)),
),
Container(
margin: EdgeInsets.fromLTRB(0, 20, 0, 0),
child: OutlineButton(
child: Text("重新加载",
style: TextStyle(
color: Colors.grey,
fontWeight: _fontWidget,
)),
onPressed: () => {onClickErrorWidget()},
))
],
),
),
);
}
Widget getLoadingWidget() {
return Center(
child: CupertinoActivityIndicator(
radius: 15.0, //值越大加载的图形越大
));
}
Widget getEmptyWidget() {
return Container(
padding: EdgeInsets.fromLTRB(0, 0, 0, 100),
color: Colors.white,
width: double.infinity,
height: double.infinity,
child: Center(
child: Container(
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image(
color: Colors.black12,
image: AssetImage(_emptyImgPath),
width: 150,
height: 150,
),
Container(
margin: EdgeInsets.fromLTRB(0, 10, 0, 0),
child: Text(_emptyWidgetContent,
style: TextStyle(
color: Colors.grey,
fontWeight: _fontWidget,
)),
)
],
),
),
),
);
}
PreferredSizeWidget _getBaseAppBar() {
return PreferredSize(
child: Offstage(
offstage: !_isAppBarShow,
child: getAppBar(),
),
preferredSize: Size.fromHeight(50));
}
///导航栏 appBar
AppBar getAppBar();
Widget _getBaseErrorWidget() {
return Offstage(
offstage: !_isErrorWidgetShow,
child: getErrorWidget(),
);
}
Widget _getBassLoadingWidget() {
return Offstage(
offstage: !_isLoadingWidgetShow,
child: getLoadingWidget(),
);
}
Widget _getBaseEmptyWidget() {
return Offstage(
offstage: !_isEmptyWidgetShow,
child: getEmptyWidget(),
);
}
///点击错误页面后展示内容
void onClickErrorWidget();
///设置错误提示信息
void setErrorContent(String content) {
if (content != null) {
setState(() {
_errorContentMesage = content;
});
}
}
///设置导航栏隐藏或者显示
void setAppBarVisible(bool isVisible) {
setState(() {
_isAppBarShow = isVisible;
});
}
void showContent() {
setState(() {
_isEmptyWidgetShow = false;
_isLoadingWidgetShow = false;
_isErrorWidgetShow = false;
});
}
void showloading() {
setState(() {
_isEmptyWidgetShow = false;
_isLoadingWidgetShow = true;
_isErrorWidgetShow = false;
});
}
void showEmpty() {
setState(() {
_isEmptyWidgetShow = true;
_isLoadingWidgetShow = false;
_isErrorWidgetShow = false;
});
}
void showError() {
setState(() {
_isEmptyWidgetShow = false;
_isLoadingWidgetShow = false;
_isErrorWidgetShow = true;
});
}
///设置空页面内容
void setEmptyWidgetContent(String content) {
if (content != null) {
setState(() {
_emptyWidgetContent = content;
});
}
}
///设置错误页面图片
void setErrorImage(String imagePath) {
if (imagePath != null) {
setState(() {
_errImgPath = imagePath;
});
}
}
///设置空页面图片
void setEmptyImage(String imagePath) {
if (imagePath != null) {
setState(() {
_emptyImgPath = imagePath;
});
}
}
}
================================================
FILE: lib/common/application.dart
================================================
import 'package:event_bus/event_bus.dart';
class Application{
static EventBus eventBus=new EventBus();
}
================================================
FILE: lib/common/user.dart
================================================
import '../model/user_model.dart';
import 'package:dio/dio.dart';
import 'package:shared_preferences/shared_preferences.dart';
class User {
static final User singleton = User._internal();
factory User() {
return singleton;
}
User._internal();
List cookie;
String userName;
void saveUserInfo(UserModel _userModel,Response response){
List cookies = response.headers["set-cookie"];
cookie = cookies;
userName = _userModel.data.username;
saveInfo();
}
Future getUserInfo() async {
SharedPreferences sp = await SharedPreferences.getInstance();
List cookies = sp.getStringList("cookies");
if (cookies != null) {
cookie = cookies;
}
String username = sp.getString("username");
if(username!=null){
userName = username;
}
}
saveInfo() async {
SharedPreferences sp = await SharedPreferences.getInstance();
sp.setStringList("cookies", cookie);
sp.setString("username", userName);
}
void clearUserInfor(){
cookie = null;
userName = null;
clearInfo();
}
clearInfo() async {
SharedPreferences sp = await SharedPreferences.getInstance();
sp.setStringList("cookies", null);
sp.setString("username", null);
}
}
================================================
FILE: lib/db/db_helper.dart
================================================
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'dart:async';
import 'package:path/path.dart';
import 'package:wanandroid_ngu/model/common_websit_model.dart';
class DatabaseHelper {
static final DatabaseHelper _instance = DatabaseHelper.internal();
factory DatabaseHelper() => _instance;
final String tableName = "table_common_web";
final String columnId = "id";
final String columnName = "name";
final String columnlink = "link";
final String columnIcon = "icon";
final String columnOrder = "web_order";
final String columnVisible = "visible";
static Database _db;
Future get db async {
if (_db != null) {
return _db;
}
_db = await initDb();
return _db;
}
DatabaseHelper.internal();
initDb() async {
Directory documentDirectory = await getApplicationDocumentsDirectory();
String path = join(documentDirectory.path, "wanandroid.db");
var ourDb = await openDatabase(path, version: 1, onCreate: _onCreate);
return ourDb;
}
//创建数据库表
void _onCreate(Database db, int version) async {
await db.execute(
"create table $tableName($columnId integer primary key,$columnIcon text not null, $columnlink text not null,$columnName text not null , $columnVisible integer not null , $columnOrder integer not null)");
print("Table is created");
}
//插入
Future saveItem(DataListBean item) async {
var dbClient = await db;
int res = await dbClient.insert("$tableName", item.toMap());
print(res.toString());
return res;
}
//查询
Future getTotalList() async {
var dbClient = await db;
var result = await dbClient.rawQuery("SELECT * FROM $tableName ");
return result.toList();
}
//查询总数
Future getCount() async {
var dbClient = await db;
return Sqflite.firstIntValue(await dbClient.rawQuery(
"SELECT COUNT(*) FROM $tableName"
));
}
//按照id查询
Future getItem(int id) async {
var dbClient = await db;
var result = await dbClient.rawQuery("SELECT * FROM $tableName WHERE id = $id");
if (result.length == 0) return null;
return DataListBean.fromMap(result.first);
}
//清空数据
Future clear() async {
var dbClient = await db;
return await dbClient.delete(tableName);
}
//根据id删除
Future deleteItem(int id) async {
var dbClient = await db;
return await dbClient.delete(tableName,
where: "$columnId = ?", whereArgs: [id]);
}
//修改
Future updateItem(DataListBean item) async {
var dbClient = await db;
return await dbClient.update("$tableName", item.toMap(),
where: "$columnId = ?", whereArgs: [item.id]);
}
//清空数据库
//关闭
Future close() async {
var dbClient = await db;
return dbClient.close();
}
}
================================================
FILE: lib/event/change_theme_event.dart
================================================
import 'package:flutter/material.dart';
class ChangeThemeEvent {
Color color;
ChangeThemeEvent(Color c) {
color = c;
}
}
================================================
FILE: lib/event/login_event.dart
================================================
class LoginEvent{
}
================================================
FILE: lib/http/api.dart
================================================
class Api{
static const String HOME_BANNER = "https://www.wanandroid.com/banner/json";
static const String HOME_ARTICLE_LIST = "https://www.wanandroid.com/article/list/";
/// 知识体系
static const String SYSTEM_TREE = "https://www.wanandroid.com/tree/json";
// 知识体系详情
static const String SYSTEM_TREE_CONTENT = "https://www.wanandroid.com/article/list/";
// 公众号名称
static const String WX_LIST = "https://wanandroid.com/wxarticle/chapters/json";
// 公众号文章
static const String WX_ARTICLE_LIST = "https://wanandroid.com/wxarticle/list/";
// 导航列表数据
static const String NAVI_LIST = "https://www.wanandroid.com/navi/json";
// 项目分类
static const String PROJECT_TREE = "https://www.wanandroid.com/project/tree/json";
// 项目列表
static const String PROJECT_LIST = "https://www.wanandroid.com/project/list/";
// 搜索热词
static const String SEARCH_HOT_WORD = "https://www.wanandroid.com//hotkey/json";
// 搜索结果
static const String SEARCH_RESULT = "https://www.wanandroid.com/article/query/";
// 用户登录
static const String USER_LOGIN = "https://www.wanandroid.com/user/login";
// 用户注册
static const String USER_REGISTER = "https://www.wanandroid.com/user/register";
// 收藏列表
static const String COLLECTION_LIST = "https://www.wanandroid.com/lg/collect/list/";
//常用网站
static const String COMMON_WEBSITE = "https://www.wanandroid.com/friend/json";
// 我的收藏-取消收藏
static const String CANCEL_COLLECTION = "https://www.wanandroid.com/lg/uncollect/";
// 我的收藏-新增收藏
static const String ADD_COLLECTION = "https://www.wanandroid.com/lg/collect/add/json";
// 网站收藏
static const String WEBSITE_COLLECTION_LIST = "https://www.wanandroid.com/lg/collect/usertools/json";
// 取消网站收藏
static const String CANCEL_WEBSITE_COLLECTION = "https://www.wanandroid.com/lg/collect/deletetool/json";
// 新增网站收藏
static const String ADD_WEBSITE_COLLECTION = "https://www.wanandroid.com/lg/collect/addtool/json";
// 编辑网站收藏
static const String EDIT_WEBSITE_COLLECTION = "https://www.wanandroid.com/lg/collect/updatetool/json";
// todo列表数据
static const String TODO_LIST = "https://wanandroid.com/lg/todo/list/";
// 新增todo数据
static const String ADD_TODO = "https://www.wanandroid.com/lg/todo/add/json";
// 更新todo数据
static const String UPDATE_TODO = "https://www.wanandroid.com/lg/todo/update/";
// 删除todo数据
static const String DELETE_TODO = "https://www.wanandroid.com/lg/todo/delete/";
// 仅更新todo完成状态
static const String DONE_TODO = "https://www.wanandroid.com/lg/todo/done/";
}
================================================
FILE: lib/http/api_service.dart
================================================
import 'package:dio/dio.dart';
import 'package:wanandroid_ngu/common/user.dart';
import 'package:wanandroid_ngu/http/dio_manager.dart';
import 'package:wanandroid_ngu/model/article_model.dart';
import 'package:wanandroid_ngu/model/banner_model.dart';
import 'package:wanandroid_ngu/model/base_model.dart';
import 'package:wanandroid_ngu/model/collection_model.dart';
import 'package:wanandroid_ngu/model/common_websit_model.dart';
import 'package:wanandroid_ngu/model/hotword_result_model.dart';
import 'package:wanandroid_ngu/model/navi_model.dart';
import 'package:wanandroid_ngu/model/pretty_model.dart';
import 'package:wanandroid_ngu/model/projectlist_model.dart';
import 'package:wanandroid_ngu/model/project_tree_model.dart';
import 'package:wanandroid_ngu/model/system_tree_content_model.dart';
import 'package:wanandroid_ngu/model/system_tree_model.dart';
import 'package:wanandroid_ngu/model/todolist_model.dart';
import 'package:wanandroid_ngu/model/user_model.dart';
import 'package:wanandroid_ngu/model/website_collection_model.dart';
import 'package:wanandroid_ngu/model/wx_article_content_model.dart';
import 'package:wanandroid_ngu/model/wx_article_title_model.dart';
import 'package:wanandroid_ngu/model/hotword_model.dart';
import 'api.dart';
class ApiService {
void getBanner(Function callback) async {
DioManager.singleton.dio
.get(Api.HOME_BANNER, options: _getOptions())
.then((response) {
callback(BannerModel(response.data));
});
}
void getArticleList(Function callback, Function errorback, int _page) async {
DioManager.singleton.dio
.get(Api.HOME_ARTICLE_LIST + "$_page/json", options: _getOptions())
.then((response) {
callback(ArticleModel(response.data));
}).catchError((e) {
errorback(e);
});
}
/// 获取知识体系列表
void getSystemTree(Function callback, Function errorback) async {
DioManager.singleton.dio
.get(Api.SYSTEM_TREE, options: _getOptions())
.then((response) {
callback(SystemTreeModel(response.data));
}).catchError((e) {
errorback(e);
});
}
/// 获取知识体系列表详情
void getSystemTreeContent(Function callback, Function errorback,int _page, int _id) async {
DioManager.singleton.dio
.get(Api.SYSTEM_TREE_CONTENT + "$_page/json?cid=$_id",
options: _getOptions())
.then((response) {
callback(SystemTreeContentModel(response.data));
}).catchError((e) {
errorback(e);
});
}
/// 获取公众号名称
void getWxList(Function callback, Function errorback) async {
DioManager.singleton.dio
.get(Api.WX_LIST, options: _getOptions())
.then((response) {
callback(WxArticleTitleModel(response.data));
}).catchError((e) {
errorback(e);
});
}
/// 获取公众号文章
void getWxArticleList(Function callback, int _id, int _page) async {
DioManager.singleton.dio
.get(Api.WX_ARTICLE_LIST + "$_id/$_page/json", options: _getOptions())
.then((response) {
callback(WxArticleContentModel(response.data));
});
}
/// 获取导航列表数据
void getNaviList(Function callback, Function errorback) async {
DioManager.singleton.dio
.get(Api.NAVI_LIST, options: _getOptions())
.then((response) {
callback(NaviModel(response.data));
}).catchError((e) {
errorback(e);
});
}
/// 获取项目分类
void getProjectTree(Function callback,Function errorback) async {
DioManager.singleton.dio
.get(Api.PROJECT_TREE, options: _getOptions())
.then((response) {
callback(ProjectTreeModel(response.data));
}).catchError((e) {
errorback(e);
});
}
/// 获取项目列表
void getProjectList(Function callback, int _page, int _id) async {
DioManager.singleton.dio
.get(Api.PROJECT_LIST + "$_page/json?cid=$_id", options: _getOptions())
.then((response) {
callback(ProjectTreeListModel(response.data));
});
}
/// 获取搜索热词
void getSearchHotWord(Function callback) async {
DioManager.singleton.dio
.get(Api.SEARCH_HOT_WORD, options: _getOptions())
.then((response) {
callback(HotwordModel.fromMap(response.data));
});
}
/// 获取搜索结果
void getSearchResult(Function callback, Function errorback, int _page, String _keyword) async {
FormData formData = new FormData.from({
"k": _keyword,
});
DioManager.singleton.dio
.post(Api.SEARCH_RESULT + "$_page/json",
data: formData, options: _getOptions())
.then((response) {
callback(HotwordResultModel.fromMap(response.data));
}).catchError((e) {
errorback(e);
});
}
/// 登录
void login(Function callback, String _username, String _password) async {
FormData formData =
new FormData.from({"username": _username, "password": _password});
DioManager.singleton.dio
.post(Api.USER_LOGIN, data: formData, options: _getOptions())
.then((response) {
callback(UserModel(response.data), response);
});
}
/// 注册
void register(Function callback, String _username, String _password) async {
FormData formData = new FormData.from({
"username": _username,
"password": _password,
"repassword": _password
});
DioManager.singleton.dio
.post(Api.USER_REGISTER, data: formData, options: null)
.then((response) {
print(response.toString());
callback(UserModel(response.data));
});
}
/// 获取收藏列表
void getCollectionList(
Function callback, Function errorback, int _page) async {
DioManager.singleton.dio
.get(Api.COLLECTION_LIST + "$_page/json", options: _getOptions())
.then((response) {
callback(CollectionModel(response.data));
}).catchError((e) {
errorback(e);
});
}
/// 我的收藏-取消收藏
void cancelCollection(
Function callback, Function errorback, int _id, int _originId) async {
FormData formData = new FormData.from({"originId": _originId});
DioManager.singleton.dio
.post(Api.CANCEL_COLLECTION + "$_id/json",
data: formData, options: _getOptions())
.then((response) {
callback(BaseModel(response.data));
}).catchError((e) {
errorback(e);
});
}
///常用网站
void getCommonWebsite(Function callback, Function errorback) async {
DioManager.singleton.dio
.get(Api.COMMON_WEBSITE, options: _getOptions())
.then((response) {
callback(CommonWebsitModel.fromMap(response.data));
}).catchError((e) {
errorback(e);
});
}
void getPrettyGirl(Function callback, int _page) async {
DioManager.singleton.dio
.get("http://gank.io/api/data/福利/10/" + "$_page")
.then((response) {
callback(PrettyModel.fromMap(response.data));
});
}
/// 取消网站收藏
void cancelWebsiteCollectionList(Function callback, int _id) async {
FormData formData = new FormData.from({
"id": _id,
});
DioManager.singleton.dio
.post(Api.CANCEL_WEBSITE_COLLECTION,
data: formData, options: _getOptions())
.then((response) {
callback(BaseModel(response.data));
});
}
Options _getOptions() {
Map map = new Map();
List cookies = User().cookie;
map["Cookie"] = cookies.toString();
return Options(headers: map);
}
}
================================================
FILE: lib/http/dio_manager.dart
================================================
import 'dart:io';
import 'package:dio/dio.dart';
class DioManager {
Dio _dio;
DioManager._internal() {
_dio = new Dio();
(_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(client) {
client.badCertificateCallback =
(X509Certificate cert, String host, int port) {
return true;
};
};
}
static DioManager singleton = DioManager._internal();
factory DioManager() => singleton;
get dio {
return _dio;
}
}
================================================
FILE: lib/loading.dart
================================================
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:wanandroid_ngu/app.dart';
//加载页面
class LoadingPage extends StatefulWidget {
@override
_LoadingState createState() => new _LoadingState();
}
class _LoadingState extends State {
@override
void initState(){
super.initState();
//在加载页面停顿2秒
new Future.delayed(Duration(seconds: 2),(){
_getHasSkip();
});
}
void _getHasSkip ()async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool hasSkip = prefs.getBool("hasSkip");
if(hasSkip==null||!hasSkip){
Navigator.of(context).pushReplacementNamed("splash");
}else {
Navigator.of(context).pushAndRemoveUntil(
new MaterialPageRoute(
builder: (context) => App()),
(route) => route == null);
}
}
@override
Widget build(BuildContext context) {
return new Center(
child: Stack(
children: [
//加载页面居中背景图 使用cover模式
Image.asset("images/loading.png",fit: BoxFit.cover,),
],
),
);
}
}
================================================
FILE: lib/main.dart
================================================
import 'package:flutter/material.dart';
import 'package:wanandroid_ngu/common/application.dart';
import 'package:wanandroid_ngu/common/user.dart';
import 'package:wanandroid_ngu/event/change_theme_event.dart';
import 'package:wanandroid_ngu/splash_screen.dart';
import 'package:wanandroid_ngu/util/theme_util.dart';
import 'package:wanandroid_ngu/util/utils.dart';
import './app.dart';
import './loading.dart';
import 'dart:io';
import 'package:flutter/services.dart';
void main() {
getLoginInfo();
runApp(MyApp());
if (Platform.isAndroid) {
// 以下两行 设置android状态栏为透明的沉浸。写在组件渲染之后,是为了在渲染后进行set赋值,覆盖状态栏,写在渲染之前MaterialApp组件会覆盖掉这个值。
SystemUiOverlayStyle systemUiOverlayStyle =
SystemUiOverlayStyle(statusBarColor: Colors.transparent);
SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
}
}
Future getLoginInfo() async {
User.singleton.getUserInfo();
}
class MyApp extends StatefulWidget {
@override
State createState() {
return MyAppState();
}
}
class MyAppState extends State {
Color themeColor = ThemeUtils.currentColorTheme;
@override
void initState() {
super.initState();
Utils.getColorThemeIndex().then((index) {
print('color theme index = $index');
if (index != null) {
ThemeUtils.currentColorTheme = ThemeUtils.supportColors[index];
Application.eventBus
.fire(new ChangeThemeEvent(ThemeUtils.supportColors[index]));
}
});
Application.eventBus.on().listen((event) {
setState(() {
themeColor = event.color;
});
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "玩Android",
debugShowCheckedModeBanner: false,
theme:
new ThemeData(primaryColor: themeColor, brightness: Brightness.light),
routes: {
"app": (BuildContext context) => new App(),
"splash": (BuildContext context) => new SplashScreen(),
},
home: new LoadingPage(),
);
}
}
================================================
FILE: lib/model/article_model.dart
================================================
import 'dart:convert' show json;
class ArticleModel {
int errorCode;
String errorMsg;
Data data;
ArticleModel.fromParams({this.errorCode, this.errorMsg, this.data});
factory ArticleModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new ArticleModel.fromJson(json.decode(jsonStr)) : new ArticleModel.fromJson(jsonStr);
ArticleModel.fromJson(jsonRes) {
errorCode = jsonRes['errorCode'];
errorMsg = jsonRes['errorMsg'];
data = jsonRes['data'] == null ? null : new Data.fromJson(jsonRes['data']);
}
@override
String toString() {
return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
}
}
class Data {
int curPage;
int offset;
int pageCount;
int size;
int total;
bool over;
List datas;
Data.fromParams({this.curPage, this.offset, this.pageCount, this.size, this.total, this.over, this.datas});
Data.fromJson(jsonRes) {
curPage = jsonRes['curPage'];
offset = jsonRes['offset'];
pageCount = jsonRes['pageCount'];
size = jsonRes['size'];
total = jsonRes['total'];
over = jsonRes['over'];
datas = jsonRes['datas'] == null ? null : [];
for (var datasItem in datas == null ? [] : jsonRes['datas']){
datas.add(datasItem == null ? null : new Article.fromJson(datasItem));
}
}
@override
String toString() {
return '{"curPage": $curPage,"offset": $offset,"pageCount": $pageCount,"size": $size,"total": $total,"over": $over,"datas": $datas}';
}
}
class Article {
int chapterId;
int courseId;
int id;
int publishTime;
int superChapterId;
int type;
int userId;
int visible;
int zan;
bool collect;
bool fresh;
String apkLink;
String author;
String chapterName;
String desc;
String envelopePic;
String link;
String niceDate;
String origin;
String projectLink;
String superChapterName;
String title;
List tags;
Article.fromParams({this.chapterId, this.courseId, this.id, this.publishTime, this.superChapterId, this.type, this.userId, this.visible, this.zan, this.collect, this.fresh, this.apkLink, this.author, this.chapterName, this.desc, this.envelopePic, this.link, this.niceDate, this.origin, this.projectLink, this.superChapterName, this.title, this.tags});
Article.fromJson(jsonRes) {
chapterId = jsonRes['chapterId'];
courseId = jsonRes['courseId'];
id = jsonRes['id'];
publishTime = jsonRes['publishTime'];
superChapterId = jsonRes['superChapterId'];
type = jsonRes['type'];
userId = jsonRes['userId'];
visible = jsonRes['visible'];
zan = jsonRes['zan'];
collect = jsonRes['collect'];
fresh = jsonRes['fresh'];
apkLink = jsonRes['apkLink'];
author = jsonRes['author'];
chapterName = jsonRes['chapterName'];
desc = jsonRes['desc'];
envelopePic = jsonRes['envelopePic'];
link = jsonRes['link'];
niceDate = jsonRes['niceDate'];
origin = jsonRes['origin'];
projectLink = jsonRes['projectLink'];
superChapterName = jsonRes['superChapterName'];
title = jsonRes['title'];
tags = jsonRes['tags'] == null ? null : [];
for (var tagsItem in tags == null ? [] : jsonRes['tags']){
tags.add(tagsItem == null ? null : new Tag.fromJson(tagsItem));
}
}
@override
String toString() {
return '{"chapterId": $chapterId,"courseId": $courseId,"id": $id,"publishTime": $publishTime,"superChapterId": $superChapterId,"type": $type,"userId": $userId,"visible": $visible,"zan": $zan,"collect": $collect,"fresh": $fresh,"apkLink": ${apkLink != null?'${json.encode(apkLink)}':'null'},"author": ${author != null?'${json.encode(author)}':'null'},"chapterName": ${chapterName != null?'${json.encode(chapterName)}':'null'},"desc": ${desc != null?'${json.encode(desc)}':'null'},"envelopePic": ${envelopePic != null?'${json.encode(envelopePic)}':'null'},"link": ${link != null?'${json.encode(link)}':'null'},"niceDate": ${niceDate != null?'${json.encode(niceDate)}':'null'},"origin": ${origin != null?'${json.encode(origin)}':'null'},"projectLink": ${projectLink != null?'${json.encode(projectLink)}':'null'},"superChapterName": ${superChapterName != null?'${json.encode(superChapterName)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'},"tags": $tags}';
}
}
class Tag {
String name;
String url;
Tag.fromParams({this.name, this.url});
Tag.fromJson(jsonRes) {
name = jsonRes['name'];
url = jsonRes['url'];
}
@override
String toString() {
return '{"name": ${name != null?'${json.encode(name)}':'null'},"url": ${url != null?'${json.encode(url)}':'null'}}';
}
}
================================================
FILE: lib/model/banner_model.dart
================================================
import 'dart:convert' show json;
class BannerModel {
int errorCode;
String errorMsg;
List data;
BannerModel.fromParams({this.errorCode, this.errorMsg, this.data});
factory BannerModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new BannerModel.fromJson(json.decode(jsonStr)) : new BannerModel.fromJson(jsonStr);
BannerModel.fromJson(jsonRes) {
errorCode = jsonRes['errorCode'];
errorMsg = jsonRes['errorMsg'];
data = jsonRes['data'] == null ? null : [];
for (var dataItem in data == null ? [] : jsonRes['data']){
data.add(dataItem == null ? null : new BannerData.fromJson(dataItem));
}
}
@override
String toString() {
return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
}
}
class BannerData {
int id;
int isVisible;
int order;
int type;
String desc;
String imagePath;
String title;
String url;
BannerData.fromParams({this.id, this.isVisible, this.order, this.type, this.desc, this.imagePath, this.title, this.url});
BannerData.fromJson(jsonRes) {
id = jsonRes['id'];
isVisible = jsonRes['isVisible'];
order = jsonRes['order'];
type = jsonRes['type'];
desc = jsonRes['desc'];
imagePath = jsonRes['imagePath'];
title = jsonRes['title'];
url = jsonRes['url'];
}
@override
String toString() {
return '{"id": $id,"isVisible": $isVisible,"order": $order,"type": $type,"desc": ${desc != null?'${json.encode(desc)}':'null'},"imagePath": ${imagePath != null?'${json.encode(imagePath)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'},"url": ${url != null?'${json.encode(url)}':'null'}}';
}
}
================================================
FILE: lib/model/base_model.dart
================================================
import 'dart:convert' show json;
class BaseModel {
int errorCode;
String errorMsg;
BaseModel.fromParams({ this.errorCode, this.errorMsg});
factory BaseModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new BaseModel.fromJson(json.decode(jsonStr)) : new BaseModel.fromJson(jsonStr);
BaseModel.fromJson(jsonRes) {
errorCode = jsonRes['errorCode'];
errorMsg = jsonRes['errorMsg'];
}
@override
String toString() {
return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'}}';
}
}
================================================
FILE: lib/model/collection_model.dart
================================================
import 'dart:convert' show json;
class CollectionModel {
int errorCode;
String errorMsg;
CollectionData data;
CollectionModel.fromParams({this.errorCode, this.errorMsg, this.data});
factory CollectionModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new CollectionModel.fromJson(json.decode(jsonStr)) : new CollectionModel.fromJson(jsonStr);
CollectionModel.fromJson(jsonRes) {
errorCode = jsonRes['errorCode'];
errorMsg = jsonRes['errorMsg'];
data = jsonRes['data'] == null ? null : new CollectionData.fromJson(jsonRes['data']);
}
@override
String toString() {
return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
}
}
class CollectionData {
int curPage;
int offset;
int pageCount;
int size;
int total;
bool over;
List datas;
CollectionData.fromParams({this.curPage, this.offset, this.pageCount, this.size, this.total, this.over, this.datas});
CollectionData.fromJson(jsonRes) {
curPage = jsonRes['curPage'];
offset = jsonRes['offset'];
pageCount = jsonRes['pageCount'];
size = jsonRes['size'];
total = jsonRes['total'];
over = jsonRes['over'];
datas = jsonRes['datas'] == null ? null : [];
for (var datasItem in datas == null ? [] : jsonRes['datas']){
datas.add(datasItem == null ? null : new Collection.fromJson(datasItem));
}
}
@override
String toString() {
return '{"curPage": $curPage,"offset": $offset,"pageCount": $pageCount,"size": $size,"total": $total,"over": $over,"datas": $datas}';
}
}
class Collection {
int chapterId;
int courseId;
int id;
int originId;
int publishTime;
int userId;
int visible;
int zan;
String author;
String chapterName;
String desc;
String envelopePic;
String link;
String niceDate;
String origin;
String title;
Collection.fromParams({this.chapterId, this.courseId, this.id, this.originId, this.publishTime, this.userId, this.visible, this.zan, this.author, this.chapterName, this.desc, this.envelopePic, this.link, this.niceDate, this.origin, this.title});
Collection.fromJson(jsonRes) {
chapterId = jsonRes['chapterId'];
courseId = jsonRes['courseId'];
id = jsonRes['id'];
originId = jsonRes['originId'];
publishTime = jsonRes['publishTime'];
userId = jsonRes['userId'];
visible = jsonRes['visible'];
zan = jsonRes['zan'];
author = jsonRes['author'];
chapterName = jsonRes['chapterName'];
desc = jsonRes['desc'];
envelopePic = jsonRes['envelopePic'];
link = jsonRes['link'];
niceDate = jsonRes['niceDate'];
origin = jsonRes['origin'];
title = jsonRes['title'];
}
@override
String toString() {
return '{"chapterId": $chapterId,"courseId": $courseId,"id": $id,"originId": ${origin != null?'${json.encode(origin)}':'null'}Id,"publishTime": $publishTime,"userId": $userId,"visible": $visible,"zan": $zan,"author": ${author != null?'${json.encode(author)}':'null'},"chapterName": ${chapterName != null?'${json.encode(chapterName)}':'null'},"desc": ${desc != null?'${json.encode(desc)}':'null'},"envelopePic": ${envelopePic != null?'${json.encode(envelopePic)}':'null'},"link": ${link != null?'${json.encode(link)}':'null'},"niceDate": ${niceDate != null?'${json.encode(niceDate)}':'null'},"origin": ${origin != null?'${json.encode(origin)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'}}';
}
}
================================================
FILE: lib/model/common_websit_model.dart
================================================
class CommonWebsitModel {
String errorMsg;
int errorCode;
List data;
static CommonWebsitModel fromMap(Map map) {
CommonWebsitModel common_websit_model = new CommonWebsitModel();
common_websit_model.errorMsg = map['errorMsg'];
common_websit_model.errorCode = map['errorCode'];
common_websit_model.data = DataListBean.fromMapList(map['data']);
return common_websit_model;
}
static List fromMapList(dynamic mapList) {
List list = new List(mapList.length);
for (int i = 0; i < mapList.length; i++) {
list[i] = fromMap(mapList[i]);
}
return list;
}
}
class DataListBean {
String icon;
String link;
String name;
int id;
int order;
int visible;
static DataListBean fromMap(Map map) {
DataListBean dataListBean = new DataListBean();
dataListBean.icon = map['icon'];
dataListBean.link = map['link'];
dataListBean.name = map['name'];
dataListBean.id = map['id'];
dataListBean.order = map['order'];
dataListBean.visible = map['visible'];
return dataListBean;
}
static List fromMapList(dynamic mapList) {
List list = new List(mapList.length);
for (int i = 0; i < mapList.length; i++) {
list[i] = fromMap(mapList[i]);
}
return list;
}
Map toMap() {
var map = Map();
map["icon"] = icon;
map["link"] = link;
map["name"] = name;
map["id"] = id;
map["web_order"] = order;
map["visible"] = visible;
if (id != null) {
map["id"] = id;
}
return map;
}
}
================================================
FILE: lib/model/common_website_model.dart
================================================
import 'dart:convert' show json;
class CommonWebsiteModel {
int errorCode;
String errorMsg;
List data;
CommonWebsiteModel.fromParams({this.errorCode, this.errorMsg, this.data});
factory CommonWebsiteModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new CommonWebsiteModel.fromJson(json.decode(jsonStr)) : new CommonWebsiteModel.fromJson(jsonStr);
CommonWebsiteModel.fromJson(jsonRes) {
errorCode = jsonRes['errorCode'];
errorMsg = jsonRes['errorMsg'];
data = jsonRes['data'] == null ? null : [];
for (var dataItem in data == null ? [] : jsonRes['data']){
data.add(dataItem == null ? null : new CommonWebsiteData.fromJson(dataItem));
}
}
@override
String toString() {
return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
}
}
class CommonWebsiteData {
int id;
int order;
int visible;
String icon;
String link;
String name;
CommonWebsiteData.fromParams({this.id, this.order, this.visible, this.icon, this.link, this.name});
CommonWebsiteData.fromJson(jsonRes) {
id = jsonRes['id'];
order = jsonRes['order'];
visible = jsonRes['visible'];
icon = jsonRes['icon'];
link = jsonRes['link'];
name = jsonRes['name'];
}
@override
String toString() {
return '{"id": $id,"order": $order,"visible": $visible,"icon": ${icon != null?'${json.encode(icon)}':'null'},"link": ${link != null?'${json.encode(link)}':'null'},"name": ${name != null?'${json.encode(name)}':'null'}}';
}
}
================================================
FILE: lib/model/hotword_model.dart
================================================
class HotwordModel {
String errorMsg;
int errorCode;
List data;
static HotwordModel fromMap(Map map) {
HotwordModel hotword_model = new HotwordModel();
hotword_model.errorMsg = map['errorMsg'];
hotword_model.errorCode = map['errorCode'];
hotword_model.data = DataListBean.fromMapList(map['data']);
return hotword_model;
}
static List fromMapList(dynamic mapList) {
List list = new List(mapList.length);
for (int i = 0; i < mapList.length; i++) {
list[i] = fromMap(mapList[i]);
}
return list;
}
}
class DataListBean {
String link;
String name;
int id;
int order;
int visible;
static DataListBean fromMap(Map map) {
DataListBean dataListBean = new DataListBean();
dataListBean.link = map['link'];
dataListBean.name = map['name'];
dataListBean.id = map['id'];
dataListBean.order = map['order'];
dataListBean.visible = map['visible'];
return dataListBean;
}
static List fromMapList(dynamic mapList) {
List list = new List(mapList.length);
for (int i = 0; i < mapList.length; i++) {
list[i] = fromMap(mapList[i]);
}
return list;
}
}
================================================
FILE: lib/model/hotword_result_model.dart
================================================
class HotwordResultModel {
String errorMsg;
int errorCode;
DataBean data;
static HotwordResultModel fromMap(Map map) {
HotwordResultModel hotword_result_model = new HotwordResultModel();
hotword_result_model.errorMsg = map['errorMsg'];
hotword_result_model.errorCode = map['errorCode'];
hotword_result_model.data = DataBean.fromMap(map['data']);
return hotword_result_model;
}
static List fromMapList(dynamic mapList) {
List list = new List(mapList.length);
for (int i = 0; i < mapList.length; i++) {
list[i] = fromMap(mapList[i]);
}
return list;
}
}
class DataBean {
bool over;
int curPage;
int offset;
int pageCount;
int size;
int total;
List datas;
static DataBean fromMap(Map map) {
DataBean dataBean = new DataBean();
dataBean.over = map['over'];
dataBean.curPage = map['curPage'];
dataBean.offset = map['offset'];
dataBean.pageCount = map['pageCount'];
dataBean.size = map['size'];
dataBean.total = map['total'];
dataBean.datas = DatasListBean.fromMapList(map['datas']);
return dataBean;
}
static List fromMapList(dynamic mapList) {
List list = new List(mapList.length);
for (int i = 0; i < mapList.length; i++) {
list[i] = fromMap(mapList[i]);
}
return list;
}
}
class DatasListBean {
String apkLink;
String author;
String chapterName;
String desc;
String envelopePic;
String link;
String niceDate;
String origin;
String projectLink;
String superChapterName;
String title;
bool collect;
bool fresh;
int chapterId;
int courseId;
int id;
int publishTime;
int superChapterId;
int type;
int userId;
int visible;
int zan;
List tags;
static DatasListBean fromMap(Map map) {
DatasListBean datasListBean = new DatasListBean();
datasListBean.apkLink = map['apkLink'];
datasListBean.author = map['author'];
datasListBean.chapterName = map['chapterName'];
datasListBean.desc = map['desc'];
datasListBean.envelopePic = map['envelopePic'];
datasListBean.link = map['link'];
datasListBean.niceDate = map['niceDate'];
datasListBean.origin = map['origin'];
datasListBean.projectLink = map['projectLink'];
datasListBean.superChapterName = map['superChapterName'];
datasListBean.title = map['title'];
datasListBean.collect = map['collect'];
datasListBean.fresh = map['fresh'];
datasListBean.chapterId = map['chapterId'];
datasListBean.courseId = map['courseId'];
datasListBean.id = map['id'];
datasListBean.publishTime = map['publishTime'];
datasListBean.superChapterId = map['superChapterId'];
datasListBean.type = map['type'];
datasListBean.userId = map['userId'];
datasListBean.visible = map['visible'];
datasListBean.zan = map['zan'];
datasListBean.tags = TagsListBean.fromMapList(map['tags']);
return datasListBean;
}
static List fromMapList(dynamic mapList) {
List list = new List(mapList.length);
for (int i = 0; i < mapList.length; i++) {
list[i] = fromMap(mapList[i]);
}
return list;
}
}
class TagsListBean {
String name;
String url;
static TagsListBean fromMap(Map map) {
TagsListBean tagsListBean = new TagsListBean();
tagsListBean.name = map['name'];
tagsListBean.url = map['url'];
return tagsListBean;
}
static List fromMapList(dynamic mapList) {
List list = new List(mapList.length);
for (int i = 0; i < mapList.length; i++) {
list[i] = fromMap(mapList[i]);
}
return list;
}
}
================================================
FILE: lib/model/navi_model.dart
================================================
import 'dart:convert' show json;
class NaviModel {
int errorCode;
String errorMsg;
List data;
NaviModel.fromParams({this.errorCode, this.errorMsg, this.data});
factory NaviModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new NaviModel.fromJson(json.decode(jsonStr)) : new NaviModel.fromJson(jsonStr);
NaviModel.fromJson(jsonRes) {
errorCode = jsonRes['errorCode'];
errorMsg = jsonRes['errorMsg'];
data = jsonRes['data'] == null ? null : [];
for (var dataItem in data == null ? [] : jsonRes['data']){
data.add(dataItem == null ? null : new NaviData.fromJson(dataItem));
}
}
@override
String toString() {
return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
}
}
class NaviData {
int cid;
String name;
List articles;
NaviData.fromParams({this.cid, this.name, this.articles});
NaviData.fromJson(jsonRes) {
cid = jsonRes['cid'];
name = jsonRes['name'];
articles = jsonRes['articles'] == null ? null : [];
for (var articlesItem in articles == null ? [] : jsonRes['articles']){
articles.add(articlesItem == null ? null : new NaviArticle.fromJson(articlesItem));
}
}
@override
String toString() {
return '{"cid": $cid,"name": ${name != null?'${json.encode(name)}':'null'},"articles": $articles}';
}
}
class NaviArticle {
int chapterId;
int courseId;
int id;
int publishTime;
int superChapterId;
int type;
int userId;
int visible;
int zan;
bool collect;
bool fresh;
String apkLink;
String author;
String chapterName;
String desc;
String envelopePic;
String link;
String niceDate;
String origin;
String projectLink;
String superChapterName;
String title;
List tags;
NaviArticle.fromParams({this.chapterId, this.courseId, this.id, this.publishTime, this.superChapterId, this.type, this.userId, this.visible, this.zan, this.collect, this.fresh, this.apkLink, this.author, this.chapterName, this.desc, this.envelopePic, this.link, this.niceDate, this.origin, this.projectLink, this.superChapterName, this.title, this.tags});
NaviArticle.fromJson(jsonRes) {
chapterId = jsonRes['chapterId'];
courseId = jsonRes['courseId'];
id = jsonRes['id'];
publishTime = jsonRes['publishTime'];
superChapterId = jsonRes['superChapterId'];
type = jsonRes['type'];
userId = jsonRes['userId'];
visible = jsonRes['visible'];
zan = jsonRes['zan'];
collect = jsonRes['collect'];
fresh = jsonRes['fresh'];
apkLink = jsonRes['apkLink'];
author = jsonRes['author'];
chapterName = jsonRes['chapterName'];
desc = jsonRes['desc'];
envelopePic = jsonRes['envelopePic'];
link = jsonRes['link'];
niceDate = jsonRes['niceDate'];
origin = jsonRes['origin'];
projectLink = jsonRes['projectLink'];
superChapterName = jsonRes['superChapterName'];
title = jsonRes['title'];
tags = jsonRes['tags'] == null ? null : [];
for (var tagsItem in tags == null ? [] : jsonRes['tags']){
tags.add(tagsItem);
}
}
@override
String toString() {
return '{"chapterId": $chapterId,"courseId": $courseId,"id": $id,"publishTime": $publishTime,"superChapterId": $superChapterId,"type": $type,"userId": $userId,"visible": $visible,"zan": $zan,"collect": $collect,"fresh": $fresh,"apkLink": ${apkLink != null?'${json.encode(apkLink)}':'null'},"author": ${author != null?'${json.encode(author)}':'null'},"chapterName": ${chapterName != null?'${json.encode(chapterName)}':'null'},"desc": ${desc != null?'${json.encode(desc)}':'null'},"envelopePic": ${envelopePic != null?'${json.encode(envelopePic)}':'null'},"link": ${link != null?'${json.encode(link)}':'null'},"niceDate": ${niceDate != null?'${json.encode(niceDate)}':'null'},"origin": ${origin != null?'${json.encode(origin)}':'null'},"projectLink": ${projectLink != null?'${json.encode(projectLink)}':'null'},"superChapterName": ${superChapterName != null?'${json.encode(superChapterName)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'},"tags": $tags}';
}
}
================================================
FILE: lib/model/pretty_model.dart
================================================
class PrettyModel {
bool error;
List results;
static PrettyModel fromMap(Map map) {
PrettyModel pretty_model = new PrettyModel();
pretty_model.error = map['error'];
pretty_model.results = ResultsListBean.fromMapList(map['results']);
return pretty_model;
}
static List fromMapList(dynamic mapList) {
List list = new List(mapList.length);
for (int i = 0; i < mapList.length; i++) {
list[i] = fromMap(mapList[i]);
}
return list;
}
}
class ResultsListBean {
String _id;
String createdAt;
String desc;
String publishedAt;
String source;
String type;
String url;
String who;
bool used;
static ResultsListBean fromMap(Map map) {
ResultsListBean resultsListBean = new ResultsListBean();
resultsListBean._id = map['_id'];
resultsListBean.createdAt = map['createdAt'];
resultsListBean.desc = map['desc'];
resultsListBean.publishedAt = map['publishedAt'];
resultsListBean.source = map['source'];
resultsListBean.type = map['type'];
resultsListBean.url = map['url'];
resultsListBean.who = map['who'];
resultsListBean.used = map['used'];
return resultsListBean;
}
static List fromMapList(dynamic mapList) {
List list = new List(mapList.length);
for (int i = 0; i < mapList.length; i++) {
list[i] = fromMap(mapList[i]);
}
return list;
}
}
================================================
FILE: lib/model/project_tree_model.dart
================================================
import 'dart:convert' show json;
class ProjectTreeModel {
int errorCode;
String errorMsg;
List data;
ProjectTreeModel.fromParams({this.errorCode, this.errorMsg, this.data});
factory ProjectTreeModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new ProjectTreeModel.fromJson(json.decode(jsonStr)) : new ProjectTreeModel.fromJson(jsonStr);
ProjectTreeModel.fromJson(jsonRes) {
errorCode = jsonRes['errorCode'];
errorMsg = jsonRes['errorMsg'];
data = jsonRes['data'] == null ? null : [];
for (var dataItem in data == null ? [] : jsonRes['data']){
data.add(dataItem == null ? null : new ProjectTreeData.fromJson(dataItem));
}
}
@override
String toString() {
return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
}
}
class ProjectTreeData {
int courseId;
int id;
int order;
int parentChapterId;
int visible;
bool userControlSetTop;
String name;
List children;
ProjectTreeData.fromParams({this.courseId, this.id, this.order, this.parentChapterId, this.visible, this.userControlSetTop, this.name, this.children});
ProjectTreeData.fromJson(jsonRes) {
courseId = jsonRes['courseId'];
id = jsonRes['id'];
order = jsonRes['order'];
parentChapterId = jsonRes['parentChapterId'];
visible = jsonRes['visible'];
userControlSetTop = jsonRes['userControlSetTop'];
name = jsonRes['name'];
children = jsonRes['children'] == null ? null : [];
for (var childrenItem in children == null ? [] : jsonRes['children']){
children.add(childrenItem);
}
}
@override
String toString() {
return '{"courseId": $courseId,"id": $id,"order": $order,"parentChapterId": $parentChapterId,"visible": $visible,"userControlSetTop": $userControlSetTop,"name": ${name != null?'${json.encode(name)}':'null'},"children": $children}';
}
}
================================================
FILE: lib/model/projectlist_model.dart
================================================
import 'dart:convert' show json;
class ProjectTreeListModel {
int errorCode;
String errorMsg;
ProjectTreeListData data;
ProjectTreeListModel.fromParams({this.errorCode, this.errorMsg, this.data});
factory ProjectTreeListModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new ProjectTreeListModel.fromJson(json.decode(jsonStr)) : new ProjectTreeListModel.fromJson(jsonStr);
ProjectTreeListModel.fromJson(jsonRes) {
errorCode = jsonRes['errorCode'];
errorMsg = jsonRes['errorMsg'];
data = jsonRes['data'] == null ? null : new ProjectTreeListData.fromJson(jsonRes['data']);
}
@override
String toString() {
return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
}
}
class ProjectTreeListData {
int curPage;
int offset;
int pageCount;
int size;
int total;
bool over;
List datas;
ProjectTreeListData.fromParams({this.curPage, this.offset, this.pageCount, this.size, this.total, this.over, this.datas});
ProjectTreeListData.fromJson(jsonRes) {
curPage = jsonRes['curPage'];
offset = jsonRes['offset'];
pageCount = jsonRes['pageCount'];
size = jsonRes['size'];
total = jsonRes['total'];
over = jsonRes['over'];
datas = jsonRes['datas'] == null ? null : [];
for (var datasItem in datas == null ? [] : jsonRes['datas']){
datas.add(datasItem == null ? null : new ProjectTreeListDatas.fromJson(datasItem));
}
}
@override
String toString() {
return '{"curPage": $curPage,"offset": $offset,"pageCount": $pageCount,"size": $size,"total": $total,"over": $over,"datas": $datas}';
}
}
class ProjectTreeListDatas {
int chapterId;
int courseId;
int id;
int publishTime;
int superChapterId;
int type;
int userId;
int visible;
int zan;
bool collect;
bool fresh;
String apkLink;
String author;
String chapterName;
String desc;
String envelopePic;
String link;
String niceDate;
String origin;
String projectLink;
String superChapterName;
String title;
List tags;
ProjectTreeListDatas.fromParams({this.chapterId, this.courseId, this.id, this.publishTime, this.superChapterId, this.type, this.userId, this.visible, this.zan, this.collect, this.fresh, this.apkLink, this.author, this.chapterName, this.desc, this.envelopePic, this.link, this.niceDate, this.origin, this.projectLink, this.superChapterName, this.title, this.tags});
ProjectTreeListDatas.fromJson(jsonRes) {
chapterId = jsonRes['chapterId'];
courseId = jsonRes['courseId'];
id = jsonRes['id'];
publishTime = jsonRes['publishTime'];
superChapterId = jsonRes['superChapterId'];
type = jsonRes['type'];
userId = jsonRes['userId'];
visible = jsonRes['visible'];
zan = jsonRes['zan'];
collect = jsonRes['collect'];
fresh = jsonRes['fresh'];
apkLink = jsonRes['apkLink'];
author = jsonRes['author'];
chapterName = jsonRes['chapterName'];
desc = jsonRes['desc'];
envelopePic = jsonRes['envelopePic'];
link = jsonRes['link'];
niceDate = jsonRes['niceDate'];
origin = jsonRes['origin'];
projectLink = jsonRes['projectLink'];
superChapterName = jsonRes['superChapterName'];
title = jsonRes['title'];
tags = jsonRes['tags'] == null ? null : [];
for (var tagsItem in tags == null ? [] : jsonRes['tags']){
tags.add(tagsItem == null ? null : new ProjectTreeListTag.fromJson(tagsItem));
}
}
@override
String toString() {
return '{"chapterId": $chapterId,"courseId": $courseId,"id": $id,"publishTime": $publishTime,"superChapterId": $superChapterId,"type": $type,"userId": $userId,"visible": $visible,"zan": $zan,"collect": $collect,"fresh": $fresh,"apkLink": ${apkLink != null?'${json.encode(apkLink)}':'null'},"author": ${author != null?'${json.encode(author)}':'null'},"chapterName": ${chapterName != null?'${json.encode(chapterName)}':'null'},"desc": ${desc != null?'${json.encode(desc)}':'null'},"envelopePic": ${envelopePic != null?'${json.encode(envelopePic)}':'null'},"link": ${link != null?'${json.encode(link)}':'null'},"niceDate": ${niceDate != null?'${json.encode(niceDate)}':'null'},"origin": ${origin != null?'${json.encode(origin)}':'null'},"projectLink": ${projectLink != null?'${json.encode(projectLink)}':'null'},"superChapterName": ${superChapterName != null?'${json.encode(superChapterName)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'},"tags": $tags}';
}
}
class ProjectTreeListTag {
String name;
String url;
ProjectTreeListTag.fromParams({this.name, this.url});
ProjectTreeListTag.fromJson(jsonRes) {
name = jsonRes['name'];
url = jsonRes['url'];
}
@override
String toString() {
return '{"name": ${name != null?'${json.encode(name)}':'null'},"url": ${url != null?'${json.encode(url)}':'null'}}';
}
}
================================================
FILE: lib/model/system_tree_content_model.dart
================================================
import 'dart:convert' show json;
class SystemTreeContentModel {
int errorCode;
String errorMsg;
SystemTreeContentData data;
SystemTreeContentModel.fromParams({this.errorCode, this.errorMsg, this.data});
factory SystemTreeContentModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new SystemTreeContentModel.fromJson(json.decode(jsonStr)) : new SystemTreeContentModel.fromJson(jsonStr);
SystemTreeContentModel.fromJson(jsonRes) {
errorCode = jsonRes['errorCode'];
errorMsg = jsonRes['errorMsg'];
data = jsonRes['data'] == null ? null : new SystemTreeContentData.fromJson(jsonRes['data']);
}
@override
String toString() {
return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
}
}
class SystemTreeContentData {
int curPage;
int offset;
int pageCount;
int size;
int total;
bool over;
List datas;
SystemTreeContentData.fromParams({this.curPage, this.offset, this.pageCount, this.size, this.total, this.over, this.datas});
SystemTreeContentData.fromJson(jsonRes) {
curPage = jsonRes['curPage'];
offset = jsonRes['offset'];
pageCount = jsonRes['pageCount'];
size = jsonRes['size'];
total = jsonRes['total'];
over = jsonRes['over'];
datas = jsonRes['datas'] == null ? null : [];
for (var datasItem in datas == null ? [] : jsonRes['datas']){
datas.add(datasItem == null ? null : new SystemTreeContentChild.fromJson(datasItem));
}
}
@override
String toString() {
return '{"curPage": $curPage,"offset": $offset,"pageCount": $pageCount,"size": $size,"total": $total,"over": $over,"datas": $datas}';
}
}
class SystemTreeContentChild {
int chapterId;
int courseId;
int id;
int publishTime;
int superChapterId;
int type;
int userId;
int visible;
int zan;
bool collect;
bool fresh;
String apkLink;
String author;
String chapterName;
String desc;
String envelopePic;
String link;
String niceDate;
String origin;
String projectLink;
String superChapterName;
String title;
List tags;
SystemTreeContentChild.fromParams({this.chapterId, this.courseId, this.id, this.publishTime, this.superChapterId, this.type, this.userId, this.visible, this.zan, this.collect, this.fresh, this.apkLink, this.author, this.chapterName, this.desc, this.envelopePic, this.link, this.niceDate, this.origin, this.projectLink, this.superChapterName, this.title, this.tags});
SystemTreeContentChild.fromJson(jsonRes) {
chapterId = jsonRes['chapterId'];
courseId = jsonRes['courseId'];
id = jsonRes['id'];
publishTime = jsonRes['publishTime'];
superChapterId = jsonRes['superChapterId'];
type = jsonRes['type'];
userId = jsonRes['userId'];
visible = jsonRes['visible'];
zan = jsonRes['zan'];
collect = jsonRes['collect'];
fresh = jsonRes['fresh'];
apkLink = jsonRes['apkLink'];
author = jsonRes['author'];
chapterName = jsonRes['chapterName'];
desc = jsonRes['desc'];
envelopePic = jsonRes['envelopePic'];
link = jsonRes['link'];
niceDate = jsonRes['niceDate'];
origin = jsonRes['origin'];
projectLink = jsonRes['projectLink'];
superChapterName = jsonRes['superChapterName'];
title = jsonRes['title'];
tags = jsonRes['tags'] == null ? null : [];
for (var tagsItem in tags == null ? [] : jsonRes['tags']){
tags.add(tagsItem);
}
}
@override
String toString() {
return '{"chapterId": $chapterId,"courseId": $courseId,"id": $id,"publishTime": $publishTime,"superChapterId": $superChapterId,"type": $type,"userId": $userId,"visible": $visible,"zan": $zan,"collect": $collect,"fresh": $fresh,"apkLink": ${apkLink != null?'${json.encode(apkLink)}':'null'},"author": ${author != null?'${json.encode(author)}':'null'},"chapterName": ${chapterName != null?'${json.encode(chapterName)}':'null'},"desc": ${desc != null?'${json.encode(desc)}':'null'},"envelopePic": ${envelopePic != null?'${json.encode(envelopePic)}':'null'},"link": ${link != null?'${json.encode(link)}':'null'},"niceDate": ${niceDate != null?'${json.encode(niceDate)}':'null'},"origin": ${origin != null?'${json.encode(origin)}':'null'},"projectLink": ${projectLink != null?'${json.encode(projectLink)}':'null'},"superChapterName": ${superChapterName != null?'${json.encode(superChapterName)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'},"tags": $tags}';
}
}
================================================
FILE: lib/model/system_tree_model.dart
================================================
import 'dart:convert' show json;
class SystemTreeModel {
int errorCode;
String errorMsg;
List data;
SystemTreeModel.fromParams({this.errorCode, this.errorMsg, this.data});
factory SystemTreeModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new SystemTreeModel.fromJson(json.decode(jsonStr)) : new SystemTreeModel.fromJson(jsonStr);
SystemTreeModel.fromJson(jsonRes) {
errorCode = jsonRes['errorCode'];
errorMsg = jsonRes['errorMsg'];
data = jsonRes['data'] == null ? null : [];
for (var dataItem in data == null ? [] : jsonRes['data']){
data.add(dataItem == null ? null : new SystemTreeData.fromJson(dataItem));
}
}
@override
String toString() {
return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
}
}
class SystemTreeData {
int courseId;
int id;
int order;
int parentChapterId;
int visible;
bool userControlSetTop;
String name;
List children;
SystemTreeData.fromParams({this.courseId, this.id, this.order, this.parentChapterId, this.visible, this.userControlSetTop, this.name, this.children});
SystemTreeData.fromJson(jsonRes) {
courseId = jsonRes['courseId'];
id = jsonRes['id'];
order = jsonRes['order'];
parentChapterId = jsonRes['parentChapterId'];
visible = jsonRes['visible'];
userControlSetTop = jsonRes['userControlSetTop'];
name = jsonRes['name'];
children = jsonRes['children'] == null ? null : [];
for (var childrenItem in children == null ? [] : jsonRes['children']){
children.add(childrenItem == null ? null : new SystemTreeChild.fromJson(childrenItem));
}
}
@override
String toString() {
return '{"courseId": $courseId,"id": $id,"order": $order,"parentChapterId": $parentChapterId,"visible": $visible,"userControlSetTop": $userControlSetTop,"name": ${name != null?'${json.encode(name)}':'null'},"children": $children}';
}
}
class SystemTreeChild {
int courseId;
int id;
int order;
int parentChapterId;
int visible;
bool userControlSetTop;
String name;
List children;
SystemTreeChild.fromParams({this.courseId, this.id, this.order, this.parentChapterId, this.visible, this.userControlSetTop, this.name, this.children});
SystemTreeChild.fromJson(jsonRes) {
courseId = jsonRes['courseId'];
id = jsonRes['id'];
order = jsonRes['order'];
parentChapterId = jsonRes['parentChapterId'];
visible = jsonRes['visible'];
userControlSetTop = jsonRes['userControlSetTop'];
name = jsonRes['name'];
children = jsonRes['children'] == null ? null : [];
for (var childrenItem in children == null ? [] : jsonRes['children']){
children.add(childrenItem);
}
}
@override
String toString() {
return '{"courseId": $courseId,"id": $id,"order": $order,"parentChapterId": $parentChapterId,"visible": $visible,"userControlSetTop": $userControlSetTop,"name": ${name != null?'${json.encode(name)}':'null'},"children": $children}';
}
}
================================================
FILE: lib/model/todo_item.dart
================================================
import 'package:flutter/material.dart';
class TodoItem extends StatelessWidget {
String _itemName;
String _dateCreated;
int _id;
TodoItem(this._itemName, this._dateCreated);
TodoItem.map(dynamic obj) {
this._itemName = obj["itemName"];
this._dateCreated = obj["dateCreated"];
this._id = obj["id"];
}
String get itemName => _itemName;
String get dateCreated => _dateCreated;
int get id => _id;
Map toMap() {
var map = Map();
map["itemName"] = _itemName;
map["dateCreated"] = _dateCreated;
if (_id != null) {
map["id"] = _id;
}
return map;
}
TodoItem.fromMap(Map map) {
this._itemName = map["itemName"];
this._dateCreated = map["dateCreated"];
this._id = map["id"];
}
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.all(8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//solve the overflow problem
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_itemName,
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 18.0),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
Container(
margin: const EdgeInsets.only(top: 10.0),
child: Text(
"Created on: $_dateCreated",
style: TextStyle(
color: Colors.black,
fontSize: 12.0,
fontStyle: FontStyle.italic),
),
),
],
),
)
],
),
);
}
}
================================================
FILE: lib/model/todolist_model.dart
================================================
import 'dart:convert' show json;
class TodoListModel {
int errorCode;
String errorMsg;
TodoListData data;
TodoListModel.fromParams({this.errorCode, this.errorMsg, this.data});
factory TodoListModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new TodoListModel.fromJson(json.decode(jsonStr)) : new TodoListModel.fromJson(jsonStr);
TodoListModel.fromJson(jsonRes) {
errorCode = jsonRes['errorCode'];
errorMsg = jsonRes['errorMsg'];
data = jsonRes['data'] == null ? null : new TodoListData.fromJson(jsonRes['data']);
}
@override
String toString() {
return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
}
}
class TodoListData {
int type;
List doneList;
List todoList;
TodoListData.fromParams({this.type, this.doneList, this.todoList});
TodoListData.fromJson(jsonRes) {
type = jsonRes['type'];
doneList = jsonRes['doneList'] == null ? null : [];
for (var doneListItem in doneList == null ? [] : jsonRes['doneList']){
doneList.add(doneListItem == null ? null : new TodoListDatas.fromJson(doneListItem));
}
todoList = jsonRes['todoList'] == null ? null : [];
for (var todoListItem in todoList == null ? [] : jsonRes['todoList']){
todoList.add(todoListItem == null ? null : new TodoListDatas.fromJson(todoListItem));
}
}
@override
String toString() {
return '{"type": $type,"doneList": $doneList,"todoList": $todoList}';
}
}
class TodoListDatas {
int date;
List todoList;
TodoListDatas.fromParams({this.date, this.todoList});
TodoListDatas.fromJson(jsonRes) {
date = jsonRes['date'];
todoList = jsonRes['todoList'] == null ? null : [];
for (var todoListItem in todoList == null ? [] : jsonRes['todoList']){
todoList.add(todoListItem == null ? null : new TodoData.fromJson(todoListItem));
}
}
@override
String toString() {
return '{"date": $date,"todoList": $todoList}';
}
}
class TodoData {
TodoData();
TodoData.origin(String title){
this.title = title;
}
int completeDate;
int date;
int id;
int priority;
int status;
int type;
int userId;
String completeDateStr;
String content;
String dateStr;
String title;
TodoData.fromParams({this.completeDate, this.date, this.id, this.priority, this.status, this.type, this.userId, this.completeDateStr, this.content, this.dateStr, this.title});
TodoData.fromJson(jsonRes) {
completeDate = jsonRes['completeDate'];
date = jsonRes['date'];
id = jsonRes['id'];
priority = jsonRes['priority'];
status = jsonRes['status'];
type = jsonRes['type'];
userId = jsonRes['userId'];
completeDateStr = jsonRes['completeDateStr'];
content = jsonRes['content'];
dateStr = jsonRes['dateStr'];
title = jsonRes['title'];
}
@override
String toString() {
return '{"completeDate": $completeDate,"date": $date,"id": $id,"priority": $priority,"status": $status,"type": $type,"userId": $userId,"completeDateStr": ${completeDateStr != null?'${json.encode(completeDateStr)}':'null'},"content": ${content != null?'${json.encode(content)}':'null'},"dateStr": ${dateStr != null?'${json.encode(dateStr)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'}}';
}
}
================================================
FILE: lib/model/user_model.dart
================================================
import 'dart:convert' show json;
class UserModel {
int errorCode;
String errorMsg;
UserData data;
UserModel.fromParams({this.errorCode, this.errorMsg, this.data});
factory UserModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new UserModel.fromJson(json.decode(jsonStr)) : new UserModel.fromJson(jsonStr);
UserModel.fromJson(jsonRes) {
errorCode = jsonRes['errorCode'];
errorMsg = jsonRes['errorMsg'];
data = jsonRes['data'] == null ? null : new UserData.fromJson(jsonRes['data']);
}
@override
String toString() {
return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
}
}
class UserData {
int id;
int type;
String email;
String icon;
String password;
String token;
String username;
List chapterTops;
List collectIds;
UserData.fromParams({this.id, this.type, this.email, this.icon, this.password, this.token, this.username, this.chapterTops, this.collectIds});
UserData.fromJson(jsonRes) {
id = jsonRes['id'];
type = jsonRes['type'];
email = jsonRes['email'];
icon = jsonRes['icon'];
password = jsonRes['password'];
token = jsonRes['token'];
username = jsonRes['username'];
chapterTops = jsonRes['chapterTops'] == null ? null : [];
for (var chapterTopsItem in chapterTops == null ? [] : jsonRes['chapterTops']){
chapterTops.add(chapterTopsItem);
}
collectIds = jsonRes['collectIds'] == null ? null : [];
for (var collectIdsItem in collectIds == null ? [] : jsonRes['collectIds']){
collectIds.add(collectIdsItem);
}
}
@override
String toString() {
return '{"id": $id,"type": $type,"email": ${email != null?'${json.encode(email)}':'null'},"icon": ${icon != null?'${json.encode(icon)}':'null'},"password": ${password != null?'${json.encode(password)}':'null'},"token": ${token != null?'${json.encode(token)}':'null'},"username": ${username != null?'${json.encode(username)}':'null'},"chapterTops": $chapterTops,"collectIds": $collectIds}';
}
}
================================================
FILE: lib/model/website_collection_model.dart
================================================
import 'dart:convert' show json;
class WebsiteCollectionModel {
int errorCode;
String errorMsg;
List data;
WebsiteCollectionModel.fromParams({this.errorCode, this.errorMsg, this.data});
factory WebsiteCollectionModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new WebsiteCollectionModel.fromJson(json.decode(jsonStr)) : new WebsiteCollectionModel.fromJson(jsonStr);
WebsiteCollectionModel.fromJson(jsonRes) {
errorCode = jsonRes['errorCode'];
errorMsg = jsonRes['errorMsg'];
data = jsonRes['data'] == null ? null : [];
for (var dataItem in data == null ? [] : jsonRes['data']){
data.add(dataItem == null ? null : new WebsiteCollectionData.fromJson(dataItem));
}
}
@override
String toString() {
return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
}
}
class WebsiteCollectionData {
int id;
int order;
int userId;
int visible;
String desc;
String icon;
String link;
String name;
WebsiteCollectionData.fromParams({this.id, this.order, this.userId, this.visible, this.desc, this.icon, this.link, this.name});
WebsiteCollectionData.fromJson(jsonRes) {
id = jsonRes['id'];
order = jsonRes['order'];
userId = jsonRes['userId'];
visible = jsonRes['visible'];
desc = jsonRes['desc'];
icon = jsonRes['icon'];
link = jsonRes['link'];
name = jsonRes['name'];
}
@override
String toString() {
return '{"id": $id,"order": $order,"userId": $userId,"visible": $visible,"desc": ${desc != null?'${json.encode(desc)}':'null'},"icon": ${icon != null?'${json.encode(icon)}':'null'},"link": ${link != null?'${json.encode(link)}':'null'},"name": ${name != null?'${json.encode(name)}':'null'}}';
}
}
================================================
FILE: lib/model/wx_article_content_model.dart
================================================
import 'dart:convert' show json;
class WxArticleContentModel {
int errorCode;
String errorMsg;
WxArticleContentData data;
WxArticleContentModel.fromParams({this.errorCode, this.errorMsg, this.data});
factory WxArticleContentModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new WxArticleContentModel.fromJson(json.decode(jsonStr)) : new WxArticleContentModel.fromJson(jsonStr);
WxArticleContentModel.fromJson(jsonRes) {
errorCode = jsonRes['errorCode'];
errorMsg = jsonRes['errorMsg'];
data = jsonRes['data'] == null ? null : new WxArticleContentData.fromJson(jsonRes['data']);
}
@override
String toString() {
return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
}
}
class WxArticleContentData {
int curPage;
int offset;
int pageCount;
int size;
int total;
bool over;
List datas;
WxArticleContentData.fromParams({this.curPage, this.offset, this.pageCount, this.size, this.total, this.over, this.datas});
WxArticleContentData.fromJson(jsonRes) {
curPage = jsonRes['curPage'];
offset = jsonRes['offset'];
pageCount = jsonRes['pageCount'];
size = jsonRes['size'];
total = jsonRes['total'];
over = jsonRes['over'];
datas = jsonRes['datas'] == null ? null : [];
for (var datasItem in datas == null ? [] : jsonRes['datas']){
datas.add(datasItem == null ? null : new WxArticleContentDatas.fromJson(datasItem));
}
}
@override
String toString() {
return '{"curPage": $curPage,"offset": $offset,"pageCount": $pageCount,"size": $size,"total": $total,"over": $over,"datas": $datas}';
}
}
class WxArticleContentDatas {
int chapterId;
int courseId;
int id;
int publishTime;
int superChapterId;
int type;
int userId;
int visible;
int zan;
bool collect;
bool fresh;
String apkLink;
String author;
String chapterName;
String desc;
String envelopePic;
String link;
String niceDate;
String origin;
String projectLink;
String superChapterName;
String title;
List tags;
WxArticleContentDatas.fromParams({this.chapterId, this.courseId, this.id, this.publishTime, this.superChapterId, this.type, this.userId, this.visible, this.zan, this.collect, this.fresh, this.apkLink, this.author, this.chapterName, this.desc, this.envelopePic, this.link, this.niceDate, this.origin, this.projectLink, this.superChapterName, this.title, this.tags});
WxArticleContentDatas.fromJson(jsonRes) {
chapterId = jsonRes['chapterId'];
courseId = jsonRes['courseId'];
id = jsonRes['id'];
publishTime = jsonRes['publishTime'];
superChapterId = jsonRes['superChapterId'];
type = jsonRes['type'];
userId = jsonRes['userId'];
visible = jsonRes['visible'];
zan = jsonRes['zan'];
collect = jsonRes['collect'];
fresh = jsonRes['fresh'];
apkLink = jsonRes['apkLink'];
author = jsonRes['author'];
chapterName = jsonRes['chapterName'];
desc = jsonRes['desc'];
envelopePic = jsonRes['envelopePic'];
link = jsonRes['link'];
niceDate = jsonRes['niceDate'];
origin = jsonRes['origin'];
projectLink = jsonRes['projectLink'];
superChapterName = jsonRes['superChapterName'];
title = jsonRes['title'];
tags = jsonRes['tags'] == null ? null : [];
for (var tagsItem in tags == null ? [] : jsonRes['tags']){
tags.add(tagsItem == null ? null : new WxArticleContentTags.fromJson(tagsItem));
}
}
@override
String toString() {
return '{"chapterId": $chapterId,"courseId": $courseId,"id": $id,"publishTime": $publishTime,"superChapterId": $superChapterId,"type": $type,"userId": $userId,"visible": $visible,"zan": $zan,"collect": $collect,"fresh": $fresh,"apkLink": ${apkLink != null?'${json.encode(apkLink)}':'null'},"author": ${author != null?'${json.encode(author)}':'null'},"chapterName": ${chapterName != null?'${json.encode(chapterName)}':'null'},"desc": ${desc != null?'${json.encode(desc)}':'null'},"envelopePic": ${envelopePic != null?'${json.encode(envelopePic)}':'null'},"link": ${link != null?'${json.encode(link)}':'null'},"niceDate": ${niceDate != null?'${json.encode(niceDate)}':'null'},"origin": ${origin != null?'${json.encode(origin)}':'null'},"projectLink": ${projectLink != null?'${json.encode(projectLink)}':'null'},"superChapterName": ${superChapterName != null?'${json.encode(superChapterName)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'},"tags": $tags}';
}
}
class WxArticleContentTags {
String name;
String url;
WxArticleContentTags.fromParams({this.name, this.url});
WxArticleContentTags.fromJson(jsonRes) {
name = jsonRes['name'];
url = jsonRes['url'];
}
@override
String toString() {
return '{"name": ${name != null?'${json.encode(name)}':'null'},"url": ${url != null?'${json.encode(url)}':'null'}}';
}
}
================================================
FILE: lib/model/wx_article_title_model.dart
================================================
import 'dart:convert' show json;
class WxArticleTitleModel {
int errorCode;
String errorMsg;
List data;
WxArticleTitleModel.fromParams({this.errorCode, this.errorMsg, this.data});
factory WxArticleTitleModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new WxArticleTitleModel.fromJson(json.decode(jsonStr)) : new WxArticleTitleModel.fromJson(jsonStr);
WxArticleTitleModel.fromJson(jsonRes) {
errorCode = jsonRes['errorCode'];
errorMsg = jsonRes['errorMsg'];
data = jsonRes['data'] == null ? null : [];
for (var dataItem in data == null ? [] : jsonRes['data']){
data.add(dataItem == null ? null : new WxArticleTitleData.fromJson(dataItem));
}
}
@override
String toString() {
return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
}
}
class WxArticleTitleData {
int courseId;
int id;
int order;
int parentChapterId;
int visible;
bool userControlSetTop;
String name;
List children;
WxArticleTitleData.fromParams({this.courseId, this.id, this.order, this.parentChapterId, this.visible, this.userControlSetTop, this.name, this.children});
WxArticleTitleData.fromJson(jsonRes) {
courseId = jsonRes['courseId'];
id = jsonRes['id'];
order = jsonRes['order'];
parentChapterId = jsonRes['parentChapterId'];
visible = jsonRes['visible'];
userControlSetTop = jsonRes['userControlSetTop'];
name = jsonRes['name'];
children = jsonRes['children'] == null ? null : [];
for (var childrenItem in children == null ? [] : jsonRes['children']){
children.add(childrenItem);
}
}
@override
String toString() {
return '{"courseId": $courseId,"id": $id,"order": $order,"parentChapterId": $parentChapterId,"visible": $visible,"userControlSetTop": $userControlSetTop,"name": ${name != null?'${json.encode(name)}':'null'},"children": $children}';
}
}
================================================
FILE: lib/splash_screen.dart
================================================
import 'package:flutter/material.dart';
import 'package:intro_slider/intro_slider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:wanandroid_ngu/app.dart';
class SplashScreen extends StatefulWidget {
@override
State createState() {
return new SplashScreenState() ;
}
}
class SplashScreenState extends State {
List slides = new List();
@override
void initState() {
super.initState();
slides.add(
new Slide(
title: "Flutter",
description:
"Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面。 Flutter可以与现有的代码一起工作。在全世界,Flutter正在被越来越多的开发者和组织使用,并且Flutter是完全免费、开源的。",
styleDescription: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontFamily: 'Raleway'),
marginDescription: EdgeInsets.only(left: 20.0, right: 20.0, top: 20.0, bottom: 70.0),
colorBegin: Color(0xffFFDAB9),
colorEnd: Color(0xff40E0D0),
directionColorBegin: Alignment.topLeft,
directionColorEnd: Alignment.bottomRight,
),
);
slides.add(
new Slide(
title: "Wanandroid",
description:
"这是一款使用Flutter写的WanAndroid客户端应用,在Android和IOS都完美运行,可以用来入门Flutter,简单明了,适合初学者,项目完全开源,如果本项目确实能够帮助到你学习Flutter,谢谢start,有问题请提交Issues,我会及时回复。",
styleDescription: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontFamily: 'Raleway'),
marginDescription: EdgeInsets.only(left: 20.0, right: 20.0, top: 20.0, bottom: 70.0),
colorBegin: Color(0xffFFFACD),
colorEnd: Color(0xffFF6347),
directionColorBegin: Alignment.topLeft,
directionColorEnd: Alignment.bottomRight,
),
);
slides.add(
new Slide(
title: "Welcome",
description:
"赠人玫瑰,手有余香;\n分享技术,传递快乐。",
styleDescription: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontFamily: 'Raleway'),
marginDescription: EdgeInsets.only(left: 20.0, right: 20.0, top: 20.0, bottom: 70.0),
colorBegin: Color(0xffFFA500),
colorEnd: Color(0xff7FFFD4),
directionColorBegin: Alignment.topLeft,
directionColorEnd: Alignment.bottomRight,
),
);
}
void onDonePress() {
_setHasSkip();
Navigator.of(context).pushAndRemoveUntil(
new MaterialPageRoute(
builder: (context) => App()),
(route) => route == null);
}
void onSkipPress() {
_setHasSkip();
Navigator.of(context).pushAndRemoveUntil(
new MaterialPageRoute(
builder: (context) => App()),
(route) => route == null);
}
void _setHasSkip ()async {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setBool("hasSkip", true);
}
@override
Widget build(BuildContext context) {
return IntroSlider(
slides: this.slides,
onDonePress: this.onDonePress,
//renderSkipBtn: this.onSkipPress,
nameSkipBtn: "跳过",
nameNextBtn: "下一页",
nameDoneBtn: "进入",
);
}
}
================================================
FILE: lib/ui/drawer/about.dart
================================================
import 'package:flutter/material.dart';
import 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';
class AboutMePage extends StatefulWidget {
@override
State createState() {
return AboutMePageState();
}
}
class AboutMePageState extends State {
TextStyle textStyle = new TextStyle(
color: Colors.blue,
decoration: new TextDecoration.combine([TextDecoration.underline]));
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("关于作者"),
),
body: new Container(
padding: EdgeInsets.fromLTRB(35, 50, 35, 15),
child: new Column(
children: [
CircleAvatar(
minRadius: 60,
maxRadius: 60,
backgroundImage: AssetImage('images/head.jpg'),
),
Padding(padding: EdgeInsets.only(top: 30)),
new Text("基于Google Flutter的玩Android客户端"),
Container(
margin: const EdgeInsets.fromLTRB(0.0, 80.0, 0.0, 0.0),
child: new Row(
children: [
new Text("邮箱:"),
new Text(
"zw20082012@126.com",
style: TextStyle(color: Colors.blue),
),
],
),
),
GestureDetector(
child: new Container(
margin: const EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 0.0),
child: new Row(
children: [
new Text("CSDN:"),
new Text(
"https://blog.csdn.net/zw2008224044",
style: textStyle,
),
],
),
),
onTap: () {
Navigator.of(context)
.push(new MaterialPageRoute(builder: (ctx) {
return new WebViewPage(
title: "ngu2008",
url: "https://blog.csdn.net/zw2008224044");
}));
},
),
GestureDetector(
child: new Container(
margin: const EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 0.0),
child: new Row(
children: [
new Text("GitHub:"),
new Text(
"https://github.com/ngu2008/wanandroid",
style: textStyle,
),
],
),
),
onTap: () {
Navigator.of(context)
.push(new MaterialPageRoute(builder: (ctx) {
return new WebViewPage(
title: "GitHub",
url: "https://github.com/ngu2008/wanandroid");
}));
},
),
Expanded(child: Container(), flex: 1),
new Text(
"本项目仅供学习使用,不得用作商业目的",
style: new TextStyle(fontSize: 12.0),
)
],
),
));
}
}
================================================
FILE: lib/ui/drawer/collctions.dart
================================================
import 'dart:ui';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:wanandroid_ngu/base/_base_widget.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/base_model.dart';
import 'package:wanandroid_ngu/model/collection_model.dart';
import 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';
class CollectionsPage extends BaseWidget {
@override
BaseWidgetState getState() {
return CollectionsPageState();
}
}
class CollectionsPageState extends BaseWidgetState {
List _datas = new List();
ScrollController _scrollController = ScrollController(); //listview的控制器
int _page = 0; //加载的页数
bool showToTopBtn = false; //是否显示“返回到顶部”按钮
Future getData() async {
_page = 0;
ApiService().getCollectionList((
CollectionModel _collectionModel,
) {
if (_collectionModel.errorCode==0) {//成功
if (_collectionModel.data.datas.length > 0) {//有数据
showContent();
setState(() {
_datas.clear();
_datas.addAll(_collectionModel.data.datas);
});
} else {//数据为空
showEmpty();
}
}else{
Fluttertoast.showToast(msg: _collectionModel.errorMsg);
}
}, (DioError error) {//发生错误
print(error.response);
setState(() {
showError();
});
}, _page);
}
Future _getMore() async {
_page++;
ApiService().getCollectionList((
CollectionModel _collectionModel,
){
if (_collectionModel.errorCode==0) {//成功
showContent();
if (_collectionModel.data.datas.length > 0) {//有数据
setState(() {
_datas.addAll(_collectionModel.data.datas);
});
} else {//数据为空
Fluttertoast.showToast(msg:"没有更多数据了");
}
}else{
Fluttertoast.showToast(msg: _collectionModel.errorMsg);
}
}, (DioError error) {
print(error.response);
setState(() {
showError();
});
}, _page);
}
@override
void initState() {
super.initState();
showloading();
getData();
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
_getMore();
}
});
_scrollController.addListener(() {
//当前位置是否超过屏幕高度
if (_scrollController.offset < 200 && showToTopBtn) {
setState(() {
showToTopBtn = false;
});
} else if (_scrollController.offset >= 200 && showToTopBtn == false) {
setState(() {
showToTopBtn = true;
});
}
});
}
@override
Widget getContentWidget(BuildContext context) {
return Scaffold(
body: RefreshIndicator(
displacement: 15,
child: ListView.separated(
//普通项
itemBuilder: _renderRow,
//插入项
separatorBuilder: (BuildContext context, int index) {
return Container(
height: 0.5,
color: Colors.black26,
);
},
controller: _scrollController,
itemCount: _datas.length + 1,
),
onRefresh: getData),
floatingActionButton: !showToTopBtn ? null : FloatingActionButton(
child: Icon(Icons.arrow_upward),
onPressed: () {
//返回到顶部时执行动画
_scrollController.animateTo(.0,
duration: Duration(milliseconds: 200),
curve: Curves.ease
);
}
),
);
}
Future _cancelCollection(int _position, int _id, int _originId) async {
ApiService().cancelCollection((BaseModel _baseModel) {
if (_baseModel.errorCode == 0) {
_datas.removeAt(_position);
}
Scaffold.of(context).showSnackBar(new SnackBar(
content: Text("移除成功!"),
));
setState(() {});
}, (DioError error) {
print(error.response);
setState(() {
showError();
});
}, _id, _originId);
}
Widget _renderRow(BuildContext context, int index) {
if (index < _datas.length) {
return _itemView(context, index);
}
return null;
}
Widget _itemView(BuildContext context, int index) {
return InkWell(
child: _slideRow(index, _datas[index]),
onTap: () {
Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
return new WebViewPage(
title: _datas[index].title, url: _datas[index].link);
}));
},
);
}
Widget _slideRow(int index, Collection item) {
return new Slidable(
delegate: new SlidableDrawerDelegate(),
actionExtentRatio: 0.25,
child: _newsRow(item),
secondaryActions: [
new IconSlideAction(
caption: '取消收藏',
color: Colors.red,
icon: Icons.delete,
onTap: () {
_cancelCollection(index, item.id, item.originId);
},
),
],
);
}
Widget _newsRow(Collection item) {
return new Column(
children: [
new Container(
padding: EdgeInsets.fromLTRB(16, 16, 16, 8),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"作者:" + item.author,
style: TextStyle(fontSize: 12),
),
new Expanded(
child: new Text(
"收藏时间:" + item.niceDate,
style: TextStyle(fontSize: 12),
textAlign: TextAlign.right,
),
),
],
)),
Container(
padding: EdgeInsets.fromLTRB(16, 0, 16, 0),
child: Row(
children: [
Expanded(
child: Text(
item.title,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: const Color(0xFF3D4E5F),
),
textAlign: TextAlign.left,
))
],
)),
Container(
padding: EdgeInsets.fromLTRB(16, 8, 16, 16),
child: Row(
children: [
item.chapterName.isNotEmpty
? Expanded(
child: Text(
"分类:" + item.chapterName,
style: TextStyle(fontSize: 12),
),
)
: Text("")
],
)),
],
);
}
@override
void dispose() {
super.dispose();
_scrollController.dispose();
}
@override
void onClickErrorWidget() {
showloading();
getData();
}
@override
AppBar getAppBar() {
return AppBar(
title: Text("我的收藏"),
elevation: 0.4,
);
}
}
================================================
FILE: lib/ui/drawer/common_website.dart
================================================
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:wanandroid_ngu/base/_base_widget.dart';
import 'package:wanandroid_ngu/db/db_helper.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/common_websit_model.dart';
import 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';
class CommonWebsitePage extends BaseWidget {
@override
BaseWidgetState getState() {
return CommonWebsitePageState();
}
}
class CommonWebsitePageState extends BaseWidgetState {
List _datas = new List();
ScrollController _scrollController = ScrollController();
var db = DatabaseHelper();
bool showToTopBtn = false; //是否显示“返回到顶部”按钮
Future _getData() async {
ApiService().getCommonWebsite((CommonWebsitModel commonWebsitModel) {
if (commonWebsitModel.errorCode == 0) {
var datas = commonWebsitModel.data;
if (datas != null && datas.length > 0) {
showContent();
setState(() {
_datas = datas;
});
//清空表数据
db.clear();
//数据存入数据库
for (int i = 0; i < datas.length; i++) {
db.saveItem(datas[i]);
}
} else {
showEmpty();
}
} else {
Fluttertoast.showToast(msg: commonWebsitModel.errorMsg);
}
}, (DioError error) {
//发生错误
print(error.response);
// setState(() {
// showError();
// });
});
}
_getDataFromDb() async {
List datas = await db.getTotalList();
if (datas.length > 0) {
datas.forEach((item) {
DataListBean dataListBean = DataListBean.fromMap(item);
_datas.add(dataListBean);
});
setState(() {
});
} else {
showloading();
}
}
@override
void initState() {
super.initState();
// showloading();
//读取数据库的数据
_getDataFromDb();
_getData();
_scrollController.addListener(() {
//当前位置是否超过屏幕高度
if (_scrollController.offset < 200 && showToTopBtn) {
setState(() {
showToTopBtn = false;
});
} else if (_scrollController.offset >= 200 && showToTopBtn == false) {
setState(() {
showToTopBtn = true;
});
}
});
}
Widget _getBodyWidget(List datas) {
return RefreshIndicator(
displacement: 15,
onRefresh: _getData,
child: GridView.builder(
padding: EdgeInsets.all(15),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, //每行2列
mainAxisSpacing: 15,
crossAxisSpacing: 15,
childAspectRatio: 1.333 //
),
controller: _scrollController,
itemCount: _datas.length,
itemBuilder: _renderItem),
);
}
Color _getColor(int index) {
switch (index % 8) {
case 0:
return const Color(0xFFfb6e52);
case 1:
return const Color(0xFFa1d46f);
case 2:
return const Color(0xFF5cc0e2);
case 3:
return const Color(0xFFffbb44);
case 4:
return const Color(0xFFef6666);
case 5:
return const Color(0xFFf8d19e);
case 6:
return const Color(0xFF48cfae);
case 7:
return const Color(0xFFaa9ef8);
}
}
Widget _renderItem(BuildContext context, int index) {
return new InkWell(
onTap: () {
Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
return new WebViewPage(
title: _datas[index].name, url: _datas[index].link);
}));
},
child: Container(
padding: EdgeInsets.only(top: 25, left: 25),
color: _getColor(index),
child: Text(
_datas[index].name,
style: TextStyle(
color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold),
),
),
);
}
@override
AppBar getAppBar() {
return AppBar(
title: Text("常用网站"),
elevation: 0.4,
);
}
@override
Widget getContentWidget(BuildContext context) {
return Scaffold(
body: _getBodyWidget(_datas),
floatingActionButton: !showToTopBtn
? null
: FloatingActionButton(
child: Icon(Icons.arrow_upward),
onPressed: () {
//返回到顶部时执行动画
_scrollController.animateTo(.0,
duration: Duration(milliseconds: 200), curve: Curves.ease);
}),
);
}
@override
void onClickErrorWidget() {
showloading();
_getData();
}
@override
void dispose() {
super.dispose();
}
}
================================================
FILE: lib/ui/drawer/drawer.dart
================================================
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:share/share.dart';
import 'package:wanandroid_ngu/common/application.dart';
import 'package:wanandroid_ngu/common/user.dart';
import 'package:wanandroid_ngu/event/change_theme_event.dart';
import 'package:wanandroid_ngu/event/login_event.dart';
import 'package:wanandroid_ngu/ui/drawer/about.dart';
import 'package:wanandroid_ngu/ui/drawer/collctions.dart';
import 'package:wanandroid_ngu/ui/drawer/common_website.dart';
import 'package:wanandroid_ngu/ui/drawer/pretty.dart';
import 'package:wanandroid_ngu/ui/login/login_page.dart';
import 'package:wanandroid_ngu/util/theme_util.dart';
import 'package:wanandroid_ngu/util/utils.dart';
class DrawerPage extends StatefulWidget {
@override
State createState() {
return new DrawerPageState();
}
}
class DrawerPageState extends State {
bool isLogin = false;
String username = "未登录";
@override
void initState() {
super.initState();
this.registerLoginEvent();
if (null != User.singleton.userName) {
isLogin = true;
username = User.singleton.userName;
}
}
void registerLoginEvent() {
Application.eventBus.on().listen((event) {
changeUI();
});
}
changeUI() async {
setState(() {
isLogin = true;
username = User.singleton.userName;
});
}
@override
Widget build(BuildContext context) {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
UserAccountsDrawerHeader(
accountName: InkWell(
child: Text(username,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)),
onTap: () {
if (!isLogin) {
Navigator.of(context)
.push(new MaterialPageRoute(builder: (context) {
return new LoginPage();
}));
}
},
),
currentAccountPicture: InkWell(
child: CircleAvatar(
backgroundImage: AssetImage('images/head.jpg'),
),
onTap: () {
if (!isLogin) {
Navigator.of(context)
.push(new MaterialPageRoute(builder: (context) {
return new LoginPage();
}));
}
},
),
),
ListTile(
title: Text(
'我的收藏',
textAlign: TextAlign.left,
),
leading: Icon(Icons.collections, size: 22.0),
onTap: () {
if (isLogin) {
onCollectionClick();
} else {
onLoginClick();
}
},
),
ListTile(
title: Text(
'常用网站',
textAlign: TextAlign.left,
),
leading: Icon(Icons.web, size: 22.0),
onTap: () {
Navigator.of(context)
.push(new MaterialPageRoute(builder: (context) {
return new CommonWebsitePage();
}));
},
),
ListTile(
title: Text(
'主题',
textAlign: TextAlign.left,
),
leading: Icon(Icons.settings, size: 22.0),
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return new SimpleDialog(
title: Text("设置主题"),
children: ThemeUtils.supportColors.map((Color color) {
return new SimpleDialogOption(
child: Container(
padding: EdgeInsets.fromLTRB(10, 8, 10, 8),
height: 35,
color: color,
),
onPressed: () {
ThemeUtils.currentColorTheme = color;
Utils.setColorTheme(
ThemeUtils.supportColors.indexOf(color));
changeColorTheme(color);
Navigator.of(context).pop();
},
);
}).toList(),
);
},
);
},
),
ListTile(
title: Text(
'分享',
textAlign: TextAlign.left,
),
leading: Icon(Icons.share, size: 22.0),
onTap: () {
Share.share(
'给你推荐一个特别好玩的应用玩安卓客户端,点击下载:https://www.pgyer.com/haFL');
},
),
ListTile(
title: Text(
'妹子图',
textAlign: TextAlign.left,
),
leading: Icon(Icons.directions_bike, size: 22.0),
onTap: () {
Navigator.of(context)
.push(new MaterialPageRoute(builder: (context) {
return new PrettyPage();
}));
},
),
ListTile(
title: Text(
'关于作者',
textAlign: TextAlign.left,
),
leading: Icon(Icons.info, size: 22.0),
onTap: () {
Navigator.of(context)
.push(new MaterialPageRoute(builder: (context) {
return new AboutMePage();
}));
},
),
logoutWidget()
],
),
);
}
Widget logoutWidget() {
if (User.singleton.userName != null) {
return ListTile(
title: Text(
'退出登录',
textAlign: TextAlign.left,
),
leading: Icon(Icons.power_settings_new, size: 22.0),
onTap: () {
User.singleton.clearUserInfor();
setState(() {
isLogin = false;
username = "未登录";
});
},
);
} else {
return SizedBox(
height: 0,
);
}
}
void onCollectionClick() async {
await Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
return new CollectionsPage();
}));
}
void onLoginClick() async {
await Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
return new LoginPage();
}));
}
changeColorTheme(Color c) {
Application.eventBus.fire(new ChangeThemeEvent(c));
}
}
================================================
FILE: lib/ui/drawer/pretty.dart
================================================
import 'package:flutter/material.dart';
import 'package:photo_view/photo_view_gallery.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/pretty_model.dart';
class PrettyPage extends StatefulWidget {
@override
State createState() {
return new PrettyPageState();
}
}
class PrettyPageState extends State {
//当前页数据
List _datas = new List();
//所有的照片数据
List photos = new List();
int _page = 1;
Future _getData() async {
ApiService().getPrettyGirl((PrettyModel prettyModel) {
setState(() {
_datas = prettyModel.results;
for (int i = 0; i < _datas.length; i++) {
PhotoViewGalleryPageOptions pageOptions = PhotoViewGalleryPageOptions(
imageProvider: NetworkImage(_datas[i].url));
photos.add(pageOptions);
}
});
}, _page);
}
@override
void initState() {
super.initState();
_getData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("妹子图"),
),
body: Container(
child: PhotoViewGallery(
onPageChanged: (int index) {
if(index==photos.length-1){//加载到最有一页
_page++;
_getData();
}
},
pageOptions: photos,
backgroundDecoration: BoxDecoration(color: Colors.black87),
)),
);
}
}
================================================
FILE: lib/ui/home/banner.dart
================================================
import 'package:flutter/material.dart';
import 'package:flutter_swiper/flutter_swiper.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/banner_model.dart';
import 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';
class BannerWidget extends StatefulWidget {
@override
State createState() {
return BannerWidgetState();
}
}
class BannerWidgetState extends State {
List _bannerList = new List();
@override
void initState() {
_bannerList.add(null);
_getBanner();
}
Future _getBanner() {
ApiService().getBanner((BannerModel _bannerModel) {
if (_bannerModel.data.length > 0) {
setState(() {
_bannerList = _bannerModel.data;
});
}
});
}
Widget buildItemImageWidget(BuildContext context, int index) {
return new InkWell(
onTap: () {
Navigator.of(context).push(new MaterialPageRoute(builder: (context){
return new WebViewPage(title: _bannerList[index].title,url: _bannerList[index].url);
}));
},
child: new Container(
child: new Image.network(
_bannerList[index].imagePath,
fit: BoxFit.fill,
),
),
);
}
@override
Widget build(BuildContext context) {
return Swiper(
itemBuilder: (BuildContext context, int index) {
if (_bannerList[index] == null ||
_bannerList[index].imagePath == null) {
return new Container(
color: Colors.grey[100],
);
} else {
return buildItemImageWidget(context, index);
}
},
itemCount: _bannerList.length,
autoplay: true,
pagination: new SwiperPagination(),
);;
}
}
================================================
FILE: lib/ui/home/home_page.dart
================================================
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:wanandroid_ngu/base/_base_widget.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/article_model.dart';
import 'package:wanandroid_ngu/ui/home/banner.dart';
import 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';
class HomePage extends BaseWidget {
@override
BaseWidgetState getState() {
return HomePageState();
}
}
class HomePageState extends BaseWidgetState {
List _datas = new List();
//listview控制器
ScrollController _scrollController = ScrollController();
bool showToTopBtn = false; //是否显示“返回到顶部”按钮
int _page = 0;
@override
void initState() {
super.initState();
setAppBarVisible(false);
getData();
_scrollController.addListener(() {
//滑到了底部,加载更多
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
_getMore();
}
//当前位置是否超过屏幕高度
if (_scrollController.offset < 200 && showToTopBtn) {
setState(() {
showToTopBtn = false;
});
} else if (_scrollController.offset >= 200 && showToTopBtn == false) {
setState(() {
showToTopBtn = true;
});
}
});
}
//获取文章列表数据
Future getData() async {
_page = 0;
ApiService().getArticleList((ArticleModel _articleModel) {
if (_articleModel.errorCode == 0) {
//成功
if (_articleModel.data.datas.length > 0) {
//有数据
showContent();
setState(() {
_datas.clear();
_datas.addAll(_articleModel.data.datas);
});
} else {
//数据为空
showEmpty();
}
} else {
Fluttertoast.showToast(msg: _articleModel.errorMsg);
}
}, (DioError error) {
//发生错误
print(error.response);
setState(() {
showError();
});
}, _page);
}
//加载更多的数据
Future _getMore() async {
_page++;
ApiService().getArticleList((ArticleModel _articleModel) {
if (_articleModel.errorCode == 0) {
//成功
if (_articleModel.data.datas.length > 0) {
//有数据
showContent();
setState(() {
_datas.addAll(_articleModel.data.datas);
});
} else {
//数据为空
Fluttertoast.showToast(msg: "没有更多数据了");
}
} else {
Fluttertoast.showToast(msg: _articleModel.errorMsg);
}
}, (DioError error) {
//发生错误
print(error.response);
setState(() {
showError();
});
}, _page);
}
@override
AppBar getAppBar() {
return AppBar(
title: Text("不显示"),
);
}
@override
Widget getContentWidget(BuildContext context) {
return Scaffold(
body: RefreshIndicator(
displacement: 15,
onRefresh: getData,
child: ListView.separated(
itemBuilder: _renderRow,
physics: new AlwaysScrollableScrollPhysics(),
separatorBuilder: (BuildContext context, int index) {
return Container(
height: 0.5,
color: Colors.black26,
);
},
controller: _scrollController,
//包含轮播图和加载更多
itemCount: _datas.length + 2),
),
floatingActionButton: !showToTopBtn
? null
: FloatingActionButton(
child: Icon(Icons.arrow_upward),
onPressed: () {
//返回到顶部时执行动画
_scrollController.animateTo(.0,
duration: Duration(milliseconds: 200), curve: Curves.ease);
}),
);
}
Widget _renderRow(BuildContext context, int index) {
if (index == 0) {
return Container(
height: 200,
color: Colors.green,
child: new BannerWidget(),
);
}
if (index < _datas.length - 1) {
return new InkWell(
onTap: () {
Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
return new WebViewPage(
title: _datas[index - 1].title, url: _datas[index - 1].link);
}));
},
child: Column(
children: [
Container(
color: Colors.white,
padding: EdgeInsets.fromLTRB(16, 16, 16, 8),
child: Row(
children: [
Text(
_datas[index - 1].author,
style: TextStyle(fontSize: 12),
textAlign: TextAlign.left,
),
Expanded(
child: Text(
_datas[index - 1].niceDate,
style: TextStyle(fontSize: 12),
textAlign: TextAlign.right,
),
),
],
),
),
Container(
color: Colors.white,
padding: EdgeInsets.fromLTRB(16, 0, 16, 0),
child: Row(
children: [
Expanded(
child: Text(
_datas[index - 1].title,
maxLines: 2,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: const Color(0xFF3D4E5F),
),
textAlign: TextAlign.left,
),
)
],
),
),
Container(
color: Colors.white,
padding: EdgeInsets.fromLTRB(16, 8, 16, 16),
child: Row(
children: [
Expanded(
child: Text(
_datas[index - 1].superChapterName,
style: TextStyle(fontSize: 12),
textAlign: TextAlign.left,
),
)
],
),
),
],
),
);
}
return null;
}
@override
void dispose() {
super.dispose();
_scrollController.dispose();
}
@override
bool get wantKeepAlive => true;
@override
void onClickErrorWidget() {
showloading();
getData();
}
}
================================================
FILE: lib/ui/knowledge/knowledge.dart
================================================
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:wanandroid_ngu/base/_base_widget.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/system_tree_model.dart';
import 'package:wanandroid_ngu/ui/knowledge/knowledge_content.dart';
import 'package:wanandroid_ngu/util/utils.dart';
class KnowledgePage extends BaseWidget {
@override
BaseWidgetState getState() {
return KnowledgePageState();
}
}
class KnowledgePageState extends BaseWidgetState {
List _datas = new List();
//listview控制器
ScrollController _scrollController = ScrollController();
bool showToTopBtn = false; //是否显示“返回到顶部”按钮
@override
void initState() {
super.initState();
setAppBarVisible(false);
_getData();
_scrollController.addListener(() {
//当前位置是否超过屏幕高度
if (_scrollController.offset < 200 && showToTopBtn) {
setState(() {
showToTopBtn = false;
});
} else if (_scrollController.offset >= 200 && showToTopBtn == false) {
setState(() {
showToTopBtn = true;
});
}
});
}
Future _getData() async {
ApiService().getSystemTree((SystemTreeModel _systemTreeModel) {
if (_systemTreeModel.errorCode == 0) {
//成功
if (_systemTreeModel.data.length > 0) {
//有数据
showContent();
setState(() {
_datas.clear();
_datas.addAll(_systemTreeModel.data);
});
} else {
//数据为空
showEmpty();
}
} else {
Fluttertoast.showToast(msg: _systemTreeModel.errorMsg);
}
},(DioError error) {
//发生错误
print(error.response);
showError();
});
}
Widget _renderRow(BuildContext context, int index) {
if (index < _datas.length) {
return InkWell(
onTap: () {
Navigator.of(context)
.push(new MaterialPageRoute(builder: (context) {
return new KnowledgeContentPage(new ValueKey(_datas[index]));
}));
},
child: Container(
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: Container(
padding: EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(bottom: 8),
child: Text(
_datas[index].name,
style: TextStyle(
fontSize: 16,
color: Color(0xFF3D4E5F),
fontWeight: FontWeight.bold),
textAlign: TextAlign.left,
),
),
Container(
alignment: Alignment.centerLeft,
child: buildChildren(_datas[index].children)),
],
),
)),
Icon(Icons.chevron_right)
],
),
));
}
return null;
}
Widget buildChildren(List children) {
List tiles = []; //先建一个数组用于存放循环生成的widget
Widget content; //单独一个widget组件,用于返回需要生成的内容widget
for (var item in children) {
tiles.add(
new Chip(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
backgroundColor: Utils.getChipBgColor(item.name),
label: new Text(item.name),
// avatar: new CircleAvatar(backgroundColor: Colors.blue,child: Text("A"),),
),
);
}
content = Wrap(
spacing: 12,
runSpacing: 12,
alignment: WrapAlignment.start,
children: tiles);
return content;
}
@override
void dispose() {
super.dispose();
_scrollController.dispose();
}
@override
AppBar getAppBar() {
return AppBar(
title: Text("不显示"),
);
}
@override
Widget getContentWidget(BuildContext context) {
return Scaffold(
body: RefreshIndicator(
displacement: 15,
onRefresh: _getData,
child: ListView.separated(
itemBuilder: _renderRow,
physics: new AlwaysScrollableScrollPhysics(),
separatorBuilder: (BuildContext context, int index) {
return Container(
height: 0.5,
color: Colors.black26,
);
},
itemCount: _datas.length,
controller: _scrollController,
),
),
floatingActionButton: !showToTopBtn ? null : FloatingActionButton(
child: Icon(Icons.arrow_upward),
onPressed: () {
//返回到顶部时执行动画
_scrollController.animateTo(.0,
duration: Duration(milliseconds: 200),
curve: Curves.ease
);
}
),
);
}
@override
void onClickErrorWidget() {
showloading();
_getData();
}
}
================================================
FILE: lib/ui/knowledge/knowledge_content.dart
================================================
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:wanandroid_ngu/base/_base_widget.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/system_tree_content_model.dart';
import 'package:wanandroid_ngu/model/system_tree_model.dart';
import 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';
class KnowledgeContentPage extends StatefulWidget {
SystemTreeData data;
KnowledgeContentPage(ValueKey key) : super(key: key) {
this.data = key.value;
}
@override
State createState() {
return KnowledgeContentPageState();
}
}
class KnowledgeContentPageState extends State
with TickerProviderStateMixin {
SystemTreeData _datas;
TabController _tabController;
@override
void initState() {
super.initState();
_datas = widget.data;
}
@override
void dispose() {
super.dispose();
_tabController.dispose();
}
@override
Widget build(BuildContext context) {
_tabController =
new TabController(length: _datas.children.length, vsync: this);
return new Scaffold(
appBar: new AppBar(
title: Text(_datas.name),
bottom: new TabBar(
indicatorColor: Colors.white,
labelStyle:TextStyle(fontSize: 16),
unselectedLabelStyle: TextStyle(fontSize: 16),
controller: _tabController,
isScrollable: true,
tabs: _datas.children.map((SystemTreeChild item) {
return Tab(
text: item.name,
);
}).toList()),
),
body: TabBarView(
controller: _tabController,
children: _datas.children.map((item) {
return NewsList(
item.id,
);
}).toList(),
),
);
}
}
//知识体系文章列表
class NewsList extends BaseWidget {
final int id;
NewsList(this.id);
@override
BaseWidgetState getState() {
return _NewsListState();
} //知识体系id
}
class _NewsListState extends BaseWidgetState {
List _datas = new List();
ScrollController _scrollController = ScrollController(); //listview的控制器
int _page = 0;
@override
void initState() {
setAppBarVisible(false);
showloading();
getData();
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
_getMore();
}
});
}
Future getData() async {
_page = 0;
int _id = widget.id;
ApiService().getSystemTreeContent(
(SystemTreeContentModel _systemTreeContentModel) {
if (_systemTreeContentModel.errorCode == 0) {
//成功
if (_systemTreeContentModel.data.datas.length > 0) {
//有数据
showContent();
setState(() {
_datas = _systemTreeContentModel.data.datas;
});
} else {
//数据为空
showEmpty();
}
} else {
Fluttertoast.showToast(msg: _systemTreeContentModel.errorMsg);
}
},(DioError error) {
//发生错误
print(error.response);
showError();
}, _page, _id);
}
Future _getMore() async {
_page++;
int _id = widget.id;
ApiService().getSystemTreeContent(
(SystemTreeContentModel _systemTreeContentModel) {
if (_systemTreeContentModel.errorCode == 0) {
//成功
if (_systemTreeContentModel.data.datas.length > 0) {
//有数据
showContent();
setState(() {
_datas.addAll(_systemTreeContentModel.data.datas);
});
} else {
//数据为空
Fluttertoast.showToast(msg: "没有更多数据了");
}
} else {
Fluttertoast.showToast(msg: _systemTreeContentModel.errorMsg);
}
},(DioError error) {
//发生错误
print(error.response);
showError();
}, _page, _id);
}
Widget _renderRow(BuildContext context, int index) {
if (index < _datas.length) {
return InkWell(
child: Container(
child: _newsRow(_datas[index]),
),
onTap: () {
Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
return new WebViewPage(
title: _datas[index].title, url: _datas[index].link);
}));
},
);
}
return null;
}
//新闻列表单个item
Widget _newsRow(SystemTreeContentChild item) {
return new Container(
color: Colors.white,
padding: EdgeInsets.all(16),
child: Column(
children: [
new Container(
padding: EdgeInsets.fromLTRB(8, 8, 8, 8),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
item.author,
style: TextStyle(fontSize: 12, color: Colors.grey),
),
new Expanded(
child: new Text(
item.niceDate,
style: TextStyle(fontSize: 12, color: Colors.grey),
textAlign: TextAlign.right,
),
),
],
)),
Container(
padding: EdgeInsets.fromLTRB(8, 0, 8, 8),
child: Row(
children: [
Expanded(
child: Text(
item.title,
style: TextStyle(
fontSize: 16,
color: const Color(0xFF3D4E5F),
fontWeight: FontWeight.bold),
textAlign: TextAlign.left,
))
],
)),
Container(
padding: EdgeInsets.fromLTRB(8, 0, 8, 8),
child: Row(
children: [
Text(
item.superChapterName,
style: TextStyle(fontSize: 12, color: Colors.grey),
),
new Text(
"/" + item.chapterName,
style: TextStyle(fontSize: 12, color: Colors.grey),
textAlign: TextAlign.right,
),
],
)),
],
),
);
}
@override
AppBar getAppBar() {
return AppBar(
title: Text("不显示"),
);
}
@override
Widget getContentWidget(BuildContext context) {
return RefreshIndicator(
onRefresh: getData,
child: ListView.separated(
physics: new AlwaysScrollableScrollPhysics(),
itemBuilder: _renderRow,
itemCount: _datas.length + 1,
controller: _scrollController,
separatorBuilder: (BuildContext context, int index) {
return Container(
height: 0.5,
color: Colors.black26,
);
},
),
);
}
@override
void onClickErrorWidget() {
showloading();
getData();
}
}
================================================
FILE: lib/ui/login/login_page.dart
================================================
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:wanandroid_ngu/common/application.dart';
import 'package:wanandroid_ngu/common/user.dart';
import 'package:wanandroid_ngu/event/login_event.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/user_model.dart';
import 'package:wanandroid_ngu/util/bubble_indication_painter.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:wanandroid_ngu/util/theme_util.dart';
class LoginPage extends StatefulWidget {
LoginPage({Key key}) : super(key: key);
@override
_LoginPageState createState() => new _LoginPageState();
}
class _LoginPageState extends State
with SingleTickerProviderStateMixin {
Color themeColor = ThemeUtils.currentColorTheme;
final GlobalKey _scaffoldKey = new GlobalKey();
final FocusNode myFocusNodeEmailLogin = FocusNode();
final FocusNode myFocusNodePasswordLogin = FocusNode();
final FocusNode myFocusNodePassword = FocusNode();
final FocusNode myFocusNodeName = FocusNode();
TextEditingController loginEmailController = new TextEditingController();
TextEditingController loginPasswordController = new TextEditingController();
bool _obscureTextLogin = true;
bool _obscureTextSignup = true;
bool _obscureTextSignupConfirm = true;
TextEditingController signupNameController = new TextEditingController();
TextEditingController signupPasswordController = new TextEditingController();
TextEditingController signupConfirmPasswordController =
new TextEditingController();
PageController _pageController;
Color left = Colors.black;
Color right = Colors.white;
String title = "登录";
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text(title),
),
key: _scaffoldKey,
body: NotificationListener(
onNotification: (overscroll) {
overscroll.disallowGlow();
},
child: SingleChildScrollView(
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height >= 775.0
? MediaQuery.of(context).size.height
: 775.0,
decoration: new BoxDecoration(
gradient: new LinearGradient(
colors: [Color(0xFFffffff), Color(0xFFffffff)],
begin: const FractionalOffset(0.0, 0.0),
end: const FractionalOffset(1.0, 1.0),
stops: [0.0, 1.0],
tileMode: TileMode.clamp),
),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: EdgeInsets.only(top: 60.0),
child: _buildMenuBar(context),
),
Expanded(
flex: 2,
child: PageView(
controller: _pageController,
onPageChanged: (i) {
if (i == 0) {
setState(() {
right = Colors.white;
left = Colors.black;
title = "登录";
});
} else if (i == 1) {
setState(() {
right = Colors.black;
left = Colors.white;
title = "注册";
});
}
},
children: [
new ConstrainedBox(
constraints: const BoxConstraints.expand(),
child: _buildSignIn(context),
),
new ConstrainedBox(
constraints: const BoxConstraints.expand(),
child: _buildSignUp(context),
),
],
),
),
],
),
),
),
),
);
}
@override
void dispose() {
myFocusNodePassword.dispose();
myFocusNodeName.dispose();
_pageController?.dispose();
super.dispose();
}
@override
void initState() {
super.initState();
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
_pageController = PageController();
}
void showInSnackBar(String value) {
FocusScope.of(context).requestFocus(new FocusNode());
_scaffoldKey.currentState?.removeCurrentSnackBar();
_scaffoldKey.currentState.showSnackBar(new SnackBar(
content: new Text(
value,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
),
),
backgroundColor: themeColor,
duration: Duration(seconds: 3),
));
}
Widget _buildMenuBar(BuildContext context) {
return Container(
width: 300.0,
height: 50.0,
decoration: BoxDecoration(
color: Color(0x552B2B2B),
borderRadius: BorderRadius.all(Radius.circular(25.0)),
),
child: CustomPaint(
painter: TabIndicationPainter(pageController: _pageController),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
child: FlatButton(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
onPressed: _onSignInButtonPress,
child: Text(
"登录",
style: TextStyle(color: left, fontSize: 16.0),
),
),
),
//Container(height: 33.0, width: 1.0, color: Colors.white),
Expanded(
child: FlatButton(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
onPressed: _onSignUpButtonPress,
child: Text(
"注册",
style: TextStyle(
color: right,
fontSize: 16.0,
),
),
),
),
],
),
),
);
}
Widget _buildSignIn(BuildContext context) {
//登录
Future _login() async {
String username = loginEmailController.text;
String password = loginPasswordController.text;
if ((null != username && username.trim().length > 0) &&
(null != password && password.trim().length > 0)) {
ApiService().login((UserModel _userModel, Response response) {
if (_userModel != null) {
User().saveUserInfo(_userModel, response);
Application.eventBus.fire(new LoginEvent());
if (_userModel.errorCode == 0) {
Fluttertoast.showToast(msg: "登录成功!");
Navigator.of(context).pop();
} else {
Fluttertoast.showToast(msg: _userModel.errorMsg);
}
}
}, username, password);
} else {
Fluttertoast.showToast(
msg: "用户名或者密码不能为空",
);
}
}
return Container(
padding: EdgeInsets.only(top: 23.0),
child: Column(
children: [
Stack(
alignment: Alignment.topCenter,
overflow: Overflow.visible,
children: [
Card(
elevation: 2.0,
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
child: Container(
width: 300.0,
height: 150.0,
child: Column(
children: [
Padding(
padding: EdgeInsets.only(
top: 10.0, bottom: 10.0, left: 25.0, right: 25.0),
child: TextField(
focusNode: myFocusNodeEmailLogin,
controller: loginEmailController,
keyboardType: TextInputType.emailAddress,
style: TextStyle(fontSize: 14.0, color: Colors.black),
decoration: InputDecoration(
border: InputBorder.none,
icon: Icon(
FontAwesomeIcons.user,
color: Colors.black,
size: 18.0,
),
hintText: "用户名",
hintStyle: TextStyle(fontSize: 17.0),
),
),
),
Container(
width: 250.0,
height: 1.0,
color: Colors.grey[400],
),
Padding(
padding: EdgeInsets.only(
top: 10.0, bottom: 10.0, left: 25.0, right: 25.0),
child: TextField(
focusNode: myFocusNodePasswordLogin,
controller: loginPasswordController,
obscureText: _obscureTextLogin,
style: TextStyle(fontSize: 16.0, color: Colors.black),
decoration: InputDecoration(
border: InputBorder.none,
icon: Icon(
FontAwesomeIcons.lock,
size: 22.0,
color: Colors.black,
),
hintText: "密码",
hintStyle: TextStyle(fontSize: 17.0),
suffixIcon: GestureDetector(
onTap: _toggleLogin,
child: Icon(
FontAwesomeIcons.eye,
size: 15.0,
color: Colors.black,
),
),
),
),
),
],
),
),
),
Container(
margin: EdgeInsets.only(top: 240.0),
decoration: new BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
boxShadow: [
BoxShadow(
color: const Color(0xFFffffff),
offset: Offset(1.0, 6.0),
blurRadius: 20.0,
),
BoxShadow(
color: const Color(0xFFffffff),
offset: Offset(1.0, 6.0),
blurRadius: 20.0,
),
],
gradient: new LinearGradient(
colors: [Color(0xFFffffff), Color(0xFFffffff)],
begin: const FractionalOffset(0.2, 0.2),
end: const FractionalOffset(1.0, 1.0),
stops: [0.0, 1.0],
tileMode: TileMode.clamp),
),
child: FlatButton(
shape: RoundedRectangleBorder(
side: BorderSide(
color: themeColor,
width: 1,
),
borderRadius: BorderRadius.circular(30)),
color: themeColor,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 60.0),
child: Text(
"登录",
style: TextStyle(
color: Colors.white,
fontSize: 18.0,
),
),
),
onPressed: () {
_login();
}),
),
],
)
],
),
);
}
Widget _buildSignUp(BuildContext context) {
Future _regist() async {
String username = signupNameController.text;
String password = signupPasswordController.text;
String rePassword = signupConfirmPasswordController.text;
if ((null != username && username.trim().length > 0) &&
(null != password && password.trim().length > 0) &&
(null != rePassword && rePassword.trim().length > 0)) {
if (password != rePassword) {
Fluttertoast.showToast(msg: "两次密码输入不一致!");
} else {
ApiService().register((UserModel _userModel) {
if (_userModel != null) {
if (_userModel.errorCode == 0) {
Fluttertoast.showToast(msg: "注册成功!");
} else {
Fluttertoast.showToast(msg: _userModel.errorMsg);
}
}
}, username, password);
}
} else {
Fluttertoast.showToast(
msg: "用户名或者密码不能为空",
);
}
}
return Container(
padding: EdgeInsets.only(top: 23.0),
child: Column(
children: [
Stack(
alignment: Alignment.topCenter,
overflow: Overflow.visible,
children: [
Card(
elevation: 2.0,
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
child: Container(
width: 300.0,
height: 210.0,
child: Column(
children: [
Padding(
padding: EdgeInsets.only(
top: 10.0, bottom: 10.0, left: 25.0, right: 25.0),
child: TextField(
focusNode: myFocusNodeName,
controller: signupNameController,
keyboardType: TextInputType.text,
textCapitalization: TextCapitalization.words,
style: TextStyle(fontSize: 16.0, color: Colors.black),
decoration: InputDecoration(
border: InputBorder.none,
icon: Icon(
FontAwesomeIcons.user,
color: Colors.black,
),
hintText: "用户名",
hintStyle: TextStyle(fontSize: 16.0),
),
),
),
Container(
width: 250.0,
height: 1.0,
color: Colors.grey[400],
),
Padding(
padding: EdgeInsets.only(
top: 10.0, bottom: 10.0, left: 25.0, right: 25.0),
child: TextField(
focusNode: myFocusNodePassword,
controller: signupPasswordController,
obscureText: _obscureTextSignup,
style: TextStyle(fontSize: 16.0, color: Colors.black),
decoration: InputDecoration(
border: InputBorder.none,
icon: Icon(
FontAwesomeIcons.lock,
color: Colors.black,
),
hintText: "密码",
hintStyle: TextStyle(fontSize: 16.0),
suffixIcon: GestureDetector(
onTap: _toggleSignup,
child: Icon(
FontAwesomeIcons.eye,
size: 15.0,
color: Colors.black,
),
),
),
),
),
Container(
width: 250.0,
height: 1.0,
color: Colors.grey[400],
),
Padding(
padding: EdgeInsets.only(
top: 10.0, bottom: 10, left: 25.0, right: 25.0),
child: TextField(
controller: signupConfirmPasswordController,
obscureText: _obscureTextSignupConfirm,
style: TextStyle(fontSize: 16.0, color: Colors.black),
decoration: InputDecoration(
border: InputBorder.none,
icon: Icon(
FontAwesomeIcons.lock,
color: Colors.black,
),
hintText: "确认密码",
hintStyle: TextStyle(fontSize: 16.0),
suffixIcon: GestureDetector(
onTap: _toggleSignupConfirm,
child: Icon(
FontAwesomeIcons.eye,
size: 15.0,
color: Colors.black,
),
),
),
),
),
],
),
),
),
Container(
margin: EdgeInsets.only(top: 340.0),
decoration: new BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
),
child: FlatButton(
shape: RoundedRectangleBorder(
side: BorderSide(
color: themeColor,
width: 1,
),
borderRadius: BorderRadius.circular(30)),
color: themeColor,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 60.0),
child: Text(
"注册",
style: TextStyle(color: Colors.white, fontSize: 18.0),
),
),
onPressed: () {
_regist();
}),
),
],
),
],
),
);
}
//切换到登录
void _onSignInButtonPress() {
_pageController.animateToPage(0,
duration: Duration(milliseconds: 500), curve: Curves.decelerate);
}
//切换到注册
void _onSignUpButtonPress() {
_pageController?.animateToPage(1,
duration: Duration(milliseconds: 500), curve: Curves.decelerate);
}
//登录密码安全开关
void _toggleLogin() {
setState(() {
_obscureTextLogin = !_obscureTextLogin;
});
}
//注册密码安全开关
void _toggleSignup() {
setState(() {
_obscureTextSignup = !_obscureTextSignup;
});
}
//注册确认密码安全开关
void _toggleSignupConfirm() {
setState(() {
_obscureTextSignupConfirm = !_obscureTextSignupConfirm;
});
}
}
================================================
FILE: lib/ui/navigation/navigation.dart
================================================
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:wanandroid_ngu/base/_base_widget.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/navi_model.dart';
import 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';
import 'package:wanandroid_ngu/util/utils.dart';
class NavigationPage extends BaseWidget {
@override
BaseWidgetState getState() {
return NavigationState();
}
}
class NavigationState extends BaseWidgetState {
List _naviTitles = new List();
//listview控制器
ScrollController _scrollController = ScrollController();
bool showToTopBtn = false; //是否显示“返回到顶部”按钮
@override
void initState() {
super.initState();
setAppBarVisible(false);
_getData();
_scrollController.addListener(() {
_scrollController.addListener(() {
//当前位置是否超过屏幕高度
if (_scrollController.offset < 200 && showToTopBtn) {
setState(() {
showToTopBtn = false;
});
} else if (_scrollController.offset >= 200 && showToTopBtn == false) {
setState(() {
showToTopBtn = true;
});
}
});
});
}
Future _getData() async {
ApiService().getNaviList((NaviModel _naviData) {
if (_naviData.errorCode == 0) {
//成功
if (_naviData.data.length > 0) {
//有数据
showContent();
setState(() {
_naviTitles = _naviData.data;
});
} else {
//数据为空
showEmpty();
}
} else {
Fluttertoast.showToast(msg: _naviData.errorMsg);
}
},(DioError error) {
//发生错误
print(error.response);
showError();
});
}
Widget _rightListView(BuildContext context) {
return ListView.separated(
itemBuilder: _renderContent,
itemCount: _naviTitles.length,
controller: _scrollController,
physics: new AlwaysScrollableScrollPhysics(),
separatorBuilder: (BuildContext context, int index) {
return Container(
height: 0.5,
color: Colors.black26,
);
});
}
Widget _renderContent(BuildContext context, int index) {
return Container(
color: Colors.white,
padding: EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(bottom: 8),
child: Text(
_naviTitles[index].name,
style: TextStyle(
fontSize: 16,
color: Color(0xFF3D4E5F),
fontWeight: FontWeight.bold),
textAlign: TextAlign.left,
),
),
Container(
alignment: Alignment.centerLeft,
child: buildChildren(_naviTitles[index].articles),
),
],
),
);
}
Widget buildChildren(List children) {
List tiles = []; //先建一个数组用于存放循环生成的widget
Widget content; //单独一个widg
for (NaviArticle item in children) {
tiles.add(new InkWell(
child: new Chip(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
backgroundColor: Utils.getChipBgColor(item.title),
label: new Text(item.title)),
onTap: () {
Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
return new WebViewPage(title: item.title, url: item.link);
}));
},
));
}
content = Wrap(
spacing: 12,
runSpacing: 12,
alignment: WrapAlignment.start,
children: tiles,
);
return content;
}
@override
AppBar getAppBar() {
return AppBar(
title: Text("不显示"),
);
}
@override
Widget getContentWidget(BuildContext context) {
return Scaffold(
body: RefreshIndicator(
displacement: 15,
child: _rightListView(context),
onRefresh: _getData,
),
floatingActionButton: !showToTopBtn
? null
: FloatingActionButton(
child: Icon(Icons.arrow_upward),
onPressed: () {
//返回到顶部时执行动画
_scrollController.animateTo(.0,
duration: Duration(milliseconds: 200), curve: Curves.ease);
}),
);
}
@override
void onClickErrorWidget() {
showloading();
_getData();
}
}
================================================
FILE: lib/ui/project/project.dart
================================================
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:wanandroid_ngu/base/_base_widget.dart';
import 'package:wanandroid_ngu/common/application.dart';
import 'package:wanandroid_ngu/event/change_theme_event.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/projectlist_model.dart';
import 'package:wanandroid_ngu/model/project_tree_model.dart';
import 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';
import 'package:wanandroid_ngu/util/theme_util.dart';
class ProjectPage extends BaseWidget {
@override
BaseWidgetState getState() {
return ProjectPageState();
}
}
class ProjectPageState extends BaseWidgetState
with TickerProviderStateMixin {
Color themeColor = ThemeUtils.currentColorTheme;
List _datas = new List();
TabController _tabController;
Future _getData() async {
ApiService().getProjectTree((ProjectTreeModel _projectTreeModel) {
if (_projectTreeModel.errorCode == 0) {
//成功
if (_projectTreeModel.data.length > 0) {
//有数据
showContent();
setState(() {
_datas = _projectTreeModel.data;
});
} else {
//数据为空
showEmpty();
}
} else {
Fluttertoast.showToast(msg: _projectTreeModel.errorMsg);
}
}, (DioError error) {
//发生错误
print(error.response);
showError();
});
}
@override
void initState() {
super.initState();
setAppBarVisible(false);
_getData();
Application.eventBus.on().listen((event) {
setState(() {
themeColor = event.color;
});
});
}
@override
void dispose() {
super.dispose();
_tabController.dispose();
super.dispose();
}
@override
AppBar getAppBar() {
return AppBar(
title: Text("不显示"),
);
}
@override
Widget getContentWidget(BuildContext context) {
_tabController = new TabController(
vsync: this,
length: _datas.length,
);
return Scaffold(
body: Column(
children: [
Container(
color: themeColor,
height: 48,
child: TabBar(
indicatorColor: Colors.white,
labelStyle:TextStyle(fontSize: 16),
unselectedLabelStyle: TextStyle(fontSize: 16),
controller: _tabController,
tabs: _datas.map((ProjectTreeData item) {
return Tab(text: item.name);
}).toList(),
isScrollable: true,
),
),
Expanded(
child: TabBarView(
controller: _tabController,
children: _datas.map((item) {
return ProjectList(item.id);
}).toList(),
))
],
));
}
@override
void onClickErrorWidget() {
showloading();
_getData();
}
}
class ProjectList extends StatefulWidget {
final int id;
ProjectList(this.id);
@override
_ProjectListState createState() {
return new _ProjectListState();
}
}
class _ProjectListState extends State {
List _datas = new List();
ScrollController _scrollController = ScrollController();
int _page = 1;
bool showToTopBtn = false; //是否显示“返回到顶部”按钮
Future _getData() async {
_page = 1;
int _id = widget.id;
ApiService().getProjectList((ProjectTreeListModel projectTreeListModel) {
setState(() {
_datas = projectTreeListModel.data.datas;
});
}, _page, _id);
}
Future _getMore() async {
_page++;
int _id = widget.id;
ApiService().getProjectList((ProjectTreeListModel projectTreeListModel) {
setState(() {
_datas.addAll(projectTreeListModel.data.datas);
});
}, _page, _id);
}
@override
void initState() {
super.initState();
_getData();
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
_getMore();
}
});
_scrollController.addListener(() {
//当前位置是否超过屏幕高度
if (_scrollController.offset < 200 && showToTopBtn) {
setState(() {
showToTopBtn = false;
});
} else if (_scrollController.offset >= 200 && showToTopBtn == false) {
setState(() {
showToTopBtn = true;
});
}
});
}
@override
void dispose() {
super.dispose();
_scrollController.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: RefreshIndicator(
displacement: 15,
onRefresh: _getData,
child: ListView.separated(
itemBuilder: _renderRow,
physics: new AlwaysScrollableScrollPhysics(),
separatorBuilder: (BuildContext context, int index) {
return Container(
height: 0.5,
color: Colors.black26,
);
},
controller: _scrollController,
//包含加载更多
itemCount: _datas.length + 1),
),
floatingActionButton: !showToTopBtn ? null : FloatingActionButton(
child: Icon(Icons.arrow_upward),
onPressed: () {
//返回到顶部时执行动画
_scrollController.animateTo(.0,
duration: Duration(milliseconds: 200),
curve: Curves.ease
);
}
),
);
}
Widget _renderRow(BuildContext context, int index) {
if (index < _datas.length) {
return new InkWell(
onTap: () {
Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
return new WebViewPage(
title: _datas[index].title, url: _datas[index].link);
}));
},
child: Container(
color: Colors.white,
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
padding: EdgeInsets.fromLTRB(8, 8, 8, 8),
child: Row(
children: [
Expanded(
child: Text(
_datas[index].title,
maxLines: 2,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: const Color(0xFF3D4E5F),
),
textAlign: TextAlign.left,
),
)
],
),
),
Container(
padding: EdgeInsets.fromLTRB(8, 0, 8, 8),
child: Row(
children: [
Expanded(
child: Text(
_datas[index].desc,
style: TextStyle(fontSize: 12, color: Colors.grey),
textAlign: TextAlign.left,
maxLines: 3,
),
)
],
),
),
Container(
padding: EdgeInsets.fromLTRB(8, 0, 8, 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
_datas[index].author,
style: TextStyle(fontSize: 12, color: Colors.grey),
),
Text(
_datas[index].niceDate,
style: TextStyle(fontSize: 12, color: Colors.grey),
),
],
),
)
],
),
),
Container(
padding: EdgeInsets.fromLTRB(8, 16, 8, 8),
child: Image.network(
_datas[index].envelopePic,
width: 80,
height: 120,
fit: BoxFit.fill,
)),
],
) ,
),
);
}
return null;
}
}
================================================
FILE: lib/ui/public_ui/webview_page.dart
================================================
import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
import 'package:wanandroid_ngu/util/theme_util.dart';
class WebViewPage extends StatefulWidget {
String title;
String url;
WebViewPage({
Key key,
@required this.title,
@required this.url,
}) : super(key: key);
@override
State createState() {
return new WebViewPageState();
}
}
class WebViewPageState extends State {
bool isLoad = true;
final flutterWebviewPlugin = new FlutterWebviewPlugin();
@override
void initState() {
flutterWebviewPlugin.onStateChanged.listen((state) {
debugPrint("state:_" + state.type.toString());
if (state.type == WebViewState.finishLoad) {
setState(() {
isLoad = false;
});
} else if (state.type == WebViewState.startLoad) {
setState(() {
isLoad = true;
});
}
});
}
// Future _requestPop() {
// //相当于Android的setResult
// Navigator.pop(context, "返回给上一个页面的测试数据");
// return new Future.value(false);
// }
@override
Widget build(BuildContext context) {
return WillPopScope(
child: WebviewScaffold(
url: widget.url,
appBar: new AppBar(
elevation: 0.4,
title: new Text(widget.title),
bottom: new PreferredSize(
child: isLoad
? new LinearProgressIndicator()
: new Divider(height: 1.0, color: ThemeUtils.currentColorTheme),
preferredSize: const Size.fromHeight(1.0),
),
),
withJavascript: true,
withZoom: false,
withLocalStorage: true,
),
);
}
}
================================================
FILE: lib/ui/publicc/publicc.dart
================================================
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:wanandroid_ngu/base/_base_widget.dart';
import 'package:wanandroid_ngu/common/application.dart';
import 'package:wanandroid_ngu/event/change_theme_event.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/wx_article_content_model.dart';
import 'package:wanandroid_ngu/model/wx_article_title_model.dart';
import 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';
import 'package:wanandroid_ngu/util/theme_util.dart';
class PubliccPage extends BaseWidget {
@override
BaseWidgetState getState() {
return PubliccPageState();
}
}
class PubliccPageState extends BaseWidgetState
with TickerProviderStateMixin {
Color themeColor = ThemeUtils.currentColorTheme;
List _datas = new List();
TabController _tabController;
Future _getData() async {
ApiService().getWxList((WxArticleTitleModel _articleTitleModel) {
if (_articleTitleModel.errorCode == 0) {
//成功
if (_articleTitleModel.data.length > 0) {
//有数据
showContent();
setState(() {
_datas = _articleTitleModel.data;
});
} else {
//数据为空
showEmpty();
}
} else {
Fluttertoast.showToast(msg: _articleTitleModel.errorMsg);
}
}, (DioError error) {
//发生错误
print(error.response);
showError();
});
}
@override
void initState() {
super.initState();
setAppBarVisible(false);
_getData();
Application.eventBus.on().listen((event) {
setState(() {
themeColor = event.color;
});
});
}
@override
void dispose() {
super.dispose();
_tabController.dispose();
super.dispose();
}
@override
AppBar getAppBar() {
return AppBar(
title: Text("不显示"),
);
}
@override
Widget getContentWidget(BuildContext context) {
_tabController = new TabController(
vsync: this,
length: _datas.length,
);
return Scaffold(
body: Column(
children: [
Container(
color: themeColor,
height: 48,
child: TabBar(
indicatorColor: Colors.white,
labelStyle: TextStyle(fontSize: 16),
unselectedLabelStyle: TextStyle(fontSize: 16),
controller: _tabController,
tabs: _datas.map((WxArticleTitleData item) {
return Tab(text: item.name);
}).toList(),
isScrollable: true,
),
),
Expanded(
child: TabBarView(
controller: _tabController,
children: _datas.map((item) {
return NewsList(item.id);
}).toList(),
))
],
));
}
@override
void onClickErrorWidget() {
showloading();
_getData();
}
}
class NewsList extends StatefulWidget {
final int id;
NewsList(this.id);
@override
_NewsListState createState() {
return new _NewsListState();
}
}
class _NewsListState extends State {
List _datas = new List();
ScrollController _scrollController = ScrollController();
int _page = 1;
bool showToTopBtn = false; //是否显示“返回到顶部”按钮
Future _getData() async {
_page = 1;
int _id = widget.id;
ApiService().getWxArticleList(
(WxArticleContentModel _wxArticleContentModel) {
setState(() {
_datas = _wxArticleContentModel.data.datas;
});
}, _id, _page);
}
Future _getMore() async {
_page++;
int _id = widget.id;
ApiService().getWxArticleList((WxArticleContentModel _articleContentModel) {
setState(() {
_datas.addAll(_articleContentModel.data.datas);
});
}, _id, _page);
}
@override
void initState() {
super.initState();
_getData();
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
_getMore();
}
});
_scrollController.addListener(() {
//当前位置是否超过屏幕高度
if (_scrollController.offset < 200 && showToTopBtn) {
setState(() {
showToTopBtn = false;
});
} else if (_scrollController.offset >= 200 && showToTopBtn == false) {
setState(() {
showToTopBtn = true;
});
}
});
}
@override
void dispose() {
super.dispose();
_scrollController.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: RefreshIndicator(
displacement: 15,
onRefresh: _getData,
child: ListView.separated(
physics: new AlwaysScrollableScrollPhysics(),
itemBuilder: _renderRow,
separatorBuilder: (BuildContext context, int index) {
return Container(
height: 0.5,
color: Colors.black26,
);
},
controller: _scrollController,
//包含加载更多
itemCount: _datas.length + 1),
),
floatingActionButton: !showToTopBtn
? null
: FloatingActionButton(
child: Icon(Icons.arrow_upward),
onPressed: () {
//返回到顶部时执行动画
_scrollController.animateTo(.0,
duration: Duration(milliseconds: 200), curve: Curves.ease);
}),
);
}
Widget _renderRow(BuildContext context, int index) {
if (index < _datas.length) {
return new InkWell(
onTap: () {
Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
return new WebViewPage(
title: _datas[index].title, url: _datas[index].link);
}));
},
child: Column(
children: [
Container(
color: Colors.white,
padding: EdgeInsets.fromLTRB(16, 16, 16, 8),
child: Row(
children: [
Text(
_datas[index].author,
style: TextStyle(fontSize: 12),
textAlign: TextAlign.left,
),
Expanded(
child: Text(
_datas[index].niceDate,
style: TextStyle(fontSize: 12),
textAlign: TextAlign.right,
),
),
],
),
),
Container(
color: Colors.white,
padding: EdgeInsets.fromLTRB(16, 0, 16, 0),
child: Row(
children: [
Expanded(
child: Text(
_datas[index].title,
maxLines: 2,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: const Color(0xFF3D4E5F),
),
textAlign: TextAlign.left,
),
)
],
),
),
Container(
color: Colors.white,
padding: EdgeInsets.fromLTRB(16, 8, 16, 16),
child: Row(
children: [
Expanded(
child: Text(
_datas[index].superChapterName,
style: TextStyle(fontSize: 12),
textAlign: TextAlign.left,
),
)
],
),
),
],
),
);
}
return null;
}
}
================================================
FILE: lib/ui/search/hot_search_result.dart
================================================
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:wanandroid_ngu/base/_base_widget.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/hotword_result_model.dart';
import 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';
class HotResultPage extends BaseWidget {
String hot;
HotResultPage(this.hot);
@override
BaseWidgetState getState() {
return HotResultPageState();
}
}
class HotResultPageState extends BaseWidgetState {
List _datas = new List();
ScrollController _scrollController = ScrollController();
int _page = 0;
bool showToTopBtn = false; //是否显示“返回到顶部”按钮
Future _getData() async {
_page = 0;
String _keyword = widget.hot;
ApiService().getSearchResult((HotwordResultModel otwordResultModel) {
if (otwordResultModel.errorCode == 0) {
//成功
if (otwordResultModel.data.datas.length > 0) {
//有数据
showContent();
setState(() {
_datas.clear();
_datas.addAll(otwordResultModel.data.datas);
});
} else {
//数据为空
showEmpty();
}
} else {
Fluttertoast.showToast(msg: otwordResultModel.errorMsg);
}
},(DioError error) {
//发生错误
print(error.response);
showError();
}, _page, _keyword);
}
Future