fx
14
.gitignore
vendored
@ -1,6 +1,5 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.lock
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
@ -9,9 +8,18 @@
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
*.lock
|
||||
.vscode
|
||||
.gradle
|
||||
.idea
|
||||
/local.properties
|
||||
.DS_Store
|
||||
/build
|
||||
.metadata
|
||||
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
@ -26,7 +34,7 @@
|
||||
.packages
|
||||
.pub-cache/
|
||||
.pub/
|
||||
build/
|
||||
/build/
|
||||
|
||||
# Android related
|
||||
**/android/**/gradle-wrapper.jar
|
||||
|
13
.vscode/launch.json
vendored
@ -1,13 +0,0 @@
|
||||
{
|
||||
// 使用 IntelliSense 了解相关属性。
|
||||
// 悬停以查看现有属性的描述。
|
||||
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Flutter",
|
||||
"request": "launch",
|
||||
"type": "dart"
|
||||
}
|
||||
]
|
||||
}
|
4
.vscode/settings.json
vendored
@ -1,4 +0,0 @@
|
||||
{
|
||||
"editor.fontSize": 14,
|
||||
|
||||
}
|
86
CHANGE-LOG.md
Normal file
@ -0,0 +1,86 @@
|
||||
## 更新日志
|
||||
|
||||
|
||||
#### 2019-2-5
|
||||
- [x] 处理因为flutter版本导致的项目运行不起来
|
||||
- [x] 更新readme, 加入开发日志, 与相关说明
|
||||
- [x] 加入 首页欢迎效果图
|
||||
- [x] refactor(整理richText的说明):
|
||||
- [x] 解决一些页面的code演示打不开的问题
|
||||
- [x] add:开发规范
|
||||
- [x] add:版本更新历史链接
|
||||
- [x] Update README.md
|
||||
- [x] add:添加版本号
|
||||
- [x] feat:添加代码开发规范
|
||||
- [x] refactor(update: version & fiexed warns):
|
||||
- [x] fix(solve conflict):
|
||||
- [x] modify:toast and andrid apk label
|
||||
- [x] Add:自动 pr 工具抓取器,抓取两周前至今的,提交数据,并去重
|
||||
- [x] fix:fluttetToast backHome
|
||||
- [x] fix:modified the style of toast && remote files
|
||||
- [x] chore(删除tools/log.json):
|
||||
- [x] 重构文件结构
|
||||
- [x] 关于手册图标更换
|
||||
- [x] 增加demo: CupertinoNavigationBar CupertinoPageRoute CupertinoPageScaffold CupertinoPicker,CupertinoPopupSurface CupertinoTimerPickerDemo
|
||||
|
||||
|
||||
#### 2019-1-24
|
||||
- [x] 功能:更新小部件的图标
|
||||
- [x] 功能:添加CupertinoTimerPickerDemo
|
||||
- [x] 调试:消除警告
|
||||
- [x] 修复:关于手册图标更换
|
||||
- [x] 添加:文案描述
|
||||
- [x] 添加:CupertinoPicker,CupertinoPopupSurface
|
||||
#### 2019-1-23
|
||||
- [x] 修复: 导航栏home返回报错
|
||||
- [x] 修复:收集错误
|
||||
- [x] 添加:CupertinoNavigationBar CupertinoPageRoute CupertinoPageScaffold
|
||||
#### 2019-1-22
|
||||
- [x] 功能:在Allsimon拉请求中添加英文简介
|
||||
#### 2019-1-21
|
||||
- [x] 功能:Cupertino的子项
|
||||
#### 2019-1-20
|
||||
- [x] 功能:CupertinoSwitch演示
|
||||
- [x] 功能:为搜索列表加入图标
|
||||
- [x] 功能:CupertinoSliverRefreshControl演示
|
||||
- [x] 功能:CupertinoSliverNavigationBar演示
|
||||
#### 2019-1-18
|
||||
- [x] 更新:SharedPreferences保存数据和android设备布局溢出
|
||||
- [x] 功能:添加CupertinoScrollbar演示
|
||||
- [x] 功能:第四页暂时用欢迎页替代。后期再开发
|
||||
#### 2019-1-17
|
||||
- [x] 添加:+许可证
|
||||
#### 2019-1-16
|
||||
- [x] 转换:将README翻译为En语言环境
|
||||
- [x] 功能:CupertinoScrollbar演示
|
||||
#### 2019-1-14
|
||||
- [x] 添加:增加手册页面
|
||||
- [x] 功能:文字演示
|
||||
- [x] 重构:修改过的图标
|
||||
- [x] 重构:文档,文章,组件收藏,新增webView
|
||||
- [x] 重构:修改过的演示
|
||||
- [x] 重构:代码视图
|
||||
- [x] 更新:版本 和readme.md
|
||||
- [x] 修改:添加代码视图
|
||||
- [x] 功能:添加搜索历史记录板
|
||||
- [x] 修改:列出加标头错误
|
||||
#### 2019-1-15
|
||||
- [x] 功能:welcomepage
|
||||
#### 2019-1-13
|
||||
- [x] 添加:一些输入描述
|
||||
- [x] 功能:加入GridPaper&SliverGrid
|
||||
- [x] 重构:修改db
|
||||
- [x] 重构:删除数据库 TabBarView
|
||||
- [x] 添加:网格视图
|
||||
- [x] 修改:checkbosListTile 错误
|
||||
- [x] 修改:自动提示文案
|
||||
- [x] 功能:增加免责声明,声明组件,自动弹出,左上角入口
|
||||
- [x] 重构:整理数据库初始逻辑,判断数据库完整性,判断是否存在已知的cat,widget,collection 三张表。
|
||||
- [x] 修复:DialogDemo,无法关闭的问题
|
||||
#### 2019-1-12
|
||||
- [x] 修复:icon没有,但内容有的,组件,给补充了icon
|
||||
- [x] 修改:1.整理文件 2.修正分析
|
||||
- [x] 更新:flutter_rookie_book => flutter_go
|
||||
- [x] 更新:更新SearchInput文件名=> search_input
|
||||
- [x] 修改:文件名称的大小写规范
|
||||
- [x] 修改:修正bottomNavigationBar iconButton警告
|
679
Flutter_Go 代码开发规范.md
Normal file
@ -0,0 +1,679 @@
|
||||
# Flutter Go 代码开发规范 0.1.0 版
|
||||
|
||||
## 代码风格
|
||||
|
||||
### 标识符三种类型
|
||||
|
||||
#### 大驼峰
|
||||
类、枚举、typedef和类型参数
|
||||
|
||||
```
|
||||
class SliderMenu { ... }
|
||||
|
||||
class HttpRequest { ... }
|
||||
|
||||
typedef Predicate = bool Function<T>(T value);
|
||||
```
|
||||
|
||||
包括用于元数据注释的类
|
||||
|
||||
```
|
||||
class Foo {
|
||||
const Foo([arg]);
|
||||
}
|
||||
|
||||
@Foo(anArg)
|
||||
class A { ... }
|
||||
|
||||
@Foo()
|
||||
class B { ... }
|
||||
```
|
||||
|
||||
#### 使用小写加下划线来命名库和源文件
|
||||
|
||||
```
|
||||
library peg_parser.source_scanner;
|
||||
|
||||
import 'file_system.dart';
|
||||
import 'slider_menu.dart';
|
||||
```
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
library pegparser.SourceScanner;
|
||||
|
||||
import 'file-system.dart';
|
||||
import 'SliderMenu.dart';
|
||||
```
|
||||
|
||||
|
||||
#### 使用小写加下划线来命名导入前缀
|
||||
|
||||
```
|
||||
import 'dart:math' as math;
|
||||
import 'package:angular_components/angular_components'
|
||||
as angular_components;
|
||||
import 'package:js/js.dart' as js;
|
||||
```
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
import 'dart:math' as Math;
|
||||
import 'package:angular_components/angular_components'
|
||||
as angularComponents;
|
||||
import 'package:js/js.dart' as JS;
|
||||
```
|
||||
|
||||
#### 使用小驼峰法命名其他标识符
|
||||
|
||||
```
|
||||
var item;
|
||||
|
||||
HttpRequest httpRequest;
|
||||
|
||||
void align(bool clearItems) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### 优先使用小驼峰法作为常量命名
|
||||
|
||||
```
|
||||
const pi = 3.14;
|
||||
const defaultTimeout = 1000;
|
||||
final urlScheme = RegExp('^([a-z]+):');
|
||||
|
||||
class Dice {
|
||||
static final numberGenerator = Random();
|
||||
}
|
||||
```
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
const PI = 3.14;
|
||||
const DefaultTimeout = 1000;
|
||||
final URL_SCHEME = RegExp('^([a-z]+):');
|
||||
|
||||
class Dice {
|
||||
static final NUMBER_GENERATOR = Random();
|
||||
}
|
||||
```
|
||||
|
||||
#### 不使用前缀字母
|
||||
因为Dart可以告诉您声明的类型、范围、可变性和其他属性,所以没有理由将这些属性编码为标识符名称。
|
||||
|
||||
```
|
||||
defaultTimeout
|
||||
```
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
kDefaultTimeout
|
||||
```
|
||||
|
||||
### 排序
|
||||
|
||||
为了使你的文件前言保持整洁,我们有规定的命令,指示应该出现在其中。每个“部分”应该用空行分隔。
|
||||
|
||||
#### 在其他引入之前引入所需的dart库
|
||||
|
||||
```
|
||||
import 'dart:async';
|
||||
import 'dart:html';
|
||||
|
||||
import 'package:bar/bar.dart';
|
||||
import 'package:foo/foo.dart';
|
||||
```
|
||||
|
||||
#### 在相对引入之前先引入在包中的库
|
||||
|
||||
```
|
||||
import 'package:bar/bar.dart';
|
||||
import 'package:foo/foo.dart';
|
||||
|
||||
import 'util.dart';
|
||||
```
|
||||
|
||||
#### 第三方包的导入先于其他包
|
||||
|
||||
```
|
||||
import 'package:bar/bar.dart';
|
||||
import 'package:foo/foo.dart';
|
||||
|
||||
import 'package:my_package/util.dart';
|
||||
```
|
||||
|
||||
#### 在所有导入之后,在单独的部分中指定导出
|
||||
|
||||
```
|
||||
import 'src/error.dart';
|
||||
import 'src/foo_bar.dart';
|
||||
|
||||
export 'src/error.dart';
|
||||
```
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
import 'src/error.dart';
|
||||
export 'src/error.dart';
|
||||
import 'src/foo_bar.dart';
|
||||
```
|
||||
|
||||
|
||||
### 所有流控制结构,请使用大括号
|
||||
|
||||
这样做可以避免悬浮的else问题
|
||||
|
||||
```
|
||||
if (isWeekDay) {
|
||||
print('Bike to work!');
|
||||
} else {
|
||||
print('Go dancing or read a book!');
|
||||
}
|
||||
```
|
||||
|
||||
#### 例外
|
||||
一个if语句没有else子句,其中整个if语句和then主体都适合一行。在这种情况下,如果你喜欢的话,你可以去掉大括号
|
||||
|
||||
```
|
||||
if (arg == null) return defaultValue;
|
||||
```
|
||||
|
||||
如果流程体超出了一行需要分划请使用大括号:
|
||||
|
||||
```
|
||||
if (overflowChars != other.overflowChars) {
|
||||
return overflowChars < other.overflowChars;
|
||||
}
|
||||
```
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
if (overflowChars != other.overflowChars)
|
||||
return overflowChars < other.overflowChars;
|
||||
```
|
||||
|
||||
## 注释
|
||||
|
||||
### 要像句子一样格式化
|
||||
除非是区分大小写的标识符,否则第一个单词要大写。以句号结尾(或“!”或“?”)。对于所有的注释都是如此:doc注释、内联内容,甚至TODOs。即使是一个句子片段。
|
||||
|
||||
```
|
||||
greet(name) {
|
||||
// Assume we have a valid name.
|
||||
print('Hi, $name!');
|
||||
}
|
||||
```
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
greet(name) {
|
||||
/* Assume we have a valid name. */
|
||||
print('Hi, $name!');
|
||||
}
|
||||
```
|
||||
|
||||
可以使用块注释(/…/)临时注释掉一段代码,但是所有其他注释都应该使用//
|
||||
|
||||
### Doc注释
|
||||
使用///文档注释来记录成员和类型。
|
||||
|
||||
使用doc注释而不是常规注释,可以让dartdoc找到并生成文档。
|
||||
|
||||
```
|
||||
/// The number of characters in this chunk when unsplit.
|
||||
int get length => ...
|
||||
```
|
||||
|
||||
> 由于历史原因,达特茅斯学院支持道格评论的两种语法:///(“C#风格”)和/**…* /(“JavaDoc风格”)。我们更喜欢/// 因为它更紧凑。/**和*/在多行文档注释中添加两个无内容的行。在某些情况下,///语法也更容易阅读,例如文档注释包含使用*标记列表项的项目符号列表。
|
||||
|
||||
### 考虑为私有api编写文档注释
|
||||
|
||||
Doc注释并不仅仅针对库的公共API的外部使用者。它们还有助于理解从库的其他部分调用的私有成员
|
||||
|
||||
#### 用一句话总结开始doc注释
|
||||
|
||||
以简短的、以用户为中心的描述开始你的文档注释,以句号结尾。
|
||||
|
||||
```
|
||||
/// Deletes the file at [path] from the file system.
|
||||
void delete(String path) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
/// Depending on the state of the file system and the user's permissions,
|
||||
/// certain operations may or may not be possible. If there is no file at
|
||||
/// [path] or it can't be accessed, this function throws either [IOError]
|
||||
/// or [PermissionError], respectively. Otherwise, this deletes the file.
|
||||
void delete(String path) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
#### “doc注释”的第一句话分隔成自己的段落
|
||||
|
||||
在第一个句子之后添加一个空行,把它分成自己的段落
|
||||
|
||||
```
|
||||
/// Deletes the file at [path].
|
||||
///
|
||||
/// Throws an [IOError] if the file could not be found. Throws a
|
||||
/// [PermissionError] if the file is present but could not be deleted.
|
||||
void delete(String path) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
## Flutter_Go 使用参考
|
||||
|
||||
### 库的引用
|
||||
|
||||
flutter go 中,导入lib下文件库,统一指定包名,避免过多的```../../```
|
||||
```
|
||||
package:flutter_go/
|
||||
```
|
||||
|
||||
### 字符串的使用
|
||||
|
||||
#### 使用相邻字符串连接字符串文字
|
||||
如果有两个字符串字面值(不是值,而是实际引用的字面值),则不需要使用+连接它们。就像在C和c++中,简单地把它们放在一起就能做到。这是创建一个长字符串很好的方法但是不适用于单独一行。
|
||||
|
||||
```
|
||||
raiseAlarm(
|
||||
'ERROR: Parts of the spaceship are on fire. Other '
|
||||
'parts are overrun by martians. Unclear which are which.');
|
||||
```
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
raiseAlarm('ERROR: Parts of the spaceship are on fire. Other ' +
|
||||
'parts are overrun by martians. Unclear which are which.');
|
||||
```
|
||||
|
||||
#### 优先使用模板字符串
|
||||
```
|
||||
'Hello, $name! You are ${year - birth} years old.';
|
||||
```
|
||||
|
||||
#### 在不需要的时候,避免使用花括号
|
||||
|
||||
```
|
||||
'Hi, $name!'
|
||||
"Wear your wildest $decade's outfit."
|
||||
```
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
'Hello, ' + name + '! You are ' + (year - birth).toString() + ' y...';
|
||||
```
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
'Hi, ${name}!'
|
||||
"Wear your wildest ${decade}'s outfit."
|
||||
```
|
||||
|
||||
### 集合
|
||||
|
||||
#### 尽可能使用集合字面量
|
||||
|
||||
如果要创建一个不可增长的列表,或者其他一些自定义集合类型,那么无论如何,都要使用构造函数。
|
||||
|
||||
```
|
||||
var points = [];
|
||||
var addresses = {};
|
||||
var lines = <Lines>[];
|
||||
```
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
var points = List();
|
||||
var addresses = Map();
|
||||
```
|
||||
|
||||
#### 不要使用.length查看集合是否为空
|
||||
|
||||
```
|
||||
if (lunchBox.isEmpty) return 'so hungry...';
|
||||
if (words.isNotEmpty) return words.join(' ');
|
||||
```
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
if (lunchBox.length == 0) return 'so hungry...';
|
||||
if (!words.isEmpty) return words.join(' ');
|
||||
```
|
||||
|
||||
#### 考虑使用高阶方法转换序列
|
||||
|
||||
如果有一个集合,并且希望从中生成一个新的修改后的集合,那么使用.map()、.where()和Iterable上的其他方便的方法通常更短,也更具有声明性
|
||||
|
||||
```
|
||||
var aquaticNames = animals
|
||||
.where((animal) => animal.isAquatic)
|
||||
.map((animal) => animal.name);
|
||||
```
|
||||
#### 避免使用带有函数字面量的Iterable.forEach()
|
||||
|
||||
在Dart中,如果你想遍历一个序列,惯用的方法是使用循环。
|
||||
|
||||
```
|
||||
for (var person in people) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
people.forEach((person) {
|
||||
...
|
||||
});
|
||||
```
|
||||
|
||||
#### 不要使用List.from(),除非打算更改结果的类型
|
||||
|
||||
给定一个迭代,有两种明显的方法可以生成包含相同元素的新列表
|
||||
|
||||
```
|
||||
var copy1 = iterable.toList();
|
||||
var copy2 = List.from(iterable);
|
||||
```
|
||||
|
||||
明显的区别是第一个比较短。重要的区别是第一个保留了原始对象的类型参数
|
||||
|
||||
```
|
||||
// Creates a List<int>:
|
||||
var iterable = [1, 2, 3];
|
||||
|
||||
// Prints "List<int>":
|
||||
print(iterable.toList().runtimeType);
|
||||
```
|
||||
|
||||
```
|
||||
// Creates a List<int>:
|
||||
var iterable = [1, 2, 3];
|
||||
|
||||
// Prints "List<dynamic>":
|
||||
print(List.from(iterable).runtimeType);
|
||||
```
|
||||
|
||||
### 参数的使用
|
||||
|
||||
#### 使用=将命名参数与其默认值分割开
|
||||
|
||||
由于遗留原因,Dart均允许“:”和“=”作为指定参数的默认值分隔符。为了与可选的位置参数保持一致,使用“=”。
|
||||
|
||||
```
|
||||
void insert(Object item, {int at = 0}) { ... }
|
||||
```
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
void insert(Object item, {int at: 0}) { ... }
|
||||
```
|
||||
|
||||
#### 不要使用显式默认值null
|
||||
|
||||
如果参数是可选的,但没有给它一个默认值,则语言隐式地使用null作为默认值,因此不需要编写它
|
||||
|
||||
```
|
||||
void error([String message]) {
|
||||
stderr.write(message ?? '\n');
|
||||
}
|
||||
```
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
void error([String message = null]) {
|
||||
stderr.write(message ?? '\n');
|
||||
}
|
||||
```
|
||||
|
||||
### 变量
|
||||
|
||||
#### 不要显式地将变量初始化为空
|
||||
在Dart中,未显式初始化的变量或字段自动被初始化为null。不要多余赋值null
|
||||
|
||||
```
|
||||
int _nextId;
|
||||
|
||||
class LazyId {
|
||||
int _id;
|
||||
|
||||
int get id {
|
||||
if (_nextId == null) _nextId = 0;
|
||||
if (_id == null) _id = _nextId++;
|
||||
|
||||
return _id;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
int _nextId = null;
|
||||
|
||||
class LazyId {
|
||||
int _id = null;
|
||||
|
||||
int get id {
|
||||
if (_nextId == null) _nextId = 0;
|
||||
if (_id == null) _id = _nextId++;
|
||||
|
||||
return _id;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 避免储存你能计算的东西
|
||||
|
||||
在设计类时,您通常希望将多个视图公开到相同的底层状态。通常你会看到在构造函数中计算所有视图的代码,然后存储它们:
|
||||
|
||||
应该避免的写法:
|
||||
|
||||
```
|
||||
class Circle {
|
||||
num radius;
|
||||
num area;
|
||||
num circumference;
|
||||
|
||||
Circle(num radius)
|
||||
: radius = radius,
|
||||
area = pi * radius * radius,
|
||||
circumference = pi * 2.0 * radius;
|
||||
}
|
||||
```
|
||||
|
||||
如上代码问题:
|
||||
|
||||
- 浪费内存
|
||||
- 缓存的问题是无效——如何知道何时缓存过期需要重新计算?
|
||||
|
||||
推荐的写法如下:
|
||||
|
||||
```
|
||||
class Circle {
|
||||
num radius;
|
||||
|
||||
Circle(this.radius);
|
||||
|
||||
num get area => pi * radius * radius;
|
||||
num get circumference => pi * 2.0 * radius;
|
||||
}
|
||||
```
|
||||
|
||||
### 类成员
|
||||
|
||||
#### 不要把不必要地将字段包装在getter和setter中
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
class Box {
|
||||
var _contents;
|
||||
get contents => _contents;
|
||||
set contents(value) {
|
||||
_contents = value;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 优先使用final字段来创建只读属性
|
||||
|
||||
尤其对于 ```StatelessWidget```
|
||||
|
||||
#### 在不需要的时候不要用this
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
class Box {
|
||||
var value;
|
||||
|
||||
void clear() {
|
||||
this.update(null);
|
||||
}
|
||||
|
||||
void update(value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
推荐如下写法:
|
||||
|
||||
```
|
||||
class Box {
|
||||
var value;
|
||||
|
||||
void clear() {
|
||||
update(null);
|
||||
}
|
||||
|
||||
void update(value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 构造函数
|
||||
|
||||
#### 尽可能使用初始化的形式
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
class Point {
|
||||
num x, y;
|
||||
Point(num x, num y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
推荐如下写法:
|
||||
|
||||
```
|
||||
class Point {
|
||||
num x, y;
|
||||
Point(this.x, this.y);
|
||||
}
|
||||
```
|
||||
|
||||
#### 不要使用new
|
||||
|
||||
Dart2使new 关键字可选
|
||||
|
||||
推荐写法:
|
||||
|
||||
```
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
RaisedButton(
|
||||
child: Text('Increment'),
|
||||
),
|
||||
Text('Click!'),
|
||||
],
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
不推荐如下写法:
|
||||
|
||||
```
|
||||
Widget build(BuildContext context) {
|
||||
return new Row(
|
||||
children: [
|
||||
new RaisedButton(
|
||||
child: new Text('Increment'),
|
||||
),
|
||||
new Text('Click!'),
|
||||
],
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 异步
|
||||
|
||||
#### 优先使用async/await代替原始的futures
|
||||
|
||||
async/await语法提高了可读性,允许你在异步代码中使用所有Dart控制流结构。
|
||||
|
||||
```
|
||||
Future<int> countActivePlayers(String teamName) async {
|
||||
try {
|
||||
var team = await downloadTeam(teamName);
|
||||
if (team == null) return 0;
|
||||
|
||||
var players = await team.roster;
|
||||
return players.where((player) => player.isActive).length;
|
||||
} catch (e) {
|
||||
log.error(e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 当异步没有任何用处时,不要使用它
|
||||
|
||||
如果可以在不改变函数行为的情况下省略异步,那么就这样做。、
|
||||
|
||||
```
|
||||
Future afterTwoThings(Future first, Future second) {
|
||||
return Future.wait([first, second]);
|
||||
}
|
||||
```
|
||||
|
||||
不推荐写法:
|
||||
|
||||
```
|
||||
Future afterTwoThings(Future first, Future second) async {
|
||||
return Future.wait([first, second]);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
88
README-en.md
Normal file
@ -0,0 +1,88 @@
|
||||
## Flutter Go
|
||||
|
||||

|
||||
|
||||
> Help developers get started quickly Flutter **Flutter Go 1.0 Android has been released**
|
||||
|
||||
|
||||
## Download URL
|
||||
|
||||
Android download URL:
|
||||
|
||||
<img src="https://img.alicdn.com/tfs/TB180.kOhYaK1RjSZFnXXa80pXa-442-420.png" width="200px">
|
||||
|
||||
Iphone download URL:
|
||||
No
|
||||
|
||||
## Development Environment
|
||||
This Project need latest package, please update regularly.
|
||||
|
||||
- dart(version: 2.0.0)
|
||||
- flutter(version: v1.0.0)
|
||||
|
||||
### Background
|
||||
|
||||
#### What is Flutter?
|
||||
|
||||
On June 21, 2018, Google released the first release preview of Flutter as a new responsive, cross-platform, high-performance mobile development framework launched by Google. Flutter is a cross-platform mobile UI framework designed to help developers develop high-performance, high-fidelity Android and iOS apps using a single set of code.
|
||||
|
||||
The advantages of Flutter mainly include:
|
||||
- Cross-platform
|
||||
- Open source
|
||||
- Hot Reload, responsive framework, and its rich controls and development tools
|
||||
- Flexible interface design and control combinations
|
||||
- High quality user experience with a portable GPU-accelerated rendering engine and high-performance ARM code runtime
|
||||
|
||||
#### The origin of Flutter Go
|
||||
|
||||
- Flutter has too little learning material, which is relatively difficult for students who are not good at English.
|
||||
- The official website document example is not sound enough, not intuitive enough
|
||||
- The usage of each widget is different, and the properties are numerous. To run a demo of a widget, it is often necessary to look through various materials everywhere.
|
||||
|
||||
#### Advantages of Flutter Go
|
||||
|
||||
- Detailed idiom widgets up to **130+**
|
||||
- Companion Demo Explain the widget's general usage
|
||||
- Centralized integration of widget cases, an APP to get all the usage of common widgets
|
||||
- Continuous iteration ‘chasing new’ official version
|
||||
|
||||
### App Preview
|
||||
|
||||
<img src="https://img.alicdn.com/tfs/TB1oeicBhjaK1RjSZFAXXbdLFXa-345-717.gif" width=200> <img src="https://img.alicdn.com/tfs/TB1WJNuBmzqK1RjSZPcXXbTepXa-345-717.gif" width=200> <img src="https://img.alicdn.com/tfs/TB13Xh3BkvoK1RjSZFNXXcxMVXa-345-717.gif" width=200> <img src="https://img.alicdn.com/tfs/TB1MtdSBjDpK1RjSZFrXXa78VXa-345-717.gif" width=200>
|
||||
|
||||
|
||||
### Core Team
|
||||
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" width="80" valign="top">
|
||||
<img height="80" width="80" src="https://github.com/minghe.png?s=128">
|
||||
<br>
|
||||
<a href="https://github.com/minghe">@minghe</a>
|
||||
</td>
|
||||
<td align="center" width="80" valign="top">
|
||||
<img height="80" width="80" src="https://github.com/ryan730.png?s=128">
|
||||
<br>
|
||||
<a href="https://github.com/ryan730">@ryan730</a>
|
||||
</td>
|
||||
<td align="center" width="80" valign="top">
|
||||
<img height="80" width="80" src="https://github.com/Nealyang.png?s=128">
|
||||
<br>
|
||||
<a href="https://github.com/Nealyang">@Nealyang</a>
|
||||
</td>
|
||||
<td align="center" width="80" valign="top">
|
||||
<img height="80" width="80" src="https://github.com/hanxu317317.png?s=128">
|
||||
<br>
|
||||
<a href="https://github.com/hanxu317317">@hanxu317317</a>
|
||||
</td>
|
||||
<td align="center" width="80" valign="top">
|
||||
<img height="80" width="80" src="https://github.com/DeckeDeng.png?s=128">
|
||||
<br>
|
||||
<a href="https://github.com/DeckeDeng">@DeckeDeng</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
Powered by [Alibaba Auction Front-end Team](https://github.com/alibaba-paimai-frontend)<img src="https://img.alicdn.com/tfs/TB1foEhAMHqK1RjSZJnXXbNLpXa-166-166.png" width= 20 height=20>
|
28
README.md
@ -1,17 +1,36 @@
|
||||
Language: [English](https://github.com/alibaba/flutter-go/blob/master/README-en.md) | [中文简体](https://github.com/alibaba/flutter-go/blob/master/README.md)
|
||||
## Flutter Go
|
||||
|
||||
> 帮助开发者快速上手 Flutter **内部测试中,1.0 正式版将于 2月 20日 发布。**
|
||||

|
||||
|
||||
> 帮助开发者快速上手 Flutter **Flutter Go 1.0 Android版已正式发布**
|
||||
|
||||
## 版本更新历史
|
||||
> 按时间顺序,展示重要的提交更新内容。
|
||||
|
||||
[地址](https://github.com/alibaba/flutter-go/blob/develop/CHANGE-LOG.md)
|
||||
|
||||
## 开发规范
|
||||
> 由于类似 javascript, java, object-c,等开发者的语言习惯不同而产生歧义,我们依据官方提供的 [dart 语言规范](https://www.dartlang.org) 定制。
|
||||
|
||||
[<< Flutter Go 开发规范第一版 >>](https://github.com/alibaba/flutter-go/blob/develop/Flutter_Go%20%E4%BB%A3%E7%A0%81%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83.md)
|
||||
|
||||
## Release安装包下载地址
|
||||
|
||||
android下载地址:
|
||||
|
||||
<img src="https://img.alicdn.com/tfs/TB1q1GVB4naK1RjSZFtXXbC2VXa-195-198.png" width="200px">
|
||||
<img src="https://img.alicdn.com/tfs/TB180.kOhYaK1RjSZFnXXa80pXa-442-420.png" width="200px">
|
||||
|
||||
iphone下载地址:
|
||||
暂无
|
||||
|
||||
## 基础环境
|
||||
本项目环境持续更新. 请定期更新各依赖包.
|
||||
|
||||
- dart(version: 2.0.0)
|
||||
- flutter(version: v1.0.0)
|
||||
|
||||
|
||||
### 背景
|
||||
|
||||
#### Flutter 是什么?
|
||||
@ -33,14 +52,15 @@ flutter优点主要包括:
|
||||
|
||||
#### Flutter Go 的优势
|
||||
|
||||
- 详解常用widget多达 **130+** 个
|
||||
- 详解常用widget多达 **140+** 个
|
||||
- 配套 Demo 详解 widget 常规用法
|
||||
- 集中整合 widget 案例,一个 APP 搞定所有常用 widget 的用法
|
||||
- 持续迭代 ‘追新’ 官方版本
|
||||
|
||||
### app 预览
|
||||
|
||||
<img src="https://img.alicdn.com/tfs/TB1oeicBhjaK1RjSZFAXXbdLFXa-345-717.gif" width=200> <img src="https://img.alicdn.com/tfs/TB1WJNuBmzqK1RjSZPcXXbTepXa-345-717.gif" width=200> <img src="https://img.alicdn.com/tfs/TB13Xh3BkvoK1RjSZFNXXcxMVXa-345-717.gif" width=200> <img src="https://img.alicdn.com/tfs/TB1MtdSBjDpK1RjSZFrXXa78VXa-345-717.gif" width=200>
|
||||
|
||||
<img src="https://img.alicdn.com/tfs/TB1MoiNExTpK1RjSZFGXXcHqFXa-362-751.gif" width=200> <img src="https://img.alicdn.com/tfs/TB1oeicBhjaK1RjSZFAXXbdLFXa-345-717.gif" width=200> <img src="https://img.alicdn.com/tfs/TB1WJNuBmzqK1RjSZPcXXbTepXa-345-717.gif" width=200> <img src="https://img.alicdn.com/tfs/TB13Xh3BkvoK1RjSZFNXXcxMVXa-345-717.gif" width=200>
|
||||
|
||||
### Core Team
|
||||
|
||||
|
@ -22,18 +22,23 @@ if (flutterVersionName == null) {
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||
|
||||
android {
|
||||
compileSdkVersion 27
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
disable 'InvalidPackage'
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId "com.example.flutterrookiebook"
|
||||
applicationId "com.ali.fluttergo"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 27
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
@ -55,6 +60,7 @@ flutter {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||
|
7
android/app/src/debug/AndroidManifest.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.ali.fluttergo">
|
||||
<!-- Flutter needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
@ -1,28 +1,25 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.flutterrookiebook">
|
||||
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
flutter needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.MODE_WORLD_READABLE"/>
|
||||
<uses-permission android:name="android.permission.MODE_WORLD_WRITEABLE"/>
|
||||
package="com.ali.fluttergo">
|
||||
|
||||
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
||||
calls FlutterMain.startInitialization(this); in its onCreate method.
|
||||
In most cases you can leave this as-is, but you if you want to provide
|
||||
additional functionality it is fine to subclass or reimplement
|
||||
FlutterApplication and put your custom class here. -->
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.MODE_WORLD_READABLE"/>
|
||||
<uses-permission android:name="android.permission.MODE_WORLD_WRITEABLE"/>
|
||||
|
||||
<application
|
||||
android:name="io.flutter.app.FlutterApplication"
|
||||
android:label="菜鸟手册"
|
||||
android:icon="@drawable/logo">
|
||||
android:label="fluttergo"
|
||||
android:icon="@mipmap/ic_launcher_logo">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!-- This keeps the window background of the activity showing
|
||||
|
@ -0,0 +1,13 @@
|
||||
package com.ali.fluttergo
|
||||
|
||||
import android.os.Bundle
|
||||
|
||||
import io.flutter.app.FlutterActivity
|
||||
import io.flutter.plugins.GeneratedPluginRegistrant
|
||||
|
||||
class MainActivity: FlutterActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
GeneratedPluginRegistrant.registerWith(this)
|
||||
}
|
||||
}
|
BIN
android/app/src/main/res/drawable/flutter_go_logo.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
@ -4,9 +4,9 @@
|
||||
<item android:drawable="@android:color/white" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<!-- <item>
|
||||
<item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
android:src="@mipmap/splash" />
|
||||
</item>
|
||||
</layer-list>
|
||||
|
BIN
android/app/src/main/res/drawable/splash.png
Normal file
After Width: | Height: | Size: 197 KiB |
8
android/app/src/main/res/layout/activity_main.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/splash">
|
||||
|
||||
|
||||
</LinearLayout>
|
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_logo.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_logo.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher_logo.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/splash.png
Normal file
After Width: | Height: | Size: 197 KiB |
BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher_logo.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_logo.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
7
android/app/src/profile/AndroidManifest.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.ali.fluttergo">
|
||||
<!-- Flutter needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
@ -1,4 +1,5 @@
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.2.71'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
@ -6,6 +7,7 @@ buildscript {
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.2.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
|
BIN
assets/app.db
BIN
assets/fonts/Flamante-Roma-Medium.ttf
Executable file
BIN
assets/fonts/Flamante-Roma-MediumItalic.ttf
Executable file
BIN
assets/fonts/Lato-Bold.ttf
Executable file
BIN
assets/images/painterImg.jpeg
Normal file
After Width: | Height: | Size: 185 KiB |
@ -7,8 +7,24 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0828E495220692B500A59437 /* iPhone Portrait-Retina 4.png in Resources */ = {isa = PBXBuildFile; fileRef = 0828E486220692B400A59437 /* iPhone Portrait-Retina 4.png */; };
|
||||
0828E496220692B500A59437 /* iPad Portrait.png in Resources */ = {isa = PBXBuildFile; fileRef = 0828E487220692B400A59437 /* iPad Portrait.png */; };
|
||||
0828E497220692B500A59437 /* iPhone X_XS Landscape.png in Resources */ = {isa = PBXBuildFile; fileRef = 0828E488220692B400A59437 /* iPhone X_XS Landscape.png */; };
|
||||
0828E498220692B500A59437 /* iPhone XS Max Portrait.png in Resources */ = {isa = PBXBuildFile; fileRef = 0828E489220692B400A59437 /* iPhone XS Max Portrait.png */; };
|
||||
0828E499220692B500A59437 /* iPhone Portrait-Retina HD 4.7.png in Resources */ = {isa = PBXBuildFile; fileRef = 0828E48A220692B400A59437 /* iPhone Portrait-Retina HD 4.7.png */; };
|
||||
0828E49A220692B500A59437 /* iPhone X_XS Portrait.png in Resources */ = {isa = PBXBuildFile; fileRef = 0828E48B220692B400A59437 /* iPhone X_XS Portrait.png */; };
|
||||
0828E49B220692B500A59437 /* iPad Landscape@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0828E48C220692B400A59437 /* iPad Landscape@2x.png */; };
|
||||
0828E49C220692B500A59437 /* iPhone Landscape-Retina HD 5.5.png in Resources */ = {isa = PBXBuildFile; fileRef = 0828E48D220692B400A59437 /* iPhone Landscape-Retina HD 5.5.png */; };
|
||||
0828E49D220692B500A59437 /* iPhone Portrait@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0828E48E220692B400A59437 /* iPhone Portrait@2x.png */; };
|
||||
0828E49E220692B500A59437 /* iPad Portrait@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0828E48F220692B400A59437 /* iPad Portrait@2x.png */; };
|
||||
0828E49F220692B500A59437 /* iPhone XS Max Landscape.png in Resources */ = {isa = PBXBuildFile; fileRef = 0828E490220692B400A59437 /* iPhone XS Max Landscape.png */; };
|
||||
0828E4A0220692B500A59437 /* iPad Landscape.png in Resources */ = {isa = PBXBuildFile; fileRef = 0828E491220692B500A59437 /* iPad Landscape.png */; };
|
||||
0828E4A1220692B500A59437 /* iPhone XR Portrait.png in Resources */ = {isa = PBXBuildFile; fileRef = 0828E492220692B500A59437 /* iPhone XR Portrait.png */; };
|
||||
0828E4A2220692B500A59437 /* iPhone Portrait-Retina HD 5.5.png in Resources */ = {isa = PBXBuildFile; fileRef = 0828E493220692B500A59437 /* iPhone Portrait-Retina HD 5.5.png */; };
|
||||
0828E4A3220692B500A59437 /* iPhone XR Landscape.png in Resources */ = {isa = PBXBuildFile; fileRef = 0828E494220692B500A59437 /* iPhone XR Landscape.png */; };
|
||||
0828E4A52206936100A59437 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0828E4A42206936100A59437 /* Images.xcassets */; };
|
||||
084A20882202E4FD00428FF5 /* flutter go.png in Resources */ = {isa = PBXBuildFile; fileRef = 084A20872202E4FD00428FF5 /* flutter go.png */; };
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||
2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; };
|
||||
333E5DAE7FC10AC69FEC26C0 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DDA792F029EDD7A11295D192 /* libPods-Runner.a */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
|
||||
@ -38,9 +54,25 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0828E486220692B400A59437 /* iPhone Portrait-Retina 4.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iPhone Portrait-Retina 4.png"; sourceTree = "<group>"; };
|
||||
0828E487220692B400A59437 /* iPad Portrait.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iPad Portrait.png"; sourceTree = "<group>"; };
|
||||
0828E488220692B400A59437 /* iPhone X_XS Landscape.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iPhone X_XS Landscape.png"; sourceTree = "<group>"; };
|
||||
0828E489220692B400A59437 /* iPhone XS Max Portrait.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iPhone XS Max Portrait.png"; sourceTree = "<group>"; };
|
||||
0828E48A220692B400A59437 /* iPhone Portrait-Retina HD 4.7.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iPhone Portrait-Retina HD 4.7.png"; sourceTree = "<group>"; };
|
||||
0828E48B220692B400A59437 /* iPhone X_XS Portrait.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iPhone X_XS Portrait.png"; sourceTree = "<group>"; };
|
||||
0828E48C220692B400A59437 /* iPad Landscape@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iPad Landscape@2x.png"; sourceTree = "<group>"; };
|
||||
0828E48D220692B400A59437 /* iPhone Landscape-Retina HD 5.5.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iPhone Landscape-Retina HD 5.5.png"; sourceTree = "<group>"; };
|
||||
0828E48E220692B400A59437 /* iPhone Portrait@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iPhone Portrait@2x.png"; sourceTree = "<group>"; };
|
||||
0828E48F220692B400A59437 /* iPad Portrait@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iPad Portrait@2x.png"; sourceTree = "<group>"; };
|
||||
0828E490220692B400A59437 /* iPhone XS Max Landscape.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iPhone XS Max Landscape.png"; sourceTree = "<group>"; };
|
||||
0828E491220692B500A59437 /* iPad Landscape.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iPad Landscape.png"; sourceTree = "<group>"; };
|
||||
0828E492220692B500A59437 /* iPhone XR Portrait.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iPhone XR Portrait.png"; sourceTree = "<group>"; };
|
||||
0828E493220692B500A59437 /* iPhone Portrait-Retina HD 5.5.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iPhone Portrait-Retina HD 5.5.png"; sourceTree = "<group>"; };
|
||||
0828E494220692B500A59437 /* iPhone XR Landscape.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iPhone XR Landscape.png"; sourceTree = "<group>"; };
|
||||
0828E4A42206936100A59437 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
|
||||
084A20872202E4FD00428FF5 /* flutter go.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "flutter go.png"; sourceTree = "<group>"; };
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||
@ -72,6 +104,28 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
0828E485220692A700A59437 /* launch */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0828E491220692B500A59437 /* iPad Landscape.png */,
|
||||
0828E48C220692B400A59437 /* iPad Landscape@2x.png */,
|
||||
0828E48F220692B400A59437 /* iPad Portrait@2x.png */,
|
||||
0828E487220692B400A59437 /* iPad Portrait.png */,
|
||||
0828E48D220692B400A59437 /* iPhone Landscape-Retina HD 5.5.png */,
|
||||
0828E486220692B400A59437 /* iPhone Portrait-Retina 4.png */,
|
||||
0828E48A220692B400A59437 /* iPhone Portrait-Retina HD 4.7.png */,
|
||||
0828E493220692B500A59437 /* iPhone Portrait-Retina HD 5.5.png */,
|
||||
0828E48E220692B400A59437 /* iPhone Portrait@2x.png */,
|
||||
0828E488220692B400A59437 /* iPhone X_XS Landscape.png */,
|
||||
0828E48B220692B400A59437 /* iPhone X_XS Portrait.png */,
|
||||
0828E494220692B500A59437 /* iPhone XR Landscape.png */,
|
||||
0828E492220692B500A59437 /* iPhone XR Portrait.png */,
|
||||
0828E490220692B400A59437 /* iPhone XS Max Landscape.png */,
|
||||
0828E489220692B400A59437 /* iPhone XS Max Portrait.png */,
|
||||
);
|
||||
path = launch;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0C172CA58CDB230D5DA80034 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -90,7 +144,6 @@
|
||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2D5378251FAA1A9400D5DBA9 /* flutter_assets */,
|
||||
3B80C3931E831B6300D905FE /* App.framework */,
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
||||
9740EEBA1CF902C7004384FC /* Flutter.framework */,
|
||||
@ -104,6 +157,8 @@
|
||||
97C146E51CF9000F007C117D = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0828E485220692A700A59437 /* launch */,
|
||||
084A20872202E4FD00428FF5 /* flutter go.png */,
|
||||
9740EEB11CF90186004384FC /* Flutter */,
|
||||
97C146F01CF9000F007C117D /* Runner */,
|
||||
97C146EF1CF9000F007C117D /* Products */,
|
||||
@ -132,6 +187,7 @@
|
||||
97C146F11CF9000F007C117D /* Supporting Files */,
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
||||
0828E4A42206936100A59437 /* Images.xcassets */,
|
||||
);
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
@ -207,11 +263,27 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0828E4A0220692B500A59437 /* iPad Landscape.png in Resources */,
|
||||
0828E4A1220692B500A59437 /* iPhone XR Portrait.png in Resources */,
|
||||
0828E49F220692B500A59437 /* iPhone XS Max Landscape.png in Resources */,
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
||||
0828E4A3220692B500A59437 /* iPhone XR Landscape.png in Resources */,
|
||||
0828E4A2220692B500A59437 /* iPhone Portrait-Retina HD 5.5.png in Resources */,
|
||||
0828E49A220692B500A59437 /* iPhone X_XS Portrait.png in Resources */,
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||
0828E49E220692B500A59437 /* iPad Portrait@2x.png in Resources */,
|
||||
0828E49D220692B500A59437 /* iPhone Portrait@2x.png in Resources */,
|
||||
0828E499220692B500A59437 /* iPhone Portrait-Retina HD 4.7.png in Resources */,
|
||||
084A20882202E4FD00428FF5 /* flutter go.png in Resources */,
|
||||
0828E497220692B500A59437 /* iPhone X_XS Landscape.png in Resources */,
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
||||
2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */,
|
||||
0828E4A52206936100A59437 /* Images.xcassets in Resources */,
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
||||
0828E49B220692B500A59437 /* iPad Landscape@2x.png in Resources */,
|
||||
0828E495220692B500A59437 /* iPhone Portrait-Retina 4.png in Resources */,
|
||||
0828E498220692B500A59437 /* iPhone XS Max Portrait.png in Resources */,
|
||||
0828E496220692B500A59437 /* iPad Portrait.png in Resources */,
|
||||
0828E49C220692B500A59437 /* iPhone Landscape-Retina HD 5.5.png in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -237,11 +309,15 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||
);
|
||||
@ -269,11 +345,15 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
|
||||
"${PODS_ROOT}/../.symlinks/flutter/ios-release/Flutter.framework",
|
||||
"${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
|
||||
);
|
||||
@ -428,6 +508,7 @@
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = Launch2;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = RDJKXT446D;
|
||||
ENABLE_BITCODE = NO;
|
||||
@ -441,7 +522,7 @@
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterRookieBook;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.ali.flutterRookieBook;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
@ -452,6 +533,7 @@
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = Launch2;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = RDJKXT446D;
|
||||
ENABLE_BITCODE = NO;
|
||||
@ -465,7 +547,7 @@
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterRookieBook;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.ali.flutterRookieBook;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
|
@ -7,6 +7,7 @@
|
||||
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
[GeneratedPluginRegistrant registerWithRegistry:self];
|
||||
// Override point for customization after application launch.
|
||||
[NSThread sleepForTimeInterval:2];
|
||||
return [super application:application didFinishLaunchingWithOptions:launchOptions];
|
||||
}
|
||||
|
||||
|
13
ios/Runner/AppDelegate.swift
Normal file
@ -0,0 +1,13 @@
|
||||
import UIKit
|
||||
import Flutter
|
||||
|
||||
@UIApplicationMain
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
override func application(
|
||||
_ application: UIApplication,
|
||||
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
|
||||
) -> Bool {
|
||||
GeneratedPluginRegistrant.register(with: self)
|
||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
}
|
||||
}
|
6
ios/Runner/Assets.xcassets/Contents.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
20
ios/Runner/Assets.xcassets/Image.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
201
ios/Runner/Assets.xcassets/Launch2.launchimage/Contents.json
Normal file
@ -0,0 +1,201 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"extent" : "full-screen",
|
||||
"idiom" : "iphone",
|
||||
"subtype" : "2688h",
|
||||
"filename" : "iPhone XS Max Portrait.png",
|
||||
"minimum-system-version" : "12.0",
|
||||
"orientation" : "portrait",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"orientation" : "landscape",
|
||||
"idiom" : "iphone",
|
||||
"extent" : "full-screen",
|
||||
"minimum-system-version" : "12.0",
|
||||
"subtype" : "2688h",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"extent" : "full-screen",
|
||||
"idiom" : "iphone",
|
||||
"subtype" : "1792h",
|
||||
"filename" : "iPhone XR Portrait.png",
|
||||
"minimum-system-version" : "12.0",
|
||||
"orientation" : "portrait",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "landscape",
|
||||
"idiom" : "iphone",
|
||||
"extent" : "full-screen",
|
||||
"minimum-system-version" : "12.0",
|
||||
"subtype" : "1792h",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"extent" : "full-screen",
|
||||
"idiom" : "iphone",
|
||||
"subtype" : "2436h",
|
||||
"filename" : "iPhone X_XS Portrait.png",
|
||||
"minimum-system-version" : "11.0",
|
||||
"orientation" : "portrait",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"orientation" : "landscape",
|
||||
"idiom" : "iphone",
|
||||
"extent" : "full-screen",
|
||||
"minimum-system-version" : "11.0",
|
||||
"subtype" : "2436h",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"extent" : "full-screen",
|
||||
"idiom" : "iphone",
|
||||
"subtype" : "736h",
|
||||
"filename" : "iPhone Portrait-Retina HD 5.5.png",
|
||||
"minimum-system-version" : "8.0",
|
||||
"orientation" : "portrait",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"orientation" : "landscape",
|
||||
"idiom" : "iphone",
|
||||
"extent" : "full-screen",
|
||||
"minimum-system-version" : "8.0",
|
||||
"subtype" : "736h",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"extent" : "full-screen",
|
||||
"idiom" : "iphone",
|
||||
"subtype" : "667h",
|
||||
"filename" : "iPhone Portrait-Retina HD 4.7.png",
|
||||
"minimum-system-version" : "8.0",
|
||||
"orientation" : "portrait",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "iPhone Portrait@2x.png",
|
||||
"extent" : "full-screen",
|
||||
"minimum-system-version" : "7.0",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"extent" : "full-screen",
|
||||
"idiom" : "iphone",
|
||||
"subtype" : "retina4",
|
||||
"filename" : "iPhone Portrait-Retina 4.png",
|
||||
"minimum-system-version" : "7.0",
|
||||
"orientation" : "portrait",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "iPad Portrait.png",
|
||||
"extent" : "full-screen",
|
||||
"minimum-system-version" : "7.0",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"orientation" : "landscape",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "iPad Landscape.png",
|
||||
"extent" : "full-screen",
|
||||
"minimum-system-version" : "7.0",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "iPad Portrait@2x.png",
|
||||
"extent" : "full-screen",
|
||||
"minimum-system-version" : "7.0",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "landscape",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "iPad Landscape@2x.png",
|
||||
"extent" : "full-screen",
|
||||
"minimum-system-version" : "7.0",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "iphone",
|
||||
"extent" : "full-screen",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "iphone",
|
||||
"extent" : "full-screen",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "iphone",
|
||||
"extent" : "full-screen",
|
||||
"subtype" : "retina4",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "ipad",
|
||||
"extent" : "to-status-bar",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "ipad",
|
||||
"extent" : "full-screen",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"orientation" : "landscape",
|
||||
"idiom" : "ipad",
|
||||
"extent" : "to-status-bar",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"orientation" : "landscape",
|
||||
"idiom" : "ipad",
|
||||
"extent" : "full-screen",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "ipad",
|
||||
"extent" : "to-status-bar",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "ipad",
|
||||
"extent" : "full-screen",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "landscape",
|
||||
"idiom" : "ipad",
|
||||
"extent" : "to-status-bar",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "landscape",
|
||||
"idiom" : "ipad",
|
||||
"extent" : "full-screen",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 110 KiB |
After Width: | Height: | Size: 296 KiB |
BIN
ios/Runner/Assets.xcassets/Launch2.launchimage/iPad Portrait.png
Normal file
After Width: | Height: | Size: 110 KiB |
After Width: | Height: | Size: 296 KiB |
After Width: | Height: | Size: 126 KiB |
After Width: | Height: | Size: 159 KiB |
After Width: | Height: | Size: 325 KiB |
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 243 KiB |
After Width: | Height: | Size: 426 KiB |
After Width: | Height: | Size: 371 KiB |
@ -2,17 +2,29 @@
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "LaunchImage.png",
|
||||
"filename" : "flutter go.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "LaunchImage@2x.png",
|
||||
"filename" : "flutter go-1.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "LaunchImage@3x.png",
|
||||
"filename" : "flutter go-2.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
@ -20,4 +32,4 @@
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
}
|
BIN
ios/Runner/Assets.xcassets/LaunchImage.imageset/flutter go-1.png
vendored
Normal file
After Width: | Height: | Size: 197 KiB |
BIN
ios/Runner/Assets.xcassets/LaunchImage.imageset/flutter go-2.png
vendored
Normal file
After Width: | Height: | Size: 197 KiB |
BIN
ios/Runner/Assets.xcassets/LaunchImage.imageset/flutter go.png
vendored
Normal file
After Width: | Height: | Size: 197 KiB |
@ -1,8 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
@ -14,24 +18,30 @@
|
||||
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
|
||||
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
|
||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
|
||||
<constraint firstAttribute="bottom" secondItem="YRO-k0-Ey4" secondAttribute="bottom" id="T5g-9A-c9v"/>
|
||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="eyW-WF-YgD"/>
|
||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="veX-UW-bF2"/>
|
||||
<constraint firstAttribute="trailing" secondItem="YRO-k0-Ey4" secondAttribute="trailing" id="yhF-ag-fuv"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
<point key="canvasLocation" x="84.799999999999997" y="337.33133433283359"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="LaunchImage" width="168" height="185"/>
|
||||
<image name="LaunchImage" width="1080" height="1920"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
@ -0,0 +1,49 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "ipad",
|
||||
"minimum-system-version" : "7.0",
|
||||
"extent" : "full-screen",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "landscape",
|
||||
"idiom" : "ipad",
|
||||
"minimum-system-version" : "7.0",
|
||||
"extent" : "full-screen",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"orientation" : "landscape",
|
||||
"idiom" : "ipad",
|
||||
"minimum-system-version" : "7.0",
|
||||
"extent" : "full-screen",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "iphone",
|
||||
"minimum-system-version" : "7.0",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "iphone",
|
||||
"minimum-system-version" : "7.0",
|
||||
"subtype" : "retina4",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "ipad",
|
||||
"minimum-system-version" : "7.0",
|
||||
"extent" : "full-screen",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>菜鸟App</string>
|
||||
<string>Flutter Go</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
|
1
ios/Runner/Runner-Bridging-Header.h
Normal file
@ -0,0 +1 @@
|
||||
#import "GeneratedPluginRegistrant.h"
|
BIN
ios/flutter go.png
Normal file
After Width: | Height: | Size: 197 KiB |
BIN
ios/launch/iPad Landscape.png
Normal file
After Width: | Height: | Size: 110 KiB |
BIN
ios/launch/iPad Landscape@2x.png
Normal file
After Width: | Height: | Size: 296 KiB |
BIN
ios/launch/iPad Portrait.png
Normal file
After Width: | Height: | Size: 110 KiB |
BIN
ios/launch/iPad Portrait@2x.png
Normal file
After Width: | Height: | Size: 296 KiB |
BIN
ios/launch/iPhone Landscape-Retina HD 5.5.png
Normal file
After Width: | Height: | Size: 323 KiB |
BIN
ios/launch/iPhone Portrait-Retina 4.png
Normal file
After Width: | Height: | Size: 126 KiB |
BIN
ios/launch/iPhone Portrait-Retina HD 4.7.png
Normal file
After Width: | Height: | Size: 159 KiB |
BIN
ios/launch/iPhone Portrait-Retina HD 5.5.png
Normal file
After Width: | Height: | Size: 325 KiB |
BIN
ios/launch/iPhone Portrait@2x.png
Normal file
After Width: | Height: | Size: 100 KiB |
BIN
ios/launch/iPhone XR Landscape.png
Normal file
After Width: | Height: | Size: 167 KiB |
BIN
ios/launch/iPhone XR Portrait.png
Normal file
After Width: | Height: | Size: 243 KiB |
BIN
ios/launch/iPhone XS Max Landscape.png
Normal file
After Width: | Height: | Size: 308 KiB |
BIN
ios/launch/iPhone XS Max Portrait.png
Normal file
After Width: | Height: | Size: 426 KiB |
BIN
ios/launch/iPhone X_XS Landscape.png
Normal file
After Width: | Height: | Size: 266 KiB |
BIN
ios/launch/iPhone X_XS Portrait.png
Normal file
After Width: | Height: | Size: 371 KiB |
@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../model/cat.dart';
|
||||
import '../common/widget_name_to_icon.dart';
|
||||
import '../resources/widget_name_to_icon.dart';
|
||||
import '../components/widget_item_container.dart';
|
||||
|
||||
class CateCard extends StatefulWidget {
|
||||
|
143
lib/components/category.dart
Normal file
@ -0,0 +1,143 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../routers/application.dart';
|
||||
import '../model/cat.dart';
|
||||
import '../model/widget.dart';
|
||||
import '../widgets/index.dart';
|
||||
import '../components/widget_item_container.dart';
|
||||
|
||||
enum CateOrWigdet { Cat, WidgetDemo }
|
||||
|
||||
class CategoryHome extends StatefulWidget {
|
||||
CategoryHome(this.name);
|
||||
final String name;
|
||||
|
||||
@override
|
||||
_CategoryHome createState() => new _CategoryHome();
|
||||
}
|
||||
|
||||
class _CategoryHome extends State<CategoryHome> {
|
||||
String title = '';
|
||||
// 显示列表 cat or widget;
|
||||
List<Cat> categories = [];
|
||||
List<WidgetPoint> widgetPoints = [];
|
||||
List<Cat> catHistory = new List();
|
||||
|
||||
CatControlModel catControl = new CatControlModel();
|
||||
WidgetControlModel widgetControl = new WidgetControlModel();
|
||||
// 所有的可用demos;
|
||||
List widgetDemosList = new WidgetDemoList().getDemos();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// 初始化加入顶级的name
|
||||
this.getCatByName(widget.name).then((Cat cat) {
|
||||
catHistory.add(cat);
|
||||
searchCatOrWigdet();
|
||||
});
|
||||
}
|
||||
|
||||
Future<Cat> getCatByName(String name) async {
|
||||
return await catControl.getCatByName(name);
|
||||
}
|
||||
|
||||
Future<bool> back() {
|
||||
if (catHistory.length == 1) {
|
||||
return Future<bool>.value(true);
|
||||
}
|
||||
catHistory.removeLast();
|
||||
searchCatOrWigdet();
|
||||
return Future<bool>.value(false);
|
||||
}
|
||||
|
||||
void go(Cat cat) {
|
||||
catHistory.add(cat);
|
||||
searchCatOrWigdet();
|
||||
}
|
||||
|
||||
void searchCatOrWigdet() async {
|
||||
// 假设进入这个界面的parent一定存在
|
||||
Cat parentCat = catHistory.last;
|
||||
|
||||
|
||||
// 继续搜索显示下一级depth: depth + 1, parentId: parentCat.id
|
||||
List<Cat> _categories =
|
||||
await catControl.getList(new Cat(parentId: parentCat.id));
|
||||
List<WidgetPoint> _widgetPoints = new List();
|
||||
if (_categories.isEmpty) {
|
||||
_widgetPoints =
|
||||
await widgetControl.getList(new WidgetPoint(catId: parentCat.id));
|
||||
}
|
||||
|
||||
this.setState(() {
|
||||
categories = _categories;
|
||||
title = parentCat.name;
|
||||
widgetPoints = _widgetPoints;
|
||||
});
|
||||
}
|
||||
|
||||
void onCatgoryTap(Cat cat) {
|
||||
go(cat);
|
||||
}
|
||||
|
||||
void onWidgetTap(WidgetPoint widgetPoint) {
|
||||
String targetName = widgetPoint.name;
|
||||
String targetRouter = '/category/error/404';
|
||||
widgetDemosList.forEach((item) {
|
||||
// print("targetRouter = item.routerName> ${[item.name,targetName]}");
|
||||
if (item.name == targetName) {
|
||||
targetRouter = item.routerName;
|
||||
}
|
||||
});
|
||||
Application.router.navigateTo(context, "$targetRouter");
|
||||
}
|
||||
|
||||
Widget _buildContent() {
|
||||
WidgetItemContainer wiContaienr = WidgetItemContainer(
|
||||
columnCount: 3,
|
||||
categories: categories,
|
||||
isWidgetPoint:false
|
||||
);
|
||||
if (widgetPoints.length > 0) {
|
||||
wiContaienr = WidgetItemContainer(
|
||||
categories: widgetPoints,
|
||||
columnCount: 3,
|
||||
isWidgetPoint:true
|
||||
);
|
||||
}
|
||||
return Container(
|
||||
padding: const EdgeInsets.only(bottom: 10.0, top: 5.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
image: DecorationImage(
|
||||
image: AssetImage('assets/images/paimaiLogo.png'),
|
||||
alignment: Alignment.bottomRight),
|
||||
),
|
||||
child: wiContaienr,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(title),
|
||||
),
|
||||
body: WillPopScope(
|
||||
onWillPop: () {
|
||||
return back();
|
||||
},
|
||||
child: ListView(
|
||||
children: <Widget>[
|
||||
_buildContent(),
|
||||
],
|
||||
),
|
||||
// child: Container(color: Colors.blue,child: Text('123'),),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,265 +1,196 @@
|
||||
/**
|
||||
* Created with Android Studio.
|
||||
* User: 一晟
|
||||
* Date: 2019/1/12
|
||||
* Time: 下午9:19
|
||||
* email: zhu.yan@alibaba-inc.com
|
||||
*/
|
||||
/// Created with Android Studio.
|
||||
/// User: 一晟
|
||||
/// Date: 2019/1/12
|
||||
/// Time: 下午9:19
|
||||
/// email: zhu.yan@alibaba-inc.com
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
//import 'package:flutter_rookie_book/model/collection_general.dart';
|
||||
//import 'package:flutter_rookie_book/model/collection_general.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
|
||||
const disclaimerText1 = '\r\r\r\r\r\r本APP属于个人的非赢利性开源项目,以供开源社区使用,凡本APP转载的所有的文章 、图片、音频、视频文件等资料的版权归版权所有人所有,本APP采用的非本站原创文章及图片等内容无法一一和版权者联系,如果本网所选内容的文章作者及编辑认为其作品不宜上网供大家浏览,或不应无偿使用请及时用电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。';
|
||||
const disclaimerText2 = '\n\r\r\r\r\r\r对于已经授权本APP独家使用并提供给本站资料的版权所有人的文章、图片等资料,如需转载使用,需取得本站和版权所有人的同意。本APP所刊发、转载的文章,其版权均归原作者所有,如其他媒体、网站或个人从本网下载使用,请在转载有关文章时务必尊重该文章的著作权,保留本网注明的“稿件来源”,并自负版权等法律责任。';
|
||||
|
||||
const disclaimerText1 =
|
||||
'\r\r\r\r\r\r本APP属于个人的非赢利性开源项目,以供开源社区使用,凡本APP转载的所有的文章 、图片、音频、视频文件等资料的版权归版权所有人所有,本APP采用的非本站原创文章及图片等内容无法一一和版权者联系,如果本网所选内容的文章作者及编辑认为其作品不宜上网供大家浏览,或不应无偿使用请及时用电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。';
|
||||
const disclaimerText2 =
|
||||
'\n\r\r\r\r\r\r对于已经授权本APP独家使用并提供给本站资料的版权所有人的文章、图片等资料,如需转载使用,需取得本站和版权所有人的同意。本APP所刊发、转载的文章,其版权均归原作者所有,如其他媒体、网站或个人从本网下载使用,请在转载有关文章时务必尊重该文章的著作权,保留本网注明的“稿件来源”,并自负版权等法律责任。';
|
||||
|
||||
class DisclaimerMsg extends StatefulWidget {
|
||||
final State pWidget;
|
||||
DisclaimerMsg({ Key key, this.pWidget }) : super(key: key);
|
||||
|
||||
DisclaimerMsg({Key key, this.pWidget}) : super(key: key);
|
||||
|
||||
DisclaimerMsgState createState() => DisclaimerMsgState();
|
||||
}
|
||||
|
||||
class DisclaimerMsgState extends State<DisclaimerMsg> {
|
||||
Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
|
||||
Future<bool> _unKnow;
|
||||
var _valBool = false;
|
||||
var _page;
|
||||
//CollectionControlModel _collectionControl = new CollectionControlModel();
|
||||
//List<CollectionGeneral> _collectionList = [];
|
||||
// void init(BuildContext context) {
|
||||
// Toast.show(context: context, message: "👉 APP免责声明",cb:showAlertDialog);
|
||||
// }
|
||||
var _readed = false;
|
||||
|
||||
//SharedPreferences 存储结果
|
||||
void refs(bool value) async {
|
||||
final SharedPreferences prefs = await _prefs;
|
||||
final bool unKnow = value;
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_unKnow = prefs.setBool("disclaimer::Boolean", unKnow).then((bool success) {
|
||||
return unKnow;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// _collectionList.clear();
|
||||
// _collectionControl.getAllCollection().then((resultList) {
|
||||
// resultList.forEach((item) {
|
||||
// _collectionList.add(item);
|
||||
// print('=============db=========${item}');
|
||||
// });
|
||||
// });
|
||||
_page = widget.pWidget;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void refs(bool value){
|
||||
if(this.mounted){
|
||||
setState(() {
|
||||
_valBool=value;
|
||||
_page.save(value);
|
||||
});
|
||||
|
||||
// _collectionControl
|
||||
// .insert(CollectionGeneral(key: 'disclaimer', values: value.toString()))
|
||||
// .then((result) {
|
||||
// print('result2====${result}');
|
||||
// }
|
||||
// );
|
||||
}
|
||||
//获取SharedPreferences 存储结果
|
||||
_unKnow = _prefs.then((SharedPreferences prefs) {
|
||||
return (prefs.getBool('disclaimer::Boolean') ?? false);
|
||||
});
|
||||
_unKnow.then((bool value) {
|
||||
_valBool = value;
|
||||
_readed = value;
|
||||
});
|
||||
}
|
||||
|
||||
void showAlertDialog(BuildContext context) {
|
||||
// new Future.delayed(Duration(seconds: 5)).then((value) {
|
||||
// Navigator.of(context).pop();
|
||||
// });
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
barrierDismissible: false, // user must tap button!
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
//title: Text('免责声明'),
|
||||
content:SingleChildScrollView(
|
||||
child: ListBody(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(5.0, 5.0, 10.0, 10.0),
|
||||
//width: 100,
|
||||
height: 35,
|
||||
child: Text('免责声明',style:TextStyle(fontSize: 18,fontWeight:FontWeight.w700 )),
|
||||
decoration: BoxDecoration(
|
||||
//color: Colors.blue,
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.fitWidth,
|
||||
image: AssetImage('assets/images/paimaiLogo.png')
|
||||
),
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(10.0),
|
||||
),
|
||||
//alignment: Alignment.bottomRight,
|
||||
)
|
||||
),
|
||||
SizedBox(height:20),
|
||||
Text(disclaimerText1),
|
||||
Text(disclaimerText2),
|
||||
],
|
||||
),
|
||||
),
|
||||
shape:RoundedRectangleBorder(borderRadius: new BorderRadius.circular(20.0)), // 圆角
|
||||
actions: <Widget>[
|
||||
Container(
|
||||
width: 270,
|
||||
alignment: Alignment.centerLeft,
|
||||
padding: new EdgeInsets.fromLTRB(0.0, 0.0, 30.0, 0.0),
|
||||
child:
|
||||
Row(
|
||||
mainAxisAlignment:MainAxisAlignment.spaceAround,
|
||||
//crossAxisAlignment:CrossAxisAlignment.start,
|
||||
content: SingleChildScrollView(
|
||||
child: ListBody(
|
||||
children: <Widget>[
|
||||
Row(
|
||||
mainAxisAlignment:MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Checkbox(
|
||||
activeColor: Theme.of(context).primaryColor,
|
||||
tristate:false,
|
||||
value: _valBool,
|
||||
onChanged: (bool bol) {
|
||||
refs(bol);
|
||||
Navigator.of(context).pop(); // here I pop to avoid multiple Dialogs
|
||||
showAlertDialog(context); //here i call the same function
|
||||
}
|
||||
),
|
||||
Text('不再自动提示',style:TextStyle(fontSize: 14)),
|
||||
],
|
||||
),
|
||||
new Flexible(
|
||||
flex: 1,
|
||||
child: Container(width: 100,)
|
||||
),
|
||||
FlatButton(
|
||||
child: Text('知道了',style:TextStyle(fontSize: 16,color: Colors.white)),
|
||||
color: Theme.of(context).primaryColor,
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
]
|
||||
// SizedBox(
|
||||
// width:150,
|
||||
// height:55,
|
||||
// child: CheckboxListTile(
|
||||
// title: Text('不再显示',style:TextStyle(fontSize: 14)),
|
||||
// controlAffinity: ListTileControlAffinity.leading,
|
||||
// activeColor: Colors.red,
|
||||
// value: _valBool,
|
||||
// onChanged: (bool value) {
|
||||
// refs(value);
|
||||
// Navigator.of(context).pop(); // here I pop to avoid multiple Dialogs
|
||||
// showAlertDialog(context); //here i call the same function
|
||||
// }
|
||||
// )
|
||||
// //secondary: const Icon(Icons.hourglass_empty),
|
||||
// ),
|
||||
// Checkbox(
|
||||
// activeColor: Colors.red,
|
||||
// tristate:false,
|
||||
// value: _valBool,
|
||||
// onChanged: (bool bol) {
|
||||
// refs(bol);
|
||||
// Navigator.of(context).pop(); // here I pop to avoid multiple Dialogs
|
||||
// showAlertDialog(context); //here i call the same function
|
||||
// }
|
||||
// ),
|
||||
// Text('不再显示',style:TextStyle(fontSize: 14)),
|
||||
// FlatButton(
|
||||
// child: Text('知道了',style:TextStyle(fontSize: 16,color: Colors.green)),
|
||||
// onPressed: () {
|
||||
// Navigator.of(context).pop();
|
||||
// },
|
||||
// ),
|
||||
// ],
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(5.0, 5.0, 10.0, 10.0),
|
||||
//width: 100,
|
||||
height: 35,
|
||||
child: Text('免责声明',
|
||||
style: TextStyle(
|
||||
fontSize: 18, fontWeight: FontWeight.w700)),
|
||||
decoration: BoxDecoration(
|
||||
//color: Colors.blue,
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.fitWidth,
|
||||
image: AssetImage('assets/images/paimaiLogo.png')),
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(10.0),
|
||||
),
|
||||
//alignment: Alignment.bottomRight,
|
||||
)),
|
||||
SizedBox(height: 20),
|
||||
Text(disclaimerText1),
|
||||
Text(disclaimerText2),
|
||||
],
|
||||
),
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: new BorderRadius.circular(20.0)), // 圆角
|
||||
|
||||
actions: <Widget>[
|
||||
new Container(
|
||||
width: 250,
|
||||
child: _create(),
|
||||
)
|
||||
)],
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
Widget build(BuildContext context) {
|
||||
return new GestureDetector(
|
||||
onTap: () {
|
||||
showAlertDialog(context);
|
||||
},
|
||||
child: Stack(
|
||||
//alignment: const Alignment(1.6, 1.6),
|
||||
children: [
|
||||
new Container(
|
||||
width:90.0,
|
||||
alignment: Alignment.center,
|
||||
decoration: new BoxDecoration(
|
||||
borderRadius:new BorderRadius.horizontal(right: Radius.circular(10)),
|
||||
color: Colors.black45,
|
||||
),
|
||||
child: new Text(
|
||||
'🔔 免责声明',
|
||||
style: new TextStyle(
|
||||
fontSize: 14.0,
|
||||
//fontWeight: FontWeight.bold,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Widget build2(BuildContext context) {
|
||||
return Container(
|
||||
padding: new EdgeInsets.all(0.0),
|
||||
alignment:Alignment.centerRight,
|
||||
child:FlatButton(
|
||||
//padding: new EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0),
|
||||
child: new Text(
|
||||
'👉 APP免责声明',
|
||||
style: new TextStyle(
|
||||
fontSize: 12.0, //textsize
|
||||
color: Colors.black54, // textcolor
|
||||
),
|
||||
),
|
||||
//color: Theme.of(context).accentColor,
|
||||
color: Theme.of(context).accentColor,
|
||||
//elevation: 0.0,//shadow
|
||||
//splashColor: Colors.blueGrey,
|
||||
Row _create() {
|
||||
//已读
|
||||
if (_readed) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: <Widget>[
|
||||
FlatButton(
|
||||
padding: EdgeInsets.symmetric(horizontal: 20.0),
|
||||
child: Text('已阅读知晓',
|
||||
style: TextStyle(fontSize: 16, color: Colors.white)),
|
||||
//可点击
|
||||
color: Theme.of(context).primaryColor,
|
||||
onPressed: () {
|
||||
showAlertDialog(context);
|
||||
//Toast.show(context: context, message: "👉 APP免责声明",cb:showAlertDialog);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
SizedBox(
|
||||
width: 10.0,
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
class Toast {
|
||||
static void show({@required BuildContext context, @required String message,Function cb}) {
|
||||
//创建一个OverlayEntry对象
|
||||
OverlayEntry overlayEntry = new OverlayEntry(builder: (context) {
|
||||
return new Positioned(
|
||||
top: MediaQuery.of(context).size.height * 0.12,
|
||||
right:5.0,
|
||||
child:RaisedButton(
|
||||
padding: new EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
|
||||
child: new Text(
|
||||
'👉 APP免责声明',
|
||||
style: new TextStyle(
|
||||
fontSize: 14.0, //textsize
|
||||
color: Colors.black54, // textcolor
|
||||
//第一次读取
|
||||
return Row(mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
//crossAxisAlignment:CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Checkbox(
|
||||
activeColor: Theme.of(context).primaryColor,
|
||||
tristate: false,
|
||||
value: _valBool,
|
||||
onChanged: (bool bol) {
|
||||
if(mounted) {
|
||||
setState(() {
|
||||
_valBool = bol;
|
||||
});
|
||||
}
|
||||
Navigator.of(context).pop(); // here I pop to avoid multiple Dialogs
|
||||
showAlertDialog(context); //here i call the same function
|
||||
}),
|
||||
Text('不再自动提示', style: TextStyle(fontSize: 14)),
|
||||
],
|
||||
),
|
||||
FlatButton(
|
||||
child: Text('知道了',
|
||||
style: TextStyle(fontSize: 16, color: Colors.white)),
|
||||
//可点击
|
||||
color: _valBool
|
||||
? Theme.of(context).primaryColor
|
||||
: Theme.of(context).primaryColor.withAlpha(800),
|
||||
onPressed: () {
|
||||
// if (_valBool) {
|
||||
refs(_valBool);
|
||||
Navigator.of(context).pop();
|
||||
// }
|
||||
},
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
showAlertDialog(context);
|
||||
},
|
||||
child: Stack(
|
||||
//alignment: const Alignment(1.6, 1.6),
|
||||
children: [
|
||||
Container(
|
||||
width: 90.0,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius:
|
||||
BorderRadius.horizontal(right: Radius.circular(10)),
|
||||
color: Colors.black45,
|
||||
),
|
||||
child: Text(
|
||||
'🔔 免责声明',
|
||||
style: TextStyle(
|
||||
fontSize: 14.0,
|
||||
//fontWeight: FontWeight.bold,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
//color: Theme.of(context).accentColor,
|
||||
color: Colors.red,
|
||||
//elevation: 0.0,//shadow
|
||||
//splashColor: Colors.blueGrey,
|
||||
onPressed: () {
|
||||
if(cb is Function){
|
||||
cb(context);
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
//往Overlay中插入插入OverlayEntry
|
||||
Overlay.of(context).insert(overlayEntry);
|
||||
new Future.delayed(Duration(seconds: 2)).then((value) {
|
||||
//overlayEntry.remove();
|
||||
});
|
||||
),
|
||||
],
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
81
lib/components/full_screen_code_dialog.dart
Normal file
@ -0,0 +1,81 @@
|
||||
/// @Author: 一凨
|
||||
/// @Date: 2019-01-14 11:42:32
|
||||
/// @Last Modified by: 一凨
|
||||
/// @Last Modified time: 2019-01-14 14:42:00
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_go/utils/example_code_parser.dart';
|
||||
import 'package:flutter_go/utils/syntax_highlighter.dart';
|
||||
|
||||
class FullScreenCodeDialog extends StatefulWidget {
|
||||
const FullScreenCodeDialog({this.filePath});
|
||||
|
||||
final String filePath;
|
||||
_FullScreenCodeDialogState createState() => _FullScreenCodeDialogState();
|
||||
}
|
||||
|
||||
class _FullScreenCodeDialogState extends State<FullScreenCodeDialog> {
|
||||
String _exampleCode;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
print('widget.filePath=======${widget.filePath}');
|
||||
getExampleCode(context,'${widget.filePath}', DefaultAssetBundle.of(context))
|
||||
.then<void>((String code) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_exampleCode = code ?? 'Example code not found';
|
||||
});
|
||||
}
|
||||
});
|
||||
super.didChangeDependencies();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final SyntaxHighlighterStyle style =
|
||||
Theme.of(context).brightness == Brightness.dark
|
||||
? SyntaxHighlighterStyle.darkThemeStyle()
|
||||
: SyntaxHighlighterStyle.lightThemeStyle();
|
||||
|
||||
Widget body;
|
||||
if (_exampleCode == null) {
|
||||
body = const Center(child: CircularProgressIndicator());
|
||||
} else {
|
||||
Widget _codeWidget;
|
||||
try{
|
||||
DartSyntaxHighlighter(style).format(_exampleCode);
|
||||
_codeWidget = RichText(
|
||||
text: TextSpan(
|
||||
style: const TextStyle(fontFamily: 'monospace', fontSize: 10.0),
|
||||
children: <TextSpan>[
|
||||
DartSyntaxHighlighter(style).format(_exampleCode)
|
||||
],),
|
||||
);
|
||||
}catch (err){
|
||||
_codeWidget = Text(_exampleCode);
|
||||
}
|
||||
body = SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: _codeWidget,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: IconButton(
|
||||
icon: const Icon(
|
||||
Icons.clear,
|
||||
semanticLabel: 'Close',
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
title: const Text('Example code'),
|
||||
),
|
||||
body: body);
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../model/story.dart';
|
||||
|
||||
class HomeBanner extends StatefulWidget {
|
||||
|
@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Created with Android Studio.
|
||||
* User: 一晟
|
||||
* Date: 2019/1/4
|
||||
* Time: 上午1:16
|
||||
* email: zhu.yan@alibaba-inc.com
|
||||
* tartget: FlatButton 的示例
|
||||
*/
|
||||
/// Created with Android Studio.
|
||||
/// User: 一晟
|
||||
/// Date: 2019/1/4
|
||||
/// Time: 上午1:16
|
||||
/// email: zhu.yan@alibaba-inc.com
|
||||
/// target: ListRefresh 的示例
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ListRefresh extends StatefulWidget {
|
||||
@ -40,9 +41,7 @@ class _ListRefreshState extends State<ListRefresh> {
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* 回弹效果
|
||||
* */
|
||||
// 回弹效果
|
||||
backElasticEffect() {
|
||||
// double edge = 50.0;
|
||||
// double offsetFromBottom = _scrollController.position.maxScrollExtent - _scrollController.position.pixels;
|
||||
@ -54,13 +53,13 @@ class _ListRefreshState extends State<ListRefresh> {
|
||||
// }
|
||||
}
|
||||
|
||||
/*
|
||||
* list探底,执行的具体事件
|
||||
* */
|
||||
// list探底,执行的具体事件
|
||||
Future _getMoreData() async {
|
||||
if (!isLoading && _hasMore) {
|
||||
// 如果上一次异步请求数据完成 同时有数据可以加载
|
||||
setState(() => isLoading = true);
|
||||
if (mounted) {
|
||||
setState(() => isLoading = true);
|
||||
}
|
||||
//if(_hasMore){ // 还有数据可以拉新
|
||||
List newEntries = await mokeHttpRequest();
|
||||
//if (newEntries.isEmpty) {
|
||||
@ -79,9 +78,7 @@ class _ListRefreshState extends State<ListRefresh> {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 伪装吐出新数据
|
||||
* */
|
||||
// 伪装吐出新数据
|
||||
Future<List> mokeHttpRequest() async {
|
||||
if (widget.requestApi is Function) {
|
||||
final listObj = await widget.requestApi({'pageIndex': _pageIndex});
|
||||
@ -94,11 +91,8 @@ class _ListRefreshState extends State<ListRefresh> {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 下拉加载的事件,清空之前list内容,取前X个
|
||||
* 其实就是列表重置
|
||||
* */
|
||||
// 下拉加载的事件,清空之前list内容,取前X个
|
||||
// 其实就是列表重置
|
||||
Future<Null> _handleRefresh() async {
|
||||
List newEntries = await mokeHttpRequest();
|
||||
if (this.mounted) {
|
||||
@ -112,9 +106,7 @@ class _ListRefreshState extends State<ListRefresh> {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 加载中的提示
|
||||
* */
|
||||
// 加载中的提示
|
||||
Widget _buildLoadText() {
|
||||
return Container(
|
||||
child: Padding(
|
||||
@ -125,9 +117,7 @@ class _ListRefreshState extends State<ListRefresh> {
|
||||
));
|
||||
}
|
||||
|
||||
/*
|
||||
* 上提加载loading的widget,如果数据到达极限,显示没有更多
|
||||
* */
|
||||
// 上提加载loading的widget,如果数据到达极限,显示没有更多
|
||||
Widget _buildProgressIndicator() {
|
||||
if (_hasMore) {
|
||||
return new Padding(
|
||||
|
53
lib/components/list_view_item.dart
Normal file
@ -0,0 +1,53 @@
|
||||
/// @Author: 一凨
|
||||
/// @Date: 2019-01-14 17:53:54
|
||||
/// @Last Modified by: 一凨
|
||||
/// @Last Modified time: 2019-01-14 17:57:51
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import '../routers/application.dart';
|
||||
import '../routers/routers.dart';
|
||||
import 'dart:core';
|
||||
|
||||
|
||||
class ListViewItem extends StatelessWidget {
|
||||
final String itemUrl;
|
||||
final String itemTitle;
|
||||
final String data;
|
||||
|
||||
const ListViewItem({Key key, this.itemUrl, this.itemTitle, this.data})
|
||||
: super(key: key);
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card(
|
||||
color: Colors.white,
|
||||
elevation: 4.0,
|
||||
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
|
||||
child: ListTile(
|
||||
onTap: () {
|
||||
// _launchURL(itemUrl, context);
|
||||
Application.router.navigateTo(context, '${Routes.webViewPage}?title=${Uri.encodeComponent(itemTitle)}&url=${Uri.encodeComponent(itemUrl)}');
|
||||
},
|
||||
title: Padding(
|
||||
child: Text(
|
||||
itemTitle,
|
||||
style: TextStyle(color: Colors.black, fontSize: 15.0),
|
||||
),
|
||||
padding: EdgeInsets.only(top: 10.0),
|
||||
),
|
||||
subtitle: Row(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
child: Text(data,
|
||||
style: TextStyle(color: Colors.black54, fontSize: 10.0)),
|
||||
padding: EdgeInsets.only(top: 10.0, bottom: 10.0),
|
||||
)
|
||||
],
|
||||
),
|
||||
trailing:
|
||||
Icon(Icons.keyboard_arrow_right, color: Colors.grey, size: 30.0),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
import 'package:flutter_markdown/flutter_markdown.dart' as md;
|
||||
import '../common/high_light_code.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_go/utils/high_light_code.dart';
|
||||
|
||||
/// 使用方法
|
||||
/// MarkdownBody(markdown)
|
||||
final hightlighter = new HighLight();
|
||||
|
@ -3,9 +3,10 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import './home_banner.dart';
|
||||
import '../model/story.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class Pagination extends StatelessWidget {
|
||||
static final String routeName = '/material/page-selector';
|
||||
|
@ -1,6 +1,11 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluro/fluro.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:flutter_go/resources/widget_name_to_icon.dart';
|
||||
import 'package:flutter_go/routers/application.dart';
|
||||
import '../model/search_history.dart';
|
||||
|
||||
typedef String FormFieldFormatter<T>(T v);
|
||||
typedef bool MaterialSearchFilter<T>(T v, String c);
|
||||
@ -18,13 +23,14 @@ class MaterialSearchResult<T> extends StatelessWidget {
|
||||
this.onTap
|
||||
}) : super(key: key);
|
||||
|
||||
final T value;
|
||||
final String value;
|
||||
final VoidCallback onTap;
|
||||
final String text;
|
||||
final IconData icon;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return new InkWell(
|
||||
onTap: this.onTap,
|
||||
child: new Container(
|
||||
@ -32,8 +38,8 @@ class MaterialSearchResult<T> extends StatelessWidget {
|
||||
padding: EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 10.0),
|
||||
child: new Row(
|
||||
children: <Widget>[
|
||||
new Container(width: 30.0, child: new Icon(icon)) ?? null,
|
||||
new Expanded(child: new Text(text, style: Theme.of(context).textTheme.subhead)),
|
||||
new Container(width: 30.0, margin: EdgeInsets.only(right: 10), child: new Icon(icon)) ?? null,
|
||||
new Expanded(child: new Text(value, style: Theme.of(context).textTheme.subhead)),
|
||||
new Text(text, style: Theme.of(context).textTheme.subhead)
|
||||
],
|
||||
),
|
||||
@ -407,11 +413,9 @@ class History extends StatefulWidget {
|
||||
_History createState() => _History();
|
||||
}
|
||||
|
||||
/*
|
||||
* AppBar 默认的实例,有状态
|
||||
* */
|
||||
// AppBar 默认的实例,有状态
|
||||
class _History extends State<History> {
|
||||
|
||||
SearchHistoryList searchHistoryList = new SearchHistoryList();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -422,11 +426,68 @@ class _History extends State<History> {
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
buildChips(BuildContext context) {
|
||||
List<Widget> list = [];
|
||||
List<SearchHistory> historyList = searchHistoryList.getList();
|
||||
print("historyList> $historyList");
|
||||
Color bgColor = Theme.of(context).primaryColor;
|
||||
historyList.forEach((SearchHistory value) {
|
||||
|
||||
Widget icon = CircleAvatar(
|
||||
backgroundColor: bgColor,
|
||||
child: Text(
|
||||
value.name.substring(0, 1),
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
);
|
||||
if (WidgetName2Icon.icons[value.name] != null) {
|
||||
icon = Icon(WidgetName2Icon.icons[value.name], size: 25);
|
||||
}
|
||||
|
||||
list.add(
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Application.router.navigateTo(context, "${value.targetRouter}", transition: TransitionType.inFromRight);
|
||||
},
|
||||
child: Chip(
|
||||
avatar: icon,
|
||||
label: Text("${value.name}"),
|
||||
),
|
||||
)
|
||||
);
|
||||
});
|
||||
return list;
|
||||
}
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new Center(
|
||||
child: Text('这是一个即将完善的历史记录的面板'),
|
||||
List<Widget> childList = buildChips(context);
|
||||
if (childList.length == 0) {
|
||||
return Center(
|
||||
child: Text("当前历史面板为空"),
|
||||
);
|
||||
}
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
alignment: Alignment.centerLeft,
|
||||
padding: EdgeInsets.fromLTRB(12.0, 12, 12, 0),
|
||||
child: InkWell(
|
||||
onLongPress: () {
|
||||
searchHistoryList.clear();
|
||||
},
|
||||
child: Text('历史搜索'),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 10),
|
||||
alignment: Alignment.topLeft,
|
||||
child: Wrap(
|
||||
spacing: 6.0, // gap between adjacent chips
|
||||
runSpacing: 0.0, // gap between lines
|
||||
children: childList
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
200
lib/components/widget_demo.dart
Normal file
@ -0,0 +1,200 @@
|
||||
/// @author Nealyang
|
||||
/// 新widget详情页模板
|
||||
|
||||
import 'dart:core';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../routers/application.dart';
|
||||
import '../routers/routers.dart';
|
||||
import '../components/markdown.dart';
|
||||
import '../model/collection.dart';
|
||||
import '../widgets/index.dart';
|
||||
import '../event/event_bus.dart';
|
||||
import '../event/event_model.dart';
|
||||
|
||||
class WidgetDemo extends StatefulWidget {
|
||||
final List<dynamic> contentList;
|
||||
final String docUrl;
|
||||
final String title;
|
||||
final String codeUrl;
|
||||
final Widget bottomNaviBar;
|
||||
|
||||
WidgetDemo(
|
||||
{Key key,
|
||||
@required this.title,
|
||||
@required this.contentList,
|
||||
@required this.codeUrl,
|
||||
@required this.docUrl,
|
||||
this.bottomNaviBar})
|
||||
: super(key: key);
|
||||
|
||||
_WidgetDemoState createState() => _WidgetDemoState();
|
||||
}
|
||||
|
||||
class _WidgetDemoState extends State<WidgetDemo> {
|
||||
bool _hasCollected = false;
|
||||
CollectionControlModel _collectionControl = new CollectionControlModel();
|
||||
var _collectionIcons;
|
||||
List widgetDemosList = new WidgetDemoList().getDemos();
|
||||
String _router = '';
|
||||
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
|
||||
List<Widget> _buildContent() {
|
||||
List<Widget> _list = [
|
||||
SizedBox(
|
||||
height: 10.0,
|
||||
),
|
||||
];
|
||||
widget.contentList.forEach((item) {
|
||||
if (item.runtimeType == String) {
|
||||
_list.add(MarkdownBody(item));
|
||||
_list.add(
|
||||
SizedBox(
|
||||
height: 20.0,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
_list.add(item);
|
||||
}
|
||||
});
|
||||
return _list;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_collectionControl.getRouterByName(widget.title).then((list) {
|
||||
widgetDemosList.forEach((item) {
|
||||
if (item.name == widget.title) {
|
||||
_router = item.routerName;
|
||||
}
|
||||
});
|
||||
if (this.mounted) {
|
||||
setState(() {
|
||||
_hasCollected = list.length > 0;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 点击收藏按钮
|
||||
_getCollection() {
|
||||
if (_hasCollected) {
|
||||
// 删除操作
|
||||
_collectionControl.deleteByName(widget.title).then((result) {
|
||||
if (result > 0 && this.mounted) {
|
||||
setState(() {
|
||||
_hasCollected = false;
|
||||
});
|
||||
_scaffoldKey.currentState
|
||||
.showSnackBar(SnackBar(content: Text('已取消收藏')));
|
||||
if (ApplicationEvent.event != null) {
|
||||
ApplicationEvent.event
|
||||
.fire(CollectionEvent(widget.title, _router, true));
|
||||
}
|
||||
return;
|
||||
}
|
||||
print('删除错误');
|
||||
});
|
||||
} else {
|
||||
// 插入操作
|
||||
_collectionControl
|
||||
.insert(Collection(name: widget.title, router: _router))
|
||||
.then((result) {
|
||||
if (this.mounted) {
|
||||
setState(() {
|
||||
_hasCollected = true;
|
||||
});
|
||||
|
||||
if (ApplicationEvent.event != null) {
|
||||
ApplicationEvent.event
|
||||
.fire(CollectionEvent(widget.title, _router, false));
|
||||
}
|
||||
|
||||
_scaffoldKey.currentState
|
||||
.showSnackBar(SnackBar(content: Text('收藏成功')));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _selectValue(value) {
|
||||
if (value == 'doc') {
|
||||
// _launchURL(widget.docUrl);
|
||||
Application.router.navigateTo(context,
|
||||
'${Routes.webViewPage}?title=${Uri.encodeComponent(widget.title)} Doc&&url=${Uri.encodeComponent(widget.docUrl)}');
|
||||
} else if (value == 'code') {
|
||||
Application.router.navigateTo(context,
|
||||
'${Routes.codeView}?filePath=${Uri.encodeComponent(widget.codeUrl)}');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_hasCollected) {
|
||||
_collectionIcons = Icons.favorite;
|
||||
} else {
|
||||
_collectionIcons = Icons.favorite_border;
|
||||
}
|
||||
return Scaffold(
|
||||
key: _scaffoldKey,
|
||||
appBar: AppBar(
|
||||
title: Text(widget.title),
|
||||
actions: <Widget>[
|
||||
new IconButton(
|
||||
tooltip: 'goBack home',
|
||||
onPressed: () {
|
||||
Navigator.popUntil(context, ModalRoute.withName('/'));
|
||||
},
|
||||
icon: Icon(Icons.home),
|
||||
),
|
||||
new IconButton(
|
||||
tooltip: 'collection',
|
||||
onPressed: _getCollection,
|
||||
icon: Icon(_collectionIcons),
|
||||
),
|
||||
PopupMenuButton<String>(
|
||||
onSelected: _selectValue,
|
||||
itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
|
||||
const PopupMenuItem<String>(
|
||||
value: 'doc',
|
||||
child: ListTile(
|
||||
leading: Icon(
|
||||
Icons.library_books,
|
||||
size: 22.0,
|
||||
),
|
||||
title: Text('查看文档'),
|
||||
),
|
||||
),
|
||||
const PopupMenuDivider(),
|
||||
const PopupMenuItem<String>(
|
||||
value: 'code',
|
||||
child: ListTile(
|
||||
leading: Icon(
|
||||
Icons.code,
|
||||
size: 22.0,
|
||||
),
|
||||
title: Text('查看Demo'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0),
|
||||
child: ListView(
|
||||
shrinkWrap: true,
|
||||
padding: const EdgeInsets.all(0.0),
|
||||
children: <Widget>[
|
||||
Column(
|
||||
children: _buildContent(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
bottomNavigationBar:
|
||||
(widget.bottomNaviBar is Widget) ? widget.bottomNaviBar : null);
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
/**
|
||||
* @author 一凨
|
||||
*/
|
||||
/// @author 一凨
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import '../common/style.dart';
|
||||
import '../common/widget_name_to_icon.dart';
|
||||
|
||||
import 'package:flutter_go/utils/style.dart';
|
||||
import 'package:flutter_go/resources/widget_name_to_icon.dart';
|
||||
|
||||
String _widgetName;
|
||||
|
||||
@ -13,9 +13,15 @@ class WidgetItem extends StatelessWidget {
|
||||
final int index; //用于计算border
|
||||
final int totalCount;
|
||||
final int rowLength;
|
||||
final String textSize;
|
||||
|
||||
WidgetItem(
|
||||
{this.title, this.onTap, this.index, this.totalCount, this.rowLength});
|
||||
{this.title,
|
||||
this.onTap,
|
||||
this.index,
|
||||
this.totalCount,
|
||||
this.rowLength,
|
||||
this.textSize});
|
||||
|
||||
Border _buildBorder(context) {
|
||||
Border _border;
|
||||
@ -64,6 +70,9 @@ class WidgetItem extends StatelessWidget {
|
||||
Icons.crop,
|
||||
);
|
||||
}
|
||||
final textStyle = (textSize == 'middle')
|
||||
? TextStyle(fontSize: 13.8, fontFamily: 'MediumItalic')
|
||||
: TextStyle(fontSize: 16.0);
|
||||
return InkWell(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
@ -80,7 +89,7 @@ class WidgetItem extends StatelessWidget {
|
||||
SizedBox(
|
||||
height: 8.0,
|
||||
),
|
||||
Text(_widgetName),
|
||||
Text(_widgetName, style: textStyle),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluro/fluro.dart';
|
||||
import './widget_item.dart';
|
||||
import '../routers/application.dart';
|
||||
import '../widgets/index.dart';
|
||||
@ -7,6 +8,7 @@ class WidgetItemContainer extends StatelessWidget {
|
||||
final int columnCount; //一行几个
|
||||
final List<dynamic> categories;
|
||||
final bool isWidgetPoint;
|
||||
|
||||
// 所有的可用demos;
|
||||
final List widgetDemosList = new WidgetDemoList().getDemos();
|
||||
|
||||
@ -41,15 +43,16 @@ class WidgetItemContainer extends StatelessWidget {
|
||||
targetRouter = item.routerName;
|
||||
}
|
||||
});
|
||||
Application.router.navigateTo(context, "$targetRouter");
|
||||
Application.router.navigateTo(context, "$targetRouter", transition: TransitionType.inFromRight);
|
||||
} else {
|
||||
Application.router
|
||||
.navigateTo(context, "/category/${item.name}");
|
||||
.navigateTo(context, "/category/${item.name}", transition: TransitionType.inFromRight);
|
||||
}
|
||||
},
|
||||
index: addI,
|
||||
totalCount: length,
|
||||
rowLength: columnCount,
|
||||
textSize: isWidgetPoint ? 'middle' : 'small',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
5
lib/event/event_bus.dart
Normal file
@ -0,0 +1,5 @@
|
||||
import 'package:event_bus/event_bus.dart';
|
||||
|
||||
class ApplicationEvent{
|
||||
static EventBus event;
|
||||
}
|
7
lib/event/event_model.dart
Normal file
@ -0,0 +1,7 @@
|
||||
class CollectionEvent{
|
||||
final String widgetName;
|
||||
final String router;
|
||||
final bool isRemove;
|
||||
// token uid...
|
||||
CollectionEvent(this.widgetName,this.router,this.isRemove);
|
||||
}
|
180
lib/main.dart
@ -1,27 +1,37 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluro/fluro.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
|
||||
import 'views/first_page.dart';
|
||||
import 'views/widget_page.dart';
|
||||
import 'views/fourth_page.dart';
|
||||
import 'views/collection_page.dart';
|
||||
import 'routers/routers.dart';
|
||||
import 'routers/application.dart';
|
||||
import 'common/provider.dart';
|
||||
import 'model/widget.dart';
|
||||
import './widgets/index.dart';
|
||||
import 'package:flutter_go/components/search_input.dart';
|
||||
|
||||
import 'package:flutter_go/utils/provider.dart';
|
||||
import 'package:flutter_go/utils/shared_preferences.dart';
|
||||
import 'package:flutter_go/views/first_page/home.dart';
|
||||
import 'package:flutter_go/model/search_history.dart';
|
||||
//import 'views/welcome_page/index.dart';
|
||||
|
||||
const int ThemeColor = 0xFFC91B3A;
|
||||
SpUtil sp;
|
||||
var db;
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
MyApp() {
|
||||
MyApp() {
|
||||
final router = new Router();
|
||||
|
||||
Routes.configureRoutes(router);
|
||||
|
||||
Application.router = router;
|
||||
}
|
||||
|
||||
showWelcomePage() {
|
||||
// 暂时关掉欢迎介绍
|
||||
return AppPage();
|
||||
// bool showWelcome = sp.getBool(SharedPreferencesKeys.showWelcome);
|
||||
// if (showWelcome == null || showWelcome == true) {
|
||||
// return WelcomePage();
|
||||
// } else {
|
||||
// return AppPage();
|
||||
// }
|
||||
}
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new MaterialApp(
|
||||
@ -39,158 +49,20 @@ class MyApp extends StatelessWidget {
|
||||
size: 35.0,
|
||||
),
|
||||
),
|
||||
home: new MyHomePage(),
|
||||
home: new Scaffold(
|
||||
body: showWelcomePage()
|
||||
),
|
||||
onGenerateRoute: Application.router.generator,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
var db;
|
||||
|
||||
void main() async {
|
||||
final provider = new Provider();
|
||||
await provider.init(true);
|
||||
sp = await SpUtil.getInstance();
|
||||
new SearchHistoryList(sp);
|
||||
db = Provider.db;
|
||||
runApp(new MyApp());
|
||||
}
|
||||
|
||||
class MyHomePage extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return _MyHomePageState();
|
||||
}
|
||||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage>
|
||||
with SingleTickerProviderStateMixin {
|
||||
WidgetControlModel widgetControl = new WidgetControlModel();
|
||||
TabController controller;
|
||||
bool isSearch = false;
|
||||
String data = '无';
|
||||
String data2ThirdPage = '这是传给ThirdPage的值';
|
||||
String appBarTitle = tabData[0]['text'];
|
||||
static List tabData = [
|
||||
{'text': '业界动态', 'icon': new Icon(Icons.language)},
|
||||
{'text': 'WIDGET', 'icon': new Icon(Icons.extension)},
|
||||
{'text': '组件收藏', 'icon': new Icon(Icons.star)},
|
||||
{'text': '关于手册', 'icon': new Icon(Icons.favorite)}
|
||||
];
|
||||
|
||||
List<Widget> myTabs = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
controller = new TabController(
|
||||
initialIndex: 0, vsync: this, length: 4); // 这里的length 决定有多少个底导 submenus
|
||||
for (int i = 0; i < tabData.length; i++) {
|
||||
myTabs.add(new Tab(text: tabData[i]['text'], icon: tabData[i]['icon']));
|
||||
}
|
||||
controller.addListener(() {
|
||||
if (controller.indexIsChanging) {
|
||||
_onTabChange();
|
||||
}
|
||||
});
|
||||
Application.controller = controller;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void onWidgetTap(WidgetPoint widgetPoint, BuildContext context) {
|
||||
List widgetDemosList = new WidgetDemoList().getDemos();
|
||||
String targetName = widgetPoint.name;
|
||||
String targetRouter = '/category/error/404';
|
||||
widgetDemosList.forEach((item) {
|
||||
if (item.name == targetName) {
|
||||
targetRouter = item.routerName;
|
||||
}
|
||||
});
|
||||
Application.router.navigateTo(context, "$targetRouter");
|
||||
}
|
||||
|
||||
Widget buildSearchInput(BuildContext context) {
|
||||
return new SearchInput((value) async {
|
||||
if (value != '') {
|
||||
List<WidgetPoint> list = await widgetControl.search(value);
|
||||
|
||||
return list
|
||||
.map((item) => new MaterialSearchResult<String>(
|
||||
value: item.name,
|
||||
text: item.name,
|
||||
onTap: () {
|
||||
onWidgetTap(item, context);
|
||||
},
|
||||
))
|
||||
.toList();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}, (value) {}, () {});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new Scaffold(
|
||||
appBar: new AppBar(title: buildSearchInput(context)),
|
||||
body: new TabBarView(controller: controller, children: <Widget>[
|
||||
new FirstPage(),
|
||||
new WidgetPage(db),
|
||||
new CollectionPage(),
|
||||
new FourthPage()
|
||||
]),
|
||||
bottomNavigationBar: Material(
|
||||
color: const Color(0xFFF0EEEF), //底部导航栏主题颜色
|
||||
child: SafeArea(
|
||||
child: Container(
|
||||
height: 65.0,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF0F0F0),
|
||||
boxShadow: <BoxShadow>[
|
||||
BoxShadow(
|
||||
color: const Color(0xFFd0d0d0),
|
||||
blurRadius: 3.0,
|
||||
spreadRadius: 2.0,
|
||||
offset: Offset(-1.0, -1.0),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: TabBar(
|
||||
controller: controller,
|
||||
indicatorColor: Theme.of(context).primaryColor, //tab标签的下划线颜色
|
||||
// labelColor: const Color(0xFF000000),
|
||||
indicatorWeight: 3.0,
|
||||
labelColor: Theme.of(context).primaryColor,
|
||||
unselectedLabelColor: const Color(0xFF8E8E8E),
|
||||
tabs: <Tab>[
|
||||
Tab(text: '业界动态', icon: Icon(Icons.language)),
|
||||
Tab(text: '组件', icon: Icon(Icons.extension)),
|
||||
Tab(text: '组件收藏', icon: Icon(Icons.favorite)),
|
||||
Tab(text: '关于手册', icon: Icon(Icons.line_weight)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _onTabChange() {
|
||||
if (this.mounted) {
|
||||
this.setState(() {
|
||||
appBarTitle = tabData[controller.index]['text'];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// void _onDataChange(val) {
|
||||
// if (this.mounted) {
|
||||
// setState(() {
|
||||
// data = val;
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
|
||||
|
||||
class BaseModel{
|
||||
Database db;
|
||||
final String table = '';
|
||||
|
@ -1,6 +1,7 @@
|
||||
|
||||
import 'dart:async';
|
||||
import '../common/sql.dart';
|
||||
|
||||
import 'package:flutter_go/utils/sql.dart';
|
||||
|
||||
abstract class CatInterface{
|
||||
int get id;
|
||||
|
@ -1,11 +1,11 @@
|
||||
/*
|
||||
* @Author: 一凨
|
||||
* @Date: 2019-01-07 16:24:42
|
||||
* @Last Modified by: 一凨
|
||||
* @Last Modified time: 2019-01-08 17:37:42
|
||||
*/
|
||||
/// @Author: 一凨
|
||||
/// @Date: 2019-01-07 16:24:42
|
||||
/// @Last Modified by: 一凨
|
||||
/// @Last Modified time: 2019-01-08 17:37:42
|
||||
|
||||
import 'dart:async';
|
||||
import '../common/sql.dart';
|
||||
|
||||
import 'package:flutter_go/utils/sql.dart';
|
||||
|
||||
abstract class CollectionInterface {
|
||||
String get name;
|
||||
|
101
lib/model/search_history.dart
Normal file
@ -0,0 +1,101 @@
|
||||
///
|
||||
/// Created with Android Studio.
|
||||
/// User: 三帆
|
||||
/// Date: 18/02/2019
|
||||
/// Time: 14:19
|
||||
/// email: sanfan.hx@alibaba-inc.com
|
||||
/// target: 搜索WidgetDemo中的历史记录model
|
||||
///
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_go/utils/shared_preferences.dart';
|
||||
|
||||
|
||||
class SearchHistory {
|
||||
final String name;
|
||||
final String targetRouter;
|
||||
|
||||
SearchHistory({@required this.name, @required this.targetRouter});
|
||||
}
|
||||
|
||||
class SearchHistoryList {
|
||||
static SpUtil _sp;
|
||||
static SearchHistoryList _instance;
|
||||
static List<SearchHistory> _searchHistoryList = [];
|
||||
|
||||
static SearchHistoryList _getInstance(SpUtil sp) {
|
||||
if (_instance == null) {
|
||||
_sp = sp;
|
||||
String json = sp.get(SharedPreferencesKeys.searchHistory);
|
||||
_instance = new SearchHistoryList.fromJSON(json);
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
||||
factory SearchHistoryList([SpUtil sp]) {
|
||||
if (sp == null && _instance == null) {
|
||||
print(new ArgumentError(
|
||||
['SearchHistoryList need instantiatied SpUtil at first timte ']));
|
||||
}
|
||||
return _getInstance(sp);
|
||||
}
|
||||
|
||||
// List<SearchHistory> _searchHistoryList = [];
|
||||
|
||||
// 存放的最大数量
|
||||
int _count = 10;
|
||||
|
||||
SearchHistoryList.fromJSON(String jsonData) {
|
||||
_searchHistoryList = [];
|
||||
if (jsonData == null) {
|
||||
return;
|
||||
}
|
||||
List jsonList = json.decode(jsonData);
|
||||
jsonList.forEach((value) {
|
||||
_searchHistoryList.add(SearchHistory(
|
||||
name: value['name'], targetRouter: value['targetRouter']));
|
||||
});
|
||||
}
|
||||
|
||||
List<SearchHistory> getList() {
|
||||
return _searchHistoryList;
|
||||
}
|
||||
|
||||
clear() {
|
||||
_sp.remove(SharedPreferencesKeys.searchHistory);
|
||||
_searchHistoryList = [];
|
||||
}
|
||||
|
||||
save() {
|
||||
_sp.putString(SharedPreferencesKeys.searchHistory, this.toJson());
|
||||
}
|
||||
|
||||
add(SearchHistory item) {
|
||||
print("_searchHistoryList> ${_searchHistoryList.length}");
|
||||
for (SearchHistory value in _searchHistoryList) {
|
||||
if (value.name == item.name) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (_searchHistoryList.length > _count) {
|
||||
_searchHistoryList.removeAt(0);
|
||||
}
|
||||
_searchHistoryList.add(item);
|
||||
save();
|
||||
}
|
||||
|
||||
toJson() {
|
||||
List<Map<String, String>> jsonList = [];
|
||||
_searchHistoryList.forEach((SearchHistory value) {
|
||||
jsonList.add({'name': value.name, 'targetRouter': value.targetRouter});
|
||||
});
|
||||
return json.encode(jsonList);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return this.toJson();
|
||||
}
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
|
||||
import 'dart:async';
|
||||
import '../common/sql.dart';
|
||||
|
||||
import "package:flutter/material.dart";
|
||||
|
||||
import 'package:flutter_go/utils/sql.dart';
|
||||
|
||||
abstract class WidgetInterface {
|
||||
int get id;
|
||||
|
||||
|
17
lib/resources/icon_names.dart
Normal file
38
lib/resources/shared_preferences_keys.dart
Normal file
@ -0,0 +1,38 @@
|
||||
|
||||
// Created with Android Studio.
|
||||
// User: 三帆
|
||||
// Date: 31/01/2019
|
||||
// Time: 18:13
|
||||
// email: sanfan.hx@alibaba-inc.com
|
||||
// target: xxx
|
||||
//
|
||||
|
||||
|
||||
//enum DateType {
|
||||
// Int,
|
||||
// Double,
|
||||
// Bool,
|
||||
// String,
|
||||
// Dynamic
|
||||
//}
|
||||
|
||||
//class spKey {
|
||||
// String name;
|
||||
// DateType type;
|
||||
//
|
||||
// spKey({this.name, this.type});
|
||||
//}
|
||||
|
||||
class SharedPreferencesKeys {
|
||||
/// boolean
|
||||
/// 用于欢迎页面. 只有第一次访问才会显示. 或者手动将这个值设为false
|
||||
static String showWelcome = 'loginWelcone';
|
||||
/// json
|
||||
/// 用于存放搜索页的搜索数据.
|
||||
/// [{
|
||||
/// name: 'name'
|
||||
///
|
||||
/// }]
|
||||
static String searchHistory = 'searchHistory';
|
||||
}
|
||||
|
171
lib/resources/widget_name_to_icon.dart
Normal file
@ -0,0 +1,171 @@
|
||||
import 'package:flutter/material.dart';
|
||||
class WidgetName2Icon {
|
||||
static Map<String,dynamic> icons = {
|
||||
"Element":Icons.explicit,
|
||||
"Components":Icons.extension,
|
||||
"Themes":Icons.filter_b_and_w,
|
||||
"Form":Icons.table_chart,
|
||||
"Frame":Icons.aspect_ratio,
|
||||
"Media":Icons.subscriptions,
|
||||
"Input":Icons.input,
|
||||
"TextField":Icons.text_fields,
|
||||
"Checkbox":Icons.check_box,
|
||||
"CheckboxListTile":Icons.playlist_add_check,
|
||||
"Button":Icons.aspect_ratio,
|
||||
"FlatButton":Icons.outlined_flag,
|
||||
"RaisedButton":Icons.picture_in_picture_alt,
|
||||
"IconButton":Icons.import_contacts,
|
||||
"PopupMenuButton":Icons.power_input,
|
||||
"FloatingActionButton":Icons.flash_off,
|
||||
"RawMaterialButton":Icons.rowing,
|
||||
"DropdownButton":Icons.drag_handle,
|
||||
"OutlineButton":Icons.done_outline,
|
||||
"Text":Icons.text_format,
|
||||
"RichText":Icons.text_rotation_angleup,
|
||||
"Radio":Icons.radio_button_checked,
|
||||
"RadioListTile":Icons.list,
|
||||
"Slider":Icons.slideshow,
|
||||
"SliderTheme":Icons.theaters,
|
||||
"SliderComponentShape":Icons.format_shapes,
|
||||
"SliderThemeData":Icons.data_usage,
|
||||
"Switch":Icons.switch_camera,
|
||||
"SwitchListTile":Icons.switch_video,
|
||||
"AnimatedSwitcher":Icons.airplanemode_active,
|
||||
"Align":Icons.format_align_left,
|
||||
"Stack":Icons.storage,
|
||||
"IndexedStack":Icons.star,
|
||||
"Layout":Icons.layers,
|
||||
"Row":Icons.recent_actors,
|
||||
"Column":Icons.cloud_off,
|
||||
"Container":Icons.edit_location,
|
||||
"Center":Icons.gesture,
|
||||
"Box":Icons.hdr_strong,
|
||||
"ConstrainedBox":Icons.account_box,
|
||||
"OverflowBox":Icons.email,
|
||||
"DecoratedBox":Icons.settings_overscan,
|
||||
"FittedBox":Icons.data_usage,
|
||||
"LimitedBox":Icons.format_align_justify,
|
||||
"RenderBox":Icons.error,
|
||||
"RotateBox":Icons.navigate_next,
|
||||
"SizedOverflowBox":Icons.undo,
|
||||
"TextBox":Icons.wallpaper,
|
||||
"UnconstrainedBox":Icons.account_box,
|
||||
"Axis":Icons.access_alarm,
|
||||
"MainAxis":Icons.add_circle,
|
||||
"CrossAxis":Icons.dehaze,
|
||||
"FlipAxis":Icons.zoom_out,
|
||||
"Expanded":Icons.all_out,
|
||||
"Spacing":Icons.crop_free,
|
||||
"Padding":Icons.crop,
|
||||
"SliverPadding":Icons.euro_symbol,
|
||||
"AnimatedPadding":Icons.zoom_out_map,
|
||||
"Table":Icons.table_chart,
|
||||
"Image":Icons.image,
|
||||
"AssetImage":Icons.image_aspect_ratio,
|
||||
"DecorationImage":Icons.picture_in_picture,
|
||||
"DecorationImagePainter":Icons.image,
|
||||
"ExactAssetImage":Icons.assessment,
|
||||
"FadeInImage":Icons.flip,
|
||||
"FileImage":Icons.filter,
|
||||
"NetworkImage":Icons.network_wifi,
|
||||
"RawImage":Icons.text_rotation_down,
|
||||
"PaintImage":Icons.format_paint,
|
||||
"PrecacheImage":Icons.perm_camera_mic,
|
||||
"MemoryImage":Icons.memory,
|
||||
"Icon":Icons.event_available,
|
||||
"ImageIcon":Icons.image,
|
||||
"IconTheme":Icons.table_chart,
|
||||
"IconData":Icons.date_range,
|
||||
"IconThemeData":Icons.insert_comment,
|
||||
"Canvas":Icons.edit,
|
||||
"PainterPath":Icons.gesture,
|
||||
"CircleProgressBarPainter":Icons.av_timer,
|
||||
"PainterSketch":Icons.touch_app,
|
||||
"Material":Icons.android,
|
||||
"MaterialApp":Icons.android,
|
||||
"MaterialButton":Icons.speaker,
|
||||
"MaterialGap":Icons.view_week,
|
||||
"MaterialSlice":Icons.format_list_numbered_rtl ,
|
||||
"MaterialColor":Icons.color_lens,
|
||||
"Cupertino":Icons.phone_iphone,
|
||||
"Scroll":Icons.swap_vertical_circle,
|
||||
"Tab":Icons.tab,
|
||||
"Menu":Icons.menu,
|
||||
"PopupMenuDivider":Icons.remove,
|
||||
"PopupMenuEntry":Icons.menu,
|
||||
"CheckedPopupMenuItem":Icons.playlist_add_check,
|
||||
"DropdownMenuItem":Icons.playlist_play,
|
||||
"Grid":Icons.grid_on,
|
||||
"Scaffold":Icons.local_convenience_store,
|
||||
"Dialog":Icons.add_alert,
|
||||
"Bar":Icons.border_horizontal,
|
||||
"Card":Icons.credit_card,
|
||||
"Panel":Icons.video_label,
|
||||
"Navigation":Icons.navigation,
|
||||
"List":Icons.list,
|
||||
"ScrollView":Icons.move_to_inbox,
|
||||
"Scrollable":Icons.swap_vertical_circle,
|
||||
"ScrollbarPainter":Icons.format_paint,
|
||||
"ScrollMetrics":Icons.camera,
|
||||
"ScrollPhysics":Icons.control_point_duplicate,
|
||||
"BoxScrollView":Icons.inbox,
|
||||
"Chip":Icons.sim_card,
|
||||
"ChipTheme":Icons.sd_card,
|
||||
"CustomScrollView":Icons.autorenew,
|
||||
"NestedScrollView":Icons.panorama_fish_eye,
|
||||
"ChipThemeData":Icons.sim_card_alert,
|
||||
"ChoiceChip":Icons.insert_drive_file,
|
||||
"FilterChip":Icons.note_add,
|
||||
"InputChip":Icons.restore_page,
|
||||
"RawChip":Icons.save,
|
||||
"LinearProgressIndicator":Icons.trending_flat ,
|
||||
"CircularProgressIndicator":Icons.rotate_left ,
|
||||
"ExpansionPanel":Icons.view_stream,
|
||||
"ExpansionPanelList":Icons.view_headline,
|
||||
"BottomNavigationBar":Icons.call_to_action,
|
||||
"ListView":Icons.view_list ,
|
||||
"ListBody":Icons.list ,
|
||||
"AnimatedList":Icons.format_line_spacing ,
|
||||
"SliverAppBar":Icons.content_paste,
|
||||
"AppBar":Icons.card_membership,
|
||||
"BottomAppBar":Icons.call_to_action,
|
||||
"BottomNavigationBarItem":Icons.crop_original,
|
||||
"FlexibleSpaceBar":Icons.aspect_ratio,
|
||||
"ButtonBar":Icons.branding_watermark,
|
||||
"SnackBar":Icons.sms_failed,
|
||||
"Progress":Icons.sync,
|
||||
"Pick":Icons.event_note,
|
||||
"DayPicker":Icons.calendar_today,
|
||||
"MonthPicker":Icons.date_range,
|
||||
"YearPicker":Icons.event_busy,
|
||||
"ShowdatePicker":Icons.event,
|
||||
"MaterialPageRoute":Icons.album,
|
||||
"MaterialAccentColor":Icons.brush,
|
||||
"SnackBarAction":Icons.assessment,
|
||||
"TabBar":Icons.burst_mode,
|
||||
"AlertDialog":Icons.sms_failed,
|
||||
"AboutDialog":Icons.sms,
|
||||
"SimpleDialog":Icons.message,
|
||||
"ScaffoldState":Icons.local_bar,
|
||||
"GridTile":Icons.apps,
|
||||
"MergeableMaterialItem":Icons.view_list,
|
||||
"CupertinoApp":Icons.face,
|
||||
"CupertinoButton":Icons.crop_7_5,
|
||||
"CupertinoColors":Icons.color_lens,
|
||||
"CupertinoIcons":Icons.insert_emoticon,
|
||||
"CupertinoNavigationBar":Icons.payment,
|
||||
"CupertinoPageRoute":Icons.router,
|
||||
"CupertinoPageScaffold":Icons.pages,
|
||||
"CupertinoPicker":Icons.add_alarm,
|
||||
"CupertinoPopupSurface":Icons.center_focus_weak,
|
||||
"CupertinoScrollbar": Icons.fullscreen,
|
||||
"CupertinoSlider": Icons.switch_camera,
|
||||
"CupertinoSegmentedControl": Icons.business_center,
|
||||
"CupertinoSliverNavigationBar": Icons.subtitles,
|
||||
"CupertinoSwitch": Icons.radio_button_checked,
|
||||
"CupertinoTabBar": Icons.tab,
|
||||
"CupertinoTabScaffold": Icons.crop_original,
|
||||
"CupertinoTabView": Icons.tablet,
|
||||
"CupertinoTimerPicker": Icons.timer
|
||||
};
|
||||
}
|
@ -1,10 +1,15 @@
|
||||
import 'package:fluro/fluro.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluro/fluro.dart';
|
||||
|
||||
import 'package:flutter_go/utils/shared_preferences.dart';
|
||||
|
||||
class Application {
|
||||
static Router router;
|
||||
static TabController controller;
|
||||
static SpUtil sharePeferences;
|
||||
|
||||
static Map<String, String> github = {
|
||||
'widgetsURL':'https://github.com/alibaba-paimai-frontend/flutter-common-widgets-app/tree/develop/lib/widgets/',
|
||||
'widgetsURL':'https://github.com/alibaba/flutter-go/blob/develop/lib/widgets/',
|
||||
//'develop':'https://github.com/alibaba-paimai-frontend/flutter-common-widgets-app/tree/develop/lib/widgets/',
|
||||
//'master':'https://github.com/alibaba-paimai-frontend/flutter-common-widgets-app/tree/master/lib/widgets/'
|
||||
};
|
||||
|
@ -1,9 +1,18 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluro/fluro.dart';
|
||||
import '../views/category.dart';
|
||||
|
||||
import 'package:flutter_go/components/category.dart';
|
||||
import '../widgets/404.dart';
|
||||
import '../common/full_screen_code_dialog.dart';
|
||||
import '../views/web_view_page.dart';
|
||||
import 'package:flutter_go/components/full_screen_code_dialog.dart';
|
||||
import 'package:flutter_go/views/web_page/web_view_page.dart';
|
||||
import 'package:flutter_go/views/first_page/home.dart';
|
||||
|
||||
// app的首页
|
||||
var homeHandler = new Handler(
|
||||
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||
return new AppPage();
|
||||
},
|
||||
);
|
||||
|
||||
var categoryHandler = new Handler(
|
||||
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||
|
@ -1,11 +1,13 @@
|
||||
|
||||
import 'package:fluro/fluro.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../widgets/index.dart';
|
||||
import './router_handler.dart';
|
||||
|
||||
class Routes {
|
||||
static String root = "/";
|
||||
static String home = "/home";
|
||||
static String widgetDemo = '/widget-demo';
|
||||
static String codeView = '/code-view';
|
||||
static String webViewPage = '/web-view-page';
|
||||
@ -15,16 +17,16 @@ class Routes {
|
||||
router.notFoundHandler = new Handler(
|
||||
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||
});
|
||||
|
||||
router.define(home, handler: homeHandler);
|
||||
|
||||
router.define('/category/:type', handler: categoryHandler);
|
||||
router.define('/category/error/404', handler: widgetNotFoundHandler);
|
||||
router.define(codeView,handler:fullScreenCodeDialog);
|
||||
router.define(webViewPage,handler:webViewPageHand);
|
||||
widgetDemosList.forEach((demo) {
|
||||
Handler handler = new Handler(
|
||||
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||
return demo.buildRouter(context);
|
||||
widgetDemosList.forEach((demo) {
|
||||
Handler handler = new Handler(
|
||||
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||
return demo.buildRouter(context);
|
||||
});
|
||||
router.define('${demo.routerName}', handler: handler);
|
||||
});
|
||||
|
40
lib/utils/example_code_parser.dart
Normal file
@ -0,0 +1,40 @@
|
||||
/// @Author: 一凨
|
||||
/// @Date: 2019-01-14 11:42:36
|
||||
/// @Last Modified by: 一凨
|
||||
/// @Last Modified time: 2019-01-14 16:53:11
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_go/routers/application.dart';
|
||||
|
||||
|
||||
Map<String, String> _exampleCode;
|
||||
String _code;
|
||||
|
||||
void _launchURL(String url) async {
|
||||
if (await canLaunch(url)) {
|
||||
await launch(url);
|
||||
} else {
|
||||
throw 'Could not launch $url';
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> getExampleCode(context,String filePath, AssetBundle bundle) async {
|
||||
if (_exampleCode == null) await _parseExampleCode(context,filePath, bundle);
|
||||
return _code;
|
||||
}
|
||||
|
||||
Future<void> _parseExampleCode(context,String filePath, AssetBundle bundle) async {
|
||||
String code;
|
||||
try {
|
||||
code = await bundle.loadString('lib/widgets/$filePath');
|
||||
} catch (err) {
|
||||
Navigator.of(context).pop();
|
||||
_launchURL(Application.github['widgetsURL'] + filePath);
|
||||
}
|
||||
_code = code;
|
||||
}
|
359
lib/utils/high_light_code.dart
Normal file
@ -0,0 +1,359 @@
|
||||
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:string_scanner/string_scanner.dart';
|
||||
|
||||
/// final SyntaxHighlighterStyle style = SyntaxHighlighterStyle.lightThemeStyle();
|
||||
/// DartSyntaxHighlighter(style).format(source)
|
||||
|
||||
class SyntaxHighlighterStyle {
|
||||
SyntaxHighlighterStyle({
|
||||
this.baseStyle,
|
||||
this.numberStyle,
|
||||
this.commentStyle,
|
||||
this.keywordStyle,
|
||||
this.stringStyle,
|
||||
this.punctuationStyle,
|
||||
this.classStyle,
|
||||
this.constantStyle
|
||||
});
|
||||
|
||||
static SyntaxHighlighterStyle lightThemeStyle() {
|
||||
return SyntaxHighlighterStyle(
|
||||
baseStyle: const TextStyle(color: Color(0xFF000000)),
|
||||
numberStyle: const TextStyle(color: Color(0xFF1565C0)),
|
||||
commentStyle: const TextStyle(color: Color(0xFF9E9E9E)),
|
||||
keywordStyle: const TextStyle(color: Color(0xFF9C27B0)),
|
||||
stringStyle: const TextStyle(color: Color(0xFF43A047)),
|
||||
punctuationStyle: const TextStyle(color: Color(0xFF000000)),
|
||||
classStyle: const TextStyle(color: Color(0xFF512DA8)),
|
||||
constantStyle: const TextStyle(color: Color(0xFF795548))
|
||||
);
|
||||
}
|
||||
|
||||
static SyntaxHighlighterStyle darkThemeStyle() {
|
||||
return SyntaxHighlighterStyle(
|
||||
baseStyle: const TextStyle(color: Color(0xFFFFFFFF)),
|
||||
numberStyle: const TextStyle(color: Color(0xFF1565C0)),
|
||||
commentStyle: const TextStyle(color: Color(0xFF9E9E9E)),
|
||||
keywordStyle: const TextStyle(color: Color(0xFF80CBC4)),
|
||||
stringStyle: const TextStyle(color: Color(0xFF009688)),
|
||||
punctuationStyle: const TextStyle(color: Color(0xFFFFFFFF)),
|
||||
classStyle: const TextStyle(color: Color(0xFF009688)),
|
||||
constantStyle: const TextStyle(color: Color(0xFF795548))
|
||||
);
|
||||
}
|
||||
|
||||
final TextStyle baseStyle;
|
||||
final TextStyle numberStyle;
|
||||
final TextStyle commentStyle;
|
||||
final TextStyle keywordStyle;
|
||||
final TextStyle stringStyle;
|
||||
final TextStyle punctuationStyle;
|
||||
final TextStyle classStyle;
|
||||
final TextStyle constantStyle;
|
||||
}
|
||||
|
||||
abstract class Highlighter { // ignore: one_member_abstracts
|
||||
TextSpan format(String src);
|
||||
}
|
||||
|
||||
class DartSyntaxHighlighter extends Highlighter {
|
||||
DartSyntaxHighlighter([this._style]) {
|
||||
_spans = <_HighlightSpan>[];
|
||||
_style ??= SyntaxHighlighterStyle.darkThemeStyle();
|
||||
}
|
||||
|
||||
SyntaxHighlighterStyle _style;
|
||||
|
||||
static const List<String> _keywords = <String>[
|
||||
'abstract', 'as', 'assert', 'async', 'await', 'break', 'case', 'catch',
|
||||
'class', 'const', 'continue', 'default', 'deferred', 'do', 'dynamic', 'else',
|
||||
'enum', 'export', 'external', 'extends', 'factory', 'false', 'final',
|
||||
'finally', 'for', 'get', 'if', 'implements', 'import', 'in', 'is', 'library',
|
||||
'new', 'null', 'operator', 'part', 'rethrow', 'return', 'set', 'static',
|
||||
'super', 'switch', 'sync', 'this', 'throw', 'true', 'try', 'typedef', 'var',
|
||||
'void', 'while', 'with', 'yield'
|
||||
];
|
||||
|
||||
static const List<String> _builtInTypes = <String>[
|
||||
'int', 'double', 'num', 'bool'
|
||||
];
|
||||
|
||||
String _src;
|
||||
StringScanner _scanner;
|
||||
|
||||
List<_HighlightSpan> _spans;
|
||||
|
||||
@override
|
||||
TextSpan format(String src) {
|
||||
_src = src;
|
||||
_scanner = StringScanner(_src);
|
||||
|
||||
if (_generateSpans()) {
|
||||
// Successfully parsed the code
|
||||
final List<TextSpan> formattedText = <TextSpan>[];
|
||||
int currentPosition = 0;
|
||||
|
||||
for (_HighlightSpan span in _spans) {
|
||||
if (currentPosition != span.start)
|
||||
formattedText.add(TextSpan(text: _src.substring(currentPosition, span.start)));
|
||||
|
||||
formattedText.add(TextSpan(style: span.textStyle(_style), text: span.textForSpan(_src)));
|
||||
|
||||
currentPosition = span.end;
|
||||
}
|
||||
|
||||
if (currentPosition != _src.length)
|
||||
formattedText.add(TextSpan(text: _src.substring(currentPosition, _src.length)));
|
||||
|
||||
return TextSpan(style: _style.baseStyle, children: formattedText);
|
||||
} else {
|
||||
// Parsing failed, return with only basic formatting
|
||||
return TextSpan(style: _style.baseStyle, text: src);
|
||||
}
|
||||
}
|
||||
|
||||
bool _generateSpans() {
|
||||
int lastLoopPosition = _scanner.position;
|
||||
|
||||
while (!_scanner.isDone) {
|
||||
// Skip White space
|
||||
_scanner.scan(RegExp(r'\s+'));
|
||||
|
||||
// Block comments
|
||||
if (_scanner.scan(RegExp(r'/\*(.|\n)*\*/'))) {
|
||||
_spans.add(_HighlightSpan(
|
||||
_HighlightType.comment,
|
||||
_scanner.lastMatch.start,
|
||||
_scanner.lastMatch.end
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Line comments
|
||||
if (_scanner.scan('//')) {
|
||||
final int startComment = _scanner.lastMatch.start;
|
||||
|
||||
bool eof = false;
|
||||
int endComment;
|
||||
if (_scanner.scan(RegExp(r'.*\n'))) {
|
||||
endComment = _scanner.lastMatch.end - 1;
|
||||
} else {
|
||||
eof = true;
|
||||
endComment = _src.length;
|
||||
}
|
||||
|
||||
_spans.add(_HighlightSpan(
|
||||
_HighlightType.comment,
|
||||
startComment,
|
||||
endComment
|
||||
));
|
||||
|
||||
if (eof)
|
||||
break;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Raw r"String"
|
||||
if (_scanner.scan(RegExp(r'r".*"'))) {
|
||||
_spans.add(_HighlightSpan(
|
||||
_HighlightType.string,
|
||||
_scanner.lastMatch.start,
|
||||
_scanner.lastMatch.end
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Raw r'String'
|
||||
if (_scanner.scan(RegExp(r"r'.*'"))) {
|
||||
_spans.add(_HighlightSpan(
|
||||
_HighlightType.string,
|
||||
_scanner.lastMatch.start,
|
||||
_scanner.lastMatch.end
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Multiline """String"""
|
||||
if (_scanner.scan(RegExp(r'"""(?:[^"\\]|\\(.|\n))*"""'))) {
|
||||
_spans.add(_HighlightSpan(
|
||||
_HighlightType.string,
|
||||
_scanner.lastMatch.start,
|
||||
_scanner.lastMatch.end
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Multiline '''String'''
|
||||
if (_scanner.scan(RegExp(r"'''(?:[^'\\]|\\(.|\n))*'''"))) {
|
||||
_spans.add(_HighlightSpan(
|
||||
_HighlightType.string,
|
||||
_scanner.lastMatch.start,
|
||||
_scanner.lastMatch.end
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
// "String"
|
||||
if (_scanner.scan(RegExp(r'"(?:[^"\\]|\\.)*"'))) {
|
||||
_spans.add(_HighlightSpan(
|
||||
_HighlightType.string,
|
||||
_scanner.lastMatch.start,
|
||||
_scanner.lastMatch.end
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
// 'String'
|
||||
if (_scanner.scan(RegExp(r"'(?:[^'\\]|\\.)*'"))) {
|
||||
_spans.add(_HighlightSpan(
|
||||
_HighlightType.string,
|
||||
_scanner.lastMatch.start,
|
||||
_scanner.lastMatch.end
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Double
|
||||
if (_scanner.scan(RegExp(r'\d+\.\d+'))) {
|
||||
_spans.add(_HighlightSpan(
|
||||
_HighlightType.number,
|
||||
_scanner.lastMatch.start,
|
||||
_scanner.lastMatch.end
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Integer
|
||||
if (_scanner.scan(RegExp(r'\d+'))) {
|
||||
_spans.add(_HighlightSpan(
|
||||
_HighlightType.number,
|
||||
_scanner.lastMatch.start,
|
||||
_scanner.lastMatch.end)
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Punctuation
|
||||
if (_scanner.scan(RegExp(r'[\[\]{}().!=<>&\|\?\+\-\*/%\^~;:,]'))) {
|
||||
_spans.add(_HighlightSpan(
|
||||
_HighlightType.punctuation,
|
||||
_scanner.lastMatch.start,
|
||||
_scanner.lastMatch.end
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Meta data
|
||||
if (_scanner.scan(RegExp(r'@\w+'))) {
|
||||
_spans.add(_HighlightSpan(
|
||||
_HighlightType.keyword,
|
||||
_scanner.lastMatch.start,
|
||||
_scanner.lastMatch.end
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Words
|
||||
if (_scanner.scan(RegExp(r'\w+'))) {
|
||||
_HighlightType type;
|
||||
|
||||
String word = _scanner.lastMatch[0];
|
||||
if (word.startsWith('_'))
|
||||
word = word.substring(1);
|
||||
|
||||
if (_keywords.contains(word))
|
||||
type = _HighlightType.keyword;
|
||||
else if (_builtInTypes.contains(word))
|
||||
type = _HighlightType.keyword;
|
||||
else if (_firstLetterIsUpperCase(word))
|
||||
type = _HighlightType.klass;
|
||||
else if (word.length >= 2 && word.startsWith('k') && _firstLetterIsUpperCase(word.substring(1)))
|
||||
type = _HighlightType.constant;
|
||||
|
||||
if (type != null) {
|
||||
_spans.add(_HighlightSpan(
|
||||
type,
|
||||
_scanner.lastMatch.start,
|
||||
_scanner.lastMatch.end
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Check if this loop did anything
|
||||
if (lastLoopPosition == _scanner.position) {
|
||||
// Failed to parse this file, abort gracefully
|
||||
return false;
|
||||
}
|
||||
lastLoopPosition = _scanner.position;
|
||||
}
|
||||
|
||||
_simplify();
|
||||
return true;
|
||||
}
|
||||
|
||||
void _simplify() {
|
||||
for (int i = _spans.length - 2; i >= 0; i -= 1) {
|
||||
if (_spans[i].type == _spans[i + 1].type && _spans[i].end == _spans[i + 1].start) {
|
||||
_spans[i] = _HighlightSpan(
|
||||
_spans[i].type,
|
||||
_spans[i].start,
|
||||
_spans[i + 1].end
|
||||
);
|
||||
_spans.removeAt(i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool _firstLetterIsUpperCase(String str) {
|
||||
if (str.isNotEmpty) {
|
||||
final String first = str.substring(0, 1);
|
||||
return first == first.toUpperCase();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
enum _HighlightType {
|
||||
number,
|
||||
comment,
|
||||
keyword,
|
||||
string,
|
||||
punctuation,
|
||||
klass,
|
||||
constant
|
||||
}
|
||||
|
||||
class _HighlightSpan {
|
||||
_HighlightSpan(this.type, this.start, this.end);
|
||||
final _HighlightType type;
|
||||
final int start;
|
||||
final int end;
|
||||
|
||||
String textForSpan(String src) {
|
||||
return src.substring(start, end);
|
||||
}
|
||||
|
||||
TextStyle textStyle(SyntaxHighlighterStyle style) {
|
||||
if (type == _HighlightType.number)
|
||||
return style.numberStyle;
|
||||
else if (type == _HighlightType.comment)
|
||||
return style.commentStyle;
|
||||
else if (type == _HighlightType.keyword)
|
||||
return style.keywordStyle;
|
||||
else if (type == _HighlightType.string)
|
||||
return style.stringStyle;
|
||||
else if (type == _HighlightType.punctuation)
|
||||
return style.punctuationStyle;
|
||||
else if (type == _HighlightType.klass)
|
||||
return style.classStyle;
|
||||
else if (type == _HighlightType.constant)
|
||||
return style.constantStyle;
|
||||
else
|
||||
return style.baseStyle;
|
||||
}
|
||||
}
|
19
lib/utils/net_utils.dart
Normal file
@ -0,0 +1,19 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
|
||||
var dio = new Dio();
|
||||
|
||||
class NetUtils {
|
||||
|
||||
static Future get(String url,{Map<String,dynamic> params}) async{
|
||||
var response = await dio.get(url, data: params);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
static Future post(String url,Map<String,dynamic> params) async{
|
||||
var response = await dio.post(url, data: params);
|
||||
return response.data;
|
||||
}
|
||||
}
|
93
lib/utils/provider.dart
Normal file
@ -0,0 +1,93 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:path/path.dart';
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
import 'package:flutter/services.dart' show rootBundle;
|
||||
|
||||
//const createSql = {
|
||||
// 'cat': """
|
||||
// CREATE TABLE "cat" (
|
||||
// `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
||||
// `name` TEXT NOT NULL UNIQUE,
|
||||
// `depth` INTEGER NOT NULL DEFAULT 1,
|
||||
// `parentId` INTEGER NOT NULL,
|
||||
// `desc` TEXT
|
||||
// );
|
||||
// """,
|
||||
// 'collectio': """
|
||||
// CREATE TABLE collection (id INTEGER PRIMARY KEY NOT NULL UNIQUE, name TEXT NOT NULL, router TEXT);
|
||||
// """,
|
||||
// 'widget': """
|
||||
// CREATE TABLE widget (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, name TEXT NOT NULL, cnName TEXT NOT NULL, image TEXT NOT NULL, doc TEXT, demo TEXT, catId INTEGER NOT NULL REFERENCES cat (id), owner TEXT);
|
||||
// """;
|
||||
//};
|
||||
|
||||
class Provider {
|
||||
static Database db;
|
||||
|
||||
// 获取数据库中所有的表
|
||||
Future<List> getTables() async {
|
||||
if (db == null) {
|
||||
return Future.value([]);
|
||||
}
|
||||
List tables = await db.rawQuery('SELECT name FROM sqlite_master WHERE type = "table"');
|
||||
List<String> targetList = [];
|
||||
tables.forEach((item) {
|
||||
targetList.add(item['name']);
|
||||
});
|
||||
return targetList;
|
||||
}
|
||||
|
||||
// 检查数据库中, 表是否完整, 在部份android中, 会出现表丢失的情况
|
||||
Future checkTableIsRight() async {
|
||||
List<String> expectTables = ['cat', 'widget', 'collection'];
|
||||
|
||||
List<String> tables = await getTables();
|
||||
|
||||
for(int i = 0; i < expectTables.length; i++) {
|
||||
if (!tables.contains(expectTables[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
//初始化数据库
|
||||
|
||||
Future init(bool isCreate) async {
|
||||
//Get a location using getDatabasesPath
|
||||
String databasesPath = await getDatabasesPath();
|
||||
String path = join(databasesPath, 'flutter.db');
|
||||
print(path);
|
||||
try {
|
||||
db = await openDatabase(path);
|
||||
} catch (e) {
|
||||
print("Error $e");
|
||||
}
|
||||
bool tableIsRight = await this.checkTableIsRight();
|
||||
|
||||
if (!tableIsRight) {
|
||||
// 关闭上面打开的db,否则无法执行open
|
||||
db.close();
|
||||
// Delete the database
|
||||
await deleteDatabase(path);
|
||||
ByteData data = await rootBundle.load(join("assets", "app.db"));
|
||||
List<int> bytes =
|
||||
data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
|
||||
await new File(path).writeAsBytes(bytes);
|
||||
|
||||
db = await openDatabase(path, version: 1,
|
||||
onCreate: (Database db, int version) async {
|
||||
print('db created version is $version');
|
||||
}, onOpen: (Database db) async {
|
||||
print('new db opened');
|
||||
});
|
||||
} else {
|
||||
print("Opening existing database");
|
||||
}
|
||||
}
|
||||
|
||||
}
|