diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 2e9846d..53ae800 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -1,5 +1,6 @@
+ package="com.flutter.beer"
+ android:installLocation="preferExternal">
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/widget/gestures/gesturedetector/index.md b/docs/widget/gestures/gesturedetector/index.md
index 83532f6..043bdcd 100644
--- a/docs/widget/gestures/gesturedetector/index.md
+++ b/docs/widget/gestures/gesturedetector/index.md
@@ -1 +1,80 @@
-## **文档完善中**
\ No newline at end of file
+## **GestureDetector**
+> 该组件可监听触摸事件,可包裹需要监听的组件后使用带有的触摸事件。
+
+### 构造函数
+```
+GestureDetector({
+ Key key,
+ this.child,
+ this.onTapDown,
+ this.onTapUp,
+ this.onTap,
+ this.onTapCancel,
+ this.onDoubleTap,
+ this.onLongPress,
+ this.onLongPressUp,
+ this.onLongPressDragStart,
+ this.onLongPressDragUpdate,
+ this.onLongPressDragUp,
+ this.onVerticalDragDown,
+ this.onVerticalDragStart,
+ this.onVerticalDragUpdate,
+ this.onVerticalDragEnd,
+ this.onVerticalDragCancel,
+ this.onHorizontalDragDown,
+ this.onHorizontalDragStart,
+ this.onHorizontalDragUpdate,
+ this.onHorizontalDragEnd,
+ this.onHorizontalDragCancel,
+ this.onForcePressStart,
+ this.onForcePressPeak,
+ this.onForcePressUpdate,
+ this.onForcePressEnd,
+ this.onPanDown,
+ this.onPanStart,
+ this.onPanUpdate,
+ this.onPanEnd,
+ this.onPanCancel,
+ this.onScaleStart,
+ this.onScaleUpdate,
+ this.onScaleEnd,
+ this.behavior,
+ this.excludeFromSemantics = false,
+ this.dragStartBehavior = DragStartBehavior.down,
+})
+```
+
+### 属性介绍
+> 点击事件可用Tap属性,执行顺序如下罗列
+- onTapDown: 触摸时触发
+- onTapUp: 触摸离开时触发
+- onTap: 点击后触发
+- onTapCancel: 触发时取消
+- onDoubleTap: 200毫秒内触摸时触发,但不触发onTap
+> 拖动事件可用Pan属性,执行顺序如下罗列,拖动时返回是手势位移数据
+- onPanDown:
+- onPanStart: (DragStartDetails e) {} 返回相对屏幕位置
+- onPanUpdate: (DragUpdateDetails e) {} 回调函数中返回是手势位移数据
+- onPanEnd: (DragEndDetails e) {} 回调函数中返回Velocity,手势瞬时速度,可结合动画使用
+- onPanCancel: 回调取消
+> 以下也可执行拖动事件,使用后不会触发Tap/Pan事件,执行顺序如下罗列,拖动时返回相对整个屏幕距离数据
+- onForcePressStart: (ForcePressDetails e) {}
+- onForcePressPeak: (ForcePressDetails e) {}
+- onForcePressUpdate: (ForcePressDetails e) {}
+- onForcePressEnd: (ForcePressDetails e) {}
+> 监听垂直或水平方向
+- onVerticalDragDown
+- onVerticalDragStart
+- onVerticalDragUpdate
+- onVerticalDragEnd
+- onVerticalDragCancel
+- onHorizontalDragDown
+- onHorizontalDragStart
+- onHorizontalDragUpdate
+- onHorizontalDragEnd
+- onHorizontalDragCancel
+> 手势放大
+- onScaleStart
+- onScaleUpdate
+- onScaleEnd
+
diff --git a/docs/widget/vision/transform/index.md b/docs/widget/vision/transform/index.md
index 83532f6..dc2da45 100644
--- a/docs/widget/vision/transform/index.md
+++ b/docs/widget/vision/transform/index.md
@@ -1 +1,24 @@
-## **文档完善中**
\ No newline at end of file
+## **Transform**
+
+> 在绘制子元素前应用转换的组件
+
+### 构造方法
+```
+Transform({
+ Key key,
+ @required Matrix4 transform,
+ Offset origin,
+ AlignmentGeometry alignment,
+ bool transformHitTests: true,
+ Widget child
+})
+```
+
+### 属性介绍
+origin:坐标系的原点(相对于此渲染对象的左上角)应用矩阵的原点
+alignment:原点的对齐方式
+transform: 在绘制过程中改变子元素的矩阵
+transformHitTests:在测试时是否执行转换
+
+
+### 实例
diff --git a/lib/components/exampleComp.dart b/lib/components/exampleComp.dart
index 37b53f7..314a926 100644
--- a/lib/components/exampleComp.dart
+++ b/lib/components/exampleComp.dart
@@ -12,18 +12,18 @@ class Index extends StatelessWidget {
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
- double _dp = 1.5;
return Store.connect(
builder: (context, child, MainStateModel model) {
return Center(
child: Container(
- width: size.width,
- height: size.height / _dp,
- margin: EdgeInsets.all(30 / _dp),
+ margin: EdgeInsets.all(10),
decoration: BoxDecoration(
border: Border.all(color: Color(AppTheme.mainColor), width: 1.0),
),
- child: this.child,
+ child: SizedBox.fromSize(
+ size: size / 1.3,
+ child: this.child,
+ ),
),
);
},
diff --git a/lib/components/expansionTile.dart b/lib/components/expansionTile.dart
new file mode 100644
index 0000000..21e3089
--- /dev/null
+++ b/lib/components/expansionTile.dart
@@ -0,0 +1,222 @@
+// Copyright 2017 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';
+
+const Duration _kExpand = Duration(milliseconds: 200);
+
+/// A single-line [ListTile] with a trailing button that expands or collapses
+/// the tile to reveal or hide the [children].
+///
+/// This widget is typically used with [ListView] to create an
+/// "expand / collapse" list entry. When used with scrolling widgets like
+/// [ListView], a unique [PageStorageKey] must be specified to enable the
+/// [ExpansionTile] to save and restore its expanded state when it is scrolled
+/// in and out of view.
+///
+/// See also:
+///
+/// * [ListTile], useful for creating expansion tile [children] when the
+/// expansion tile represents a sublist.
+/// * The "Expand/collapse" section of
+/// .
+class ExpansionTile extends StatefulWidget {
+ /// Creates a single-line [ListTile] with a trailing button that expands or collapses
+ /// the tile to reveal or hide the [children]. The [initiallyExpanded] property must
+ /// be non-null.
+ const ExpansionTile({
+ Key key,
+ this.headerBackgroundColor,
+ this.leading,
+ @required this.title,
+ this.backgroundColor,
+ this.iconColor,
+ this.onExpansionChanged,
+ this.children = const [],
+ this.trailing,
+ this.initiallyExpanded = false,
+ }) : assert(initiallyExpanded != null),
+ super(key: key);
+
+ /// A widget to display before the title.
+ ///
+ /// Typically a [CircleAvatar] widget.
+ final Widget leading;
+
+ /// The primary content of the list item.
+ ///
+ /// Typically a [Text] widget.
+ final Widget title;
+
+ /// Called when the tile expands or collapses.
+ ///
+ /// When the tile starts expanding, this function is called with the value
+ /// true. When the tile starts collapsing, this function is called with
+ /// the value false.
+ final ValueChanged onExpansionChanged;
+
+ /// The widgets that are displayed when the tile expands.
+ ///
+ /// Typically [ListTile] widgets.
+ final List children;
+
+ /// The color to display behind the sublist when expanded.
+ final Color backgroundColor;
+
+ /// The color to display the background of the header.
+ final Color headerBackgroundColor;
+
+ /// The color to display the icon of the header.
+ final Color iconColor;
+
+ /// A widget to display instead of a rotating arrow icon.
+ final Widget trailing;
+
+ /// Specifies if the list tile is initially expanded (true) or collapsed (false, the default).
+ final bool initiallyExpanded;
+
+ @override
+ _ExpansionTileState createState() => _ExpansionTileState();
+}
+
+class _ExpansionTileState extends State
+ with SingleTickerProviderStateMixin {
+ static final Animatable _easeOutTween =
+ CurveTween(curve: Curves.easeOut);
+ static final Animatable _easeInTween =
+ CurveTween(curve: Curves.easeIn);
+ static final Animatable _halfTween =
+ Tween(begin: 0.0, end: 0.5);
+
+ final ColorTween _borderColorTween = ColorTween();
+ final ColorTween _headerColorTween = ColorTween();
+ final ColorTween _iconColorTween = ColorTween();
+ final ColorTween _backgroundColorTween = ColorTween();
+
+ AnimationController _controller;
+ Animation _iconTurns;
+ Animation _heightFactor;
+ Animation _borderColor;
+ Animation _headerColor;
+ Animation _iconColor;
+ Animation _backgroundColor;
+
+ bool _isExpanded = false;
+
+ @override
+ void initState() {
+ super.initState();
+ _controller = AnimationController(duration: _kExpand, vsync: this);
+ _heightFactor = _controller.drive(_easeInTween);
+ _iconTurns = _controller.drive(_halfTween.chain(_easeInTween));
+ _borderColor = _controller.drive(_borderColorTween.chain(_easeOutTween));
+ _headerColor = _controller.drive(_headerColorTween.chain(_easeInTween));
+ _iconColor = _controller.drive(_iconColorTween.chain(_easeInTween));
+ _backgroundColor =
+ _controller.drive(_backgroundColorTween.chain(_easeOutTween));
+
+ _isExpanded =
+ PageStorage.of(context)?.readState(context) ?? widget.initiallyExpanded;
+ if (_isExpanded) _controller.value = 1.0;
+ }
+
+ @override
+ void dispose() {
+ _controller.dispose();
+ super.dispose();
+ }
+
+ void _handleTap() {
+ setState(() {
+ _isExpanded = !_isExpanded;
+ if (_isExpanded) {
+ _controller.forward();
+ } else {
+ _controller.reverse().then((void value) {
+ if (!mounted) return;
+ setState(() {
+ // Rebuild without widget.children.
+ });
+ });
+ }
+ PageStorage.of(context)?.writeState(context, _isExpanded);
+ });
+ if (widget.onExpansionChanged != null)
+ widget.onExpansionChanged(_isExpanded);
+ }
+
+ Widget _buildChildren(BuildContext context, Widget child) {
+ final Color borderSideColor = _borderColor.value ?? Colors.transparent;
+ final Color titleColor = _headerColor.value;
+
+ return Container(
+ decoration: BoxDecoration(
+ color: _backgroundColor.value ?? Colors.transparent,
+ border: Border(
+ top: BorderSide(color: borderSideColor),
+ bottom: BorderSide(color: borderSideColor),
+ )),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ IconTheme.merge(
+ data: IconThemeData(color: _iconColor.value),
+ child: Container(
+ color: widget.headerBackgroundColor ?? Colors.black,
+ child: ListTile(
+ onTap: _handleTap,
+ leading: widget.leading,
+ title: DefaultTextStyle(
+ style: Theme.of(context)
+ .textTheme
+ .subhead
+ .copyWith(color: titleColor),
+ child: widget.title,
+ ),
+ trailing: widget.trailing ??
+ RotationTransition(
+ turns: _iconTurns,
+ child: Icon(
+ Icons.expand_more,
+ color: widget.iconColor ?? Colors.grey,
+ ),
+ ),
+ ),
+ ),
+ ),
+ ClipRect(
+ child: Align(
+ heightFactor: _heightFactor.value,
+ child: child,
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+
+ @override
+ void didChangeDependencies() {
+ final ThemeData theme = Theme.of(context);
+ _borderColorTween..end = theme.dividerColor;
+ _headerColorTween
+ ..begin = theme.textTheme.subhead.color
+ ..end = theme.primaryColor;
+ _iconColorTween
+ ..begin = theme.unselectedWidgetColor
+ ..end = theme.primaryColor;
+ _backgroundColorTween..end = widget.backgroundColor;
+ super.didChangeDependencies();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final bool closed = !_isExpanded && _controller.isDismissed;
+ return AnimatedBuilder(
+ animation: _controller.view,
+ builder: _buildChildren,
+ child: closed ? null : Column(children: widget.children),
+ );
+ }
+}
diff --git a/lib/components/headerComp.dart b/lib/components/headerComp.dart
index b1c3b52..f756d18 100644
--- a/lib/components/headerComp.dart
+++ b/lib/components/headerComp.dart
@@ -8,8 +8,8 @@ class Index extends StatelessWidget {
return Text(
this.text,
style: TextStyle(
- // fontStyle: FontStyle.normal,
- ),
+ //color: Theme.of(context).primaryTextTheme.title.color
+ ),
);
}
}
diff --git a/lib/components/markdownComp.dart b/lib/components/markdownComp.dart
index ae61332..a2e2508 100644
--- a/lib/components/markdownComp.dart
+++ b/lib/components/markdownComp.dart
@@ -2,6 +2,9 @@ import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart' as md;
import 'package:efox_flutter/utils/syntaxHighlighter.dart'
show DartSyntaxHighlighter;
+import 'package:efox_flutter/config/color.dart' show materialColor;
+import 'package:efox_flutter/config/theme.dart' show AppTheme;
+import 'package:efox_flutter/store/index.dart' show model;
class Index extends StatelessWidget {
final String data;
diff --git a/lib/components/webviewComp.dart b/lib/components/webviewComp.dart
index 499d58d..60c68aa 100644
--- a/lib/components/webviewComp.dart
+++ b/lib/components/webviewComp.dart
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
-import 'headerComp.dart' as Header;
-import 'package:flutter_webview_plugin/flutter_webview_plugin.dart' show FlutterWebviewPlugin, WebviewScaffold;
+import 'package:flutter_webview_plugin/flutter_webview_plugin.dart'
+ show FlutterWebviewPlugin, WebviewScaffold;
class Index extends StatelessWidget {
final String url;
@@ -18,17 +18,21 @@ class Index extends StatelessWidget {
Widget build(BuildContext context) {
return WebviewScaffold(
url: this.url,
- appBar: new AppBar(
- title: Header.Index(this.title),
+ enableAppScheme: false,
+ appBar: AppBar(
+ elevation: 0,
+ title: Text(
+ this.title,
+ ),
+ leading: IconButton(
+ icon: Icon(Icons.arrow_back),
+ color: Theme.of(context).primaryTextTheme.title.color,
+ onPressed: () => Navigator.pop(context),
+ ),
),
withZoom: true,
withLocalStorage: true,
hidden: true,
- // initialChild: Container(
- // child: const Center(
- // child: CircularProgressIndicator(),
- // ),
- // ),
);
}
}
diff --git a/lib/components/widgetComp.dart b/lib/components/widgetComp.dart
index 45df4f3..e690299 100644
--- a/lib/components/widgetComp.dart
+++ b/lib/components/widgetComp.dart
@@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:efox_flutter/store/index.dart' show Store;
-import 'headerComp.dart' as Header;
import 'package:efox_flutter/components/markdownComp.dart' as MarkDownComp;
import 'package:efox_flutter/lang/index.dart' show AppLocalizations;
import 'package:efox_flutter/components/baseComp.dart' as BaseComp;
@@ -85,12 +84,18 @@ class IndexState extends State {
this.model = model;
return Scaffold(
appBar: AppBar(
- /* title: Header.Index(
- this.title,
- ), */
+ //title: Text(this.title),
+ elevation: 0,
+ backgroundColor: Color(AppTheme.secondColor),
actions: this.getActions(
context,
),
+ leading: IconButton(
+ icon: Icon(Icons.arrow_back),
+ //color: Theme.of(context).primaryTextTheme.title.color,
+ color: Color(AppTheme.blackColor),
+ onPressed: () => Navigator.pop(context),
+ ),
),
body: this.loading ? this.renderLoading() : this.renderWidget(),
);
@@ -127,6 +132,8 @@ class IndexState extends State {
getActions(context) {
return [
IconButton(
+ //color: Theme.of(context).primaryTextTheme.title.color,
+ color: Color(AppTheme.blackColor),
icon: Icon(
Icons.insert_link,
),
@@ -137,16 +144,18 @@ class IndexState extends State {
);
},
),
- IconButton(
+ /* IconButton(
icon: Icon(
Icons.code,
),
onPressed: () async {
this.openPage(context);
},
- ),
+ ), */
IconButton(
icon: Icon(Icons.share),
+ //color: Theme.of(context).primaryTextTheme.title.color,
+ color: Color(AppTheme.blackColor),
onPressed: () {
final String msg =
this.model.config.state.env.githubAssetOrigin + this.mdUrl;
diff --git a/lib/config/color.dart b/lib/config/color.dart
new file mode 100644
index 0000000..1cbf1da
--- /dev/null
+++ b/lib/config/color.dart
@@ -0,0 +1,26 @@
+Map materialColor = {
+ 'red': 0xFFF44336,
+ 'pink': 0xFFE91E63,
+ 'purple': 0xFF9C27B0,
+ 'deepPurple': 0xFF673AB7,
+ 'indigo': 0xFF3F51B5,
+ //
+
+ 'blue': 0xFF2196F3,
+ 'lightBlue': 0xFF03A9F4,
+ 'cyan': 0xFF00BCD4,
+ 'teal': 0xFF009688,
+ 'green': 0xFF4CAF50,
+ //
+ 'lightGreen': 0xFF8BC34A,
+ 'lime': 0xFFCDDC39,
+ 'yellow': 0xFFFFEB3B,
+ 'amber': 0xFFFFC107,
+ 'orange': 0xFFFF9800,
+ //
+ 'deepOrange': 0xFFFF5722,
+ 'brown': 0xFF795548,
+ 'grey': 0xFF9E9E9E,
+ 'blueGrey': 0xFF607D8B,
+ 'black': 0xFF222222,
+};
diff --git a/lib/config/theme.dart b/lib/config/theme.dart
index 967ab66..0582100 100644
--- a/lib/config/theme.dart
+++ b/lib/config/theme.dart
@@ -1,31 +1,48 @@
import 'package:flutter/material.dart';
+import 'color.dart' show materialColor;
+/**
+ * yello #FFEB3B
+ * red #F44336
+ * blue #2196F3
+ */
class AppTheme {
- static int mainColor = 0xFFD32F2F;
+ //static int mainColor = 0xFFD32F2F;
+ static int mainColor = materialColor['red'];
static int secondColor = 0xFFFFFFFF;
static int thirdColor = 0xFFFAFAFA;
static int greyColor = 0x8A000000;
static int blackColor = 0xFF000000;
static int lineColor = 0xFFEEEEEE;
- static ThemeData themData = ThemeData(
- textTheme: TextTheme(
- body1: TextStyle(
- // color: Colors.black,
- // fontWeight: FontWeight.bold,
- ),
- ),
- //platform: TargetPlatform.iOS,
- iconTheme: IconThemeData(
- size: 32,
- color: Color(thirdColor),
- opacity: 0.85,
- ),
- // primaryIconTheme 导航栏按钮颜色
- primaryIconTheme: IconThemeData(
- color: Color(secondColor),
- ),
- accentColor: Colors.grey, // 选中颜色
- primaryColor: Color(mainColor), // appbar背景
- scaffoldBackgroundColor: Color(secondColor), // 整体的scaffold背景颜色
- );
+ static getThemeData(String theme) {
+ //print('==================================getThemeData=$theme');
+ mainColor = materialColor[theme];
+ ThemeData themData = ThemeData(
+ textTheme: TextTheme(
+ body1: TextStyle(
+ // color: Colors.black,
+ // fontWeight: FontWeight.bold,
+ ),
+ ),
+ //platform: TargetPlatform.iOS,
+ iconTheme: IconThemeData(
+ size: 32,
+ color: Color(thirdColor),
+ opacity: 0.85,
+ ),
+ // primaryIconTheme 导航栏按钮颜色
+ primaryIconTheme: IconThemeData(
+ color: Color(secondColor),
+ ),
+ accentColor: Colors.grey, // 选中颜色
+ primaryColor: Color(mainColor), // appbar背景
+ primaryTextTheme: TextTheme(
+ title: TextStyle(
+ // color: Colors.red
+ ),
+ button: TextStyle(color: Colors.red)),
+ scaffoldBackgroundColor: Color(secondColor), // 整体的scaffold背景颜色
+ );
+ return themData;
+ }
}
diff --git a/lib/lang/index.dart b/lib/lang/index.dart
index c6ca568..a5f622b 100644
--- a/lib/lang/index.dart
+++ b/lib/lang/index.dart
@@ -3,6 +3,7 @@ import 'dart:async';
import 'dart:convert';
import 'package:efox_flutter/lang/config.dart' as I18NConfig;
import 'package:flutter/services.dart' show rootBundle;
+import 'package:efox_flutter/utils/localstage.dart' show LocalStorage;
class AppLocalizations {
Locale _locale; // language
@@ -21,7 +22,8 @@ class AppLocalizations {
}
// 设置语言切换代理
- static void setProxy(Function setState, AppLocalizationsDelegate delegate) async {
+ static void setProxy(
+ Function setState, AppLocalizationsDelegate delegate) async {
_setState = setState;
_delegate = delegate;
print("_delegate = $_delegate");
@@ -29,17 +31,17 @@ class AppLocalizations {
static get languageCode => _inst._locale.languageCode;
- static void getLanguageJson([Locale locale]) async {
+ static Future getLanguageJson([Locale locale]) async {
Locale _tmpLocale = _inst._locale;
print(_tmpLocale.languageCode);
String jsonLang;
try {
- jsonLang = await rootBundle
- .loadString('locale/${_tmpLocale.languageCode}.json');
+ jsonLang =
+ await rootBundle.loadString('locale/${_tmpLocale.languageCode}.json');
} catch (e) {
_inst._locale = Locale(I18NConfig.ConfigLanguage.defualtLanguage.code);
- jsonLang = await rootBundle
- .loadString('locale/${I18NConfig.ConfigLanguage.defualtLanguage.code}.json');
+ jsonLang = await rootBundle.loadString(
+ 'locale/${I18NConfig.ConfigLanguage.defualtLanguage.code}.json');
}
json.decode(jsonLang);
jsonLanguage = json.decode(jsonLang);
@@ -54,10 +56,12 @@ class AppLocalizations {
: Locale("zh", "CH");
}
_inst._locale = locale;
- getLanguageJson(); // 根据语言获取对应的国际化文件
- _setState(() {
- _delegate = AppLocalizationsDelegate(locale);
- });
+ LocalStorage.set('lang', locale.languageCode);
+ getLanguageJson().then((v) {
+ _setState(() {
+ _delegate = AppLocalizationsDelegate(locale);
+ });
+ }); // 根据语言获取对应的国际化文件
}
// get local language
@@ -95,17 +99,23 @@ class AppLocalizations {
class AppLocalizationsDelegate extends LocalizationsDelegate {
final Locale locale;
- AppLocalizationsDelegate ([this.locale]);
+ AppLocalizationsDelegate([this.locale]);
@override
bool isSupported(Locale locale) {
- return I18NConfig.ConfigLanguage.sopportLanguage.keys.toList().contains(locale.languageCode);
+ return I18NConfig.ConfigLanguage.sopportLanguage.keys
+ .toList()
+ .contains(locale.languageCode);
}
@override
Future load(Locale _locale) async {
- Locale _tmpLocale = locale ?? _locale;
- return await AppLocalizations.init(_tmpLocale);
+ String lang = await LocalStorage.get('lang');
+ Locale __locale = locale ?? _locale;
+ if (lang != null) {
+ __locale = Locale(lang);
+ }
+ return await AppLocalizations.init(__locale);
}
@override
@@ -113,4 +123,4 @@ class AppLocalizationsDelegate extends LocalizationsDelegate {
// false时 不执行上述重写函数
return false;
}
-}
\ No newline at end of file
+}
diff --git a/lib/main.dart b/lib/main.dart
index 90e8934..9eeeaa7 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,22 +1,12 @@
import 'package:flutter/material.dart';
-
-//语言包实例化
-import 'package:flutter_localizations/flutter_localizations.dart';
+import 'package:flutter_localizations/flutter_localizations.dart'; //语言包实例化
import 'package:efox_flutter/lang/index.dart'
show AppLocalizationsDelegate, AppLocalizations;
import 'package:efox_flutter/lang/config.dart' show ConfigLanguage;
-
-//引用Store 层
-import 'package:efox_flutter/store/index.dart' show model, Store;
-
-//路由
-import 'package:efox_flutter/router/index.dart' show FluroRouter;
-
-//主题
-import 'package:efox_flutter/config/theme.dart' show AppTheme;
-
-//统计
-import 'package:efox_flutter/utils/analytics.dart' as Analytics;
+import 'package:efox_flutter/store/index.dart' show model, Store; //引用Store 层
+import 'package:efox_flutter/router/index.dart' show FluroRouter; //路由
+import 'package:efox_flutter/config/theme.dart' show AppTheme; //主题
+import 'package:efox_flutter/utils/analytics.dart' as Analytics; //统计
void main() => runApp(MainApp());
@@ -38,37 +28,40 @@ class MainAppState extends State {
//实例化多语言
super.initState();
_delegate = AppLocalizationsDelegate();
+ model.dispatch('config', 'getTheme');
}
@override
Widget build(BuildContext context) {
return Store.init(
model: model,
- child: MaterialApp(
- localeResolutionCallback: (deviceLocale, supportedLocales) {
- print(
- 'deviceLocale=$deviceLocale supportedLocales=$supportedLocales');
- Locale _locale = supportedLocales.contains(deviceLocale)
- ? deviceLocale
- : Locale('zh');
- return _locale;
- },
- onGenerateTitle: (context) {
- // 设置多语言代理
- AppLocalizations.setProxy(setState, _delegate);
- return 'flutter';
- },
- localizationsDelegates: [
- GlobalMaterialLocalizations.delegate,
- GlobalWidgetsLocalizations.delegate,
- _delegate,
- ],
- supportedLocales: ConfigLanguage.supportedLocales,
+ child: Store.connect(builder: (context, child, model) {
+ return MaterialApp(
+ localeResolutionCallback: (deviceLocale, supportedLocales) {
+ print(
+ 'deviceLocale=$deviceLocale supportedLocales=$supportedLocales');
+ Locale _locale = supportedLocales.contains(deviceLocale)
+ ? deviceLocale
+ : Locale('zh');
+ return _locale;
+ },
+ onGenerateTitle: (context) {
+ // 设置多语言代理
+ AppLocalizations.setProxy(setState, _delegate);
+ return 'flutter';
+ },
+ localizationsDelegates: [
+ GlobalMaterialLocalizations.delegate,
+ GlobalWidgetsLocalizations.delegate,
+ _delegate,
+ ],
+ supportedLocales: ConfigLanguage.supportedLocales,
// title: 'Flutter Demo',
- theme: AppTheme.themData,
- onGenerateRoute: FluroRouter.router.generator,
- navigatorObservers: [Analytics.observer],
- ),
+ theme: AppTheme.getThemeData(model.config.state.theme),
+ onGenerateRoute: FluroRouter.router.generator,
+ navigatorObservers: [Analytics.observer],
+ );
+ }),
);
}
}
diff --git a/lib/page/component/tabs.dart b/lib/page/component/tabs.dart
index c7192d2..334075c 100644
--- a/lib/page/component/tabs.dart
+++ b/lib/page/component/tabs.dart
@@ -5,7 +5,6 @@ import 'package:efox_flutter/config/theme.dart' show AppTheme;
import 'package:efox_flutter/widget/index.dart' as WidgetRoot;
import 'package:efox_flutter/router/index.dart' show FluroRouter;
import 'package:efox_flutter/lang/index.dart' show AppLocalizations;
-import 'package:efox_flutter/components/headerComp.dart' as Header;
class Index extends StatefulWidget {
final MainStateModel model;
@@ -45,12 +44,6 @@ class _IndexState extends State
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
- /* appBar: AppBar(
- title: Header.Index(
- AppLocalizations.$t('nav_title_0'),
- ),
- actions: appBarActions(),
- ), */
appBar: PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight),
child: Container(
@@ -76,13 +69,6 @@ class _IndexState extends State
tabs: _mapList.map((v) {
return new Tab(
text: AppLocalizations.$t(v.typeName),
- /* icon: Icon(
- IconData(
- v.code,
- fontFamily: 'MaterialIcons',
- matchTextDirection: true,
- ),
- ), */
);
}).toList());
}
@@ -152,36 +138,4 @@ class _IndexState extends State
),
);
}
-
- List appBarActions() {
- return [
- PopupMenuButton(
- icon: Icon(
- Icons.more_vert,
- ),
- onSelected: (local) {
- AppLocalizations.changeLanguage(Locale(local));
- print('local=$local');
- },
- itemBuilder: (context) => [
- PopupMenuItem(
- child: Row(
- children: [
- Text('中文'),
- ],
- ),
- value: 'zh',
- ),
- PopupMenuItem(
- child: Row(
- children: [
- Text('english'),
- ],
- ),
- value: 'en',
- ),
- ],
- ),
- ];
- }
}
diff --git a/lib/page/home.dart b/lib/page/home.dart
index 56ee524..cd9e83f 100644
--- a/lib/page/home.dart
+++ b/lib/page/home.dart
@@ -6,7 +6,9 @@ import 'package:efox_flutter/controller/index.dart' as Controller;
//import 'component/index.dart' as TabIndex;
// import 'mine/index.dart' as MyIndex;
import 'component/tabs.dart' as TabIndex;
-import 'mine/index_1.dart' as MyIndex;
+import 'mine/index_2.dart' as MyIndex;
+
+import 'package:efox_flutter/utils/appVersion.dart' show AppVersion;
class Index extends StatefulWidget {
@override
@@ -22,6 +24,7 @@ class _IndexState extends State {
super.initState();
_pageController = PageController();
Controller.initState();
+ AppVersion().check(context);
}
@override
diff --git a/lib/page/mine/index_1.dart b/lib/page/mine/index_1.dart
index c6c4e77..32f854d 100644
--- a/lib/page/mine/index_1.dart
+++ b/lib/page/mine/index_1.dart
@@ -67,7 +67,7 @@ class _IndexState extends State {
child: Wrap(
children: [
ListTile(
- leading: Icon(Icons.label_outline),
+ //leading: Icon(Icons.label_outline),
title: Text(
AppLocalizations.$t('common_mine_1.cn'),
),
@@ -77,7 +77,7 @@ class _IndexState extends State {
},
),
ListTile(
- leading: Icon(Icons.label_outline),
+ //leading: Icon(Icons.label_outline),
title: Text(AppLocalizations.$t('common_mine_1.en')),
onTap: () {
AppLocalizations.changeLanguage(Locale('en'));
@@ -102,7 +102,7 @@ class _IndexState extends State {
child: Wrap(
children: [
ListTile(
- leading: Icon(Icons.label_outline),
+ //leading: Icon(Icons.label_outline),
title: Text(
AppLocalizations.$t('mine.loadNetwork'),
),
@@ -112,7 +112,7 @@ class _IndexState extends State {
},
),
ListTile(
- leading: Icon(Icons.label_outline),
+ //leading: Icon(Icons.label_outline),
title: Text(AppLocalizations.$t('mine.loadLocal')),
onTap: () {
widget.model.dispatch('config', 'setEnv', false);
@@ -128,71 +128,49 @@ class _IndexState extends State {
@override
Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(
- title: Text(AppLocalizations.$t('nav_title_1')),
- elevation: 0,
- centerTitle: true,
- ),
- body: ListView.builder(
- shrinkWrap: true,
- itemCount: _getList().length * 2,
- itemBuilder: (context, index) {
- double _index = index / 2;
- if (index % 2 == 0) {
- dynamic item = _getList()[_index.toInt()];
- return ListTile(
- onTap: () {
- actionsEvent(item['index']);
- },
- leading: Icon(
- IconData(
- item['icon'],
- fontFamily: 'MaterialIcons',
- matchTextDirection: true,
- ),
- ),
- title: Text(item['name']),
- );
- } else {
- return Divider(
- color: Color(AppTheme.lineColor),
- );
- }
- },
- ),
- );
- /* return SingleChildScrollView(
+ return SingleChildScrollView(
child: Column(
children: [
Container(
decoration: BoxDecoration(
- borderRadius: BorderRadius.only(
- bottomLeft: Radius.circular(10),
- bottomRight: Radius.circular(10)
- ),
- color: Colors.red,
- ),
+ borderRadius: BorderRadius.only(
+ bottomLeft: Radius.circular(10),
+ bottomRight: Radius.circular(10),
+ ),
+ color: Colors.red,
+ gradient: LinearGradient(
+ begin: Alignment.centerLeft,
+ end: Alignment.centerRight,
+ colors: [Colors.red, Colors.blue])),
height: 240,
child: Stack(
alignment: const FractionalOffset(0.8, 0.8),
children: [
- Row(
- children: [
- Image.network(
- 'https://raw.githubusercontent.com/efoxTeam/flutter-ui/master/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png',
- width: 80.0,
- height: 80.0,
- fit: BoxFit.cover,
- ),
- SizedBox(
- width: 10,
- ),
- Text(
- 'Hello Guest',
- style: TextStyle(color: Colors.white),
- )
- ],
+ Center(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Opacity(
+ child: Image.network(
+ 'https://raw.githubusercontent.com/efoxTeam/flutter-ui/master/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png',
+ width: 80.0,
+ height: 80.0,
+ fit: BoxFit.cover,
+ ),
+ opacity: 1,
+ ),
+ SizedBox(
+ height: 10,
+ ),
+ Text(
+ "Flutter-UI",
+ style: TextStyle(
+ color: Colors.white,
+ fontSize: 26,
+ fontWeight: FontWeight.bold),
+ )
+ ],
+ ),
)
],
),
@@ -226,7 +204,7 @@ class _IndexState extends State {
),
],
),
- ); */
+ );
}
}
diff --git a/lib/page/mine/index_2.dart b/lib/page/mine/index_2.dart
new file mode 100644
index 0000000..ca75f0c
--- /dev/null
+++ b/lib/page/mine/index_2.dart
@@ -0,0 +1,156 @@
+import 'package:flutter/material.dart';
+import 'dart:io' show Platform;
+import 'package:efox_flutter/lang/index.dart' show AppLocalizations;
+//import 'package:efox_flutter/router/index.dart' show FluroRouter;
+import 'package:efox_flutter/config/theme.dart' show AppTheme;
+import 'package:efox_flutter/store/index.dart' show model;
+import 'package:efox_flutter/config/color.dart' show materialColor;
+import 'package:efox_flutter/utils/appVersion.dart' show AppVersion;
+import 'package:efox_flutter/components/expansionTile.dart' as Comp;
+
+class _IndexState extends State {
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ /**
+ * 国际化
+ */
+ void openLanguageSelectMenu() async {
+ await showModalBottomSheet(
+ context: context,
+ builder: (BuildContext bc) {
+ return Container(
+ child: Wrap(
+ children: [
+ ListTile(
+ title: Text(
+ '中文',
+ ),
+ onTap: () {
+ AppLocalizations.changeLanguage(Locale('zh'));
+ Navigator.pop(context);
+ },
+ ),
+ ListTile(
+ title: Text('English'),
+ onTap: () {
+ AppLocalizations.changeLanguage(Locale('en'));
+ Navigator.pop(context);
+ },
+ ),
+ ],
+ ),
+ );
+ },
+ );
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ List _EdageList = [];
+ materialColor.forEach((k, v) {
+ _EdageList.add(this.Edage(k, v));
+ });
+ return Scaffold(
+ appBar: AppBar(
+ elevation: 0,
+ centerTitle: true,
+ title: Text(AppLocalizations.$t('nav_title_1'))),
+ body: ListView(
+ children: [
+ ListTile(
+ onTap: () => this.openLanguageSelectMenu(),
+ leading: Icon(Icons.language),
+ title: Text(AppLocalizations.$t('common_mine_1.language')),
+ trailing: Container(
+ child: Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Text(AppLocalizations.languageCode),
+ Icon(Icons.navigate_next)
+ ],
+ ),
+ )),
+ Divider(
+ color: Color(AppTheme.lineColor),
+ ),
+ Comp.ExpansionTile(
+ leading: Icon(Icons.color_lens),
+ headerBackgroundColor: Colors.transparent,
+ title: Row(
+ children: [
+ Text(AppLocalizations.$t('common_mine_1.theme')),
+ Container(
+ margin: EdgeInsets.fromLTRB(5, 5, 0, 0),
+ child: Container(
+ color: Color(materialColor[model.config.state.theme]),
+ height: 15,
+ width: 15,
+ ),
+ )
+ ],
+ ),
+ children: [
+ Padding(
+ padding: EdgeInsets.all(10),
+ child: Wrap(
+ spacing: 10,
+ runSpacing: 5,
+ children: _EdageList,
+ ),
+ )
+ ],
+ ),
+ Divider(
+ color: Color(AppTheme.lineColor),
+ ),
+ (Platform.isAndroid)
+ ? ListTile(
+ onTap: () {
+ AppVersion().check(context, showTips: true);
+ },
+ leading: Icon(Icons.history),
+ title: Text(AppLocalizations.$t('common_mine_1.version')),
+ trailing: Container(
+ child: Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Text(model.config.state.appVersion),
+ Icon(Icons.navigate_next)
+ ],
+ ),
+ ))
+ : Container(),
+ (Platform.isAndroid)
+ ? Divider(
+ color: Color(AppTheme.lineColor),
+ )
+ : Container(),
+ ],
+ ));
+ }
+
+ Widget Edage(name, color) {
+ return GestureDetector(
+ onTap: () {
+ model.dispatch('config', 'setTheme', name);
+ },
+ child: Container(
+ color: Color(color),
+ height: 30,
+ width: 30,
+ ),
+ );
+ }
+}
+
+class Index extends StatefulWidget {
+ final dynamic model;
+
+ Index({Key key, this.model}) : super(key: key);
+
+ @override
+ _IndexState createState() => _IndexState();
+}
diff --git a/lib/store/http.dart b/lib/store/http.dart
index 0700e9a..04f73c5 100644
--- a/lib/store/http.dart
+++ b/lib/store/http.dart
@@ -6,7 +6,7 @@ Dio getDio([Options options]) {
connectTimeout: 30 * 1000,
receiveTimeout: 30 * 1000,
)); // with default Options
- dio.interceptors.add(LogInterceptor(responseBody: true));
+ // dio.interceptors.add(LogInterceptor(responseBody: true));
return dio;
}
diff --git a/lib/store/models/config_state_model.dart b/lib/store/models/config_state_model.dart
index 1e5adee..4c2b9c0 100644
--- a/lib/store/models/config_state_model.dart
+++ b/lib/store/models/config_state_model.dart
@@ -2,11 +2,15 @@ import 'dart:convert';
import 'package:efox_flutter/config/index.dart' as Config;
import 'package:efox_flutter/store/index.dart' show model;
import 'package:efox_flutter/utils/loadAsset.dart' show loadAssets;
+import 'package:efox_flutter/utils/localstage.dart' show LocalStorage;
+import 'package:package_info/package_info.dart' show PackageInfo;
class ConfigInfo {
bool isPro = Config.isPro;
String version = '1.0';
dynamic env = Config.env;
+ String theme = 'red';
+ String appVersion = '-';
}
ConfigInfo _appConfigInfo = new ConfigInfo();
@@ -14,9 +18,22 @@ ConfigInfo _appConfigInfo = new ConfigInfo();
class ConfigModel {
get state => _appConfigInfo;
- dynamic getVersion () async {
+ Future getAppVersion() async {
+ PackageInfo packageInfo = await PackageInfo.fromPlatform();
+ _appConfigInfo.appVersion = await packageInfo.version;
+ }
+
+ Future getTheme() async {
+ String theme = await LocalStorage.get('theme');
+ if (theme != null) {
+ _appConfigInfo.theme = theme;
+ }
+ }
+
+ dynamic getVersion() async {
print('version ${model.config.state.env.versionUrl}');
- String _version = await loadAssets(model.config.state.env.versionUrl).then((resp) {
+ String _version =
+ await loadAssets(model.config.state.env.versionUrl).then((resp) {
Map res = json.decode(resp);
return res['version'].toString() ?? '0.1';
}).catchError((err) {
@@ -37,6 +54,13 @@ class ConfigModel {
case 'setVersion':
_appConfigInfo.version = await this.getVersion();
break;
+ case 'setTheme':
+ _appConfigInfo.theme = payload;
+ LocalStorage.set('theme', payload);
+ break;
+ case 'getTheme':
+ await this.getTheme();
+ break;
}
}
}
diff --git a/lib/store/models/main_state_model.dart b/lib/store/models/main_state_model.dart
index 0808905..dc1ec67 100644
--- a/lib/store/models/main_state_model.dart
+++ b/lib/store/models/main_state_model.dart
@@ -21,6 +21,9 @@ class MainStateModel extends Model with UserModel {
this.state = {
'config': config,
};
+ //init model data
+ config.getAppVersion();
+ //
}
/**
diff --git a/lib/utils/appVersion.dart b/lib/utils/appVersion.dart
new file mode 100644
index 0000000..676a6c2
--- /dev/null
+++ b/lib/utils/appVersion.dart
@@ -0,0 +1,124 @@
+import 'dart:io';
+import 'dart:convert';
+import 'package:package_info/package_info.dart';
+import 'package:path_provider/path_provider.dart';
+import 'package:flutter_downloader/flutter_downloader.dart';
+import 'package:open_file/open_file.dart';
+import 'package:permission_handler/permission_handler.dart';
+import 'package:efox_flutter/store/http.dart' as Http;
+import 'package:flutter/material.dart';
+
+class AppVersion {
+ var _context;
+ Future _checkPermission() async {
+ PermissionStatus permission = await PermissionHandler()
+ .checkPermissionStatus(PermissionGroup.storage);
+ if (permission != PermissionStatus.granted) {
+ Map permissions =
+ await PermissionHandler()
+ .requestPermissions([PermissionGroup.storage]);
+ if (permissions[PermissionGroup.storage] == PermissionStatus.granted) {
+ return true;
+ }
+ } else {
+ return true;
+ }
+ return false;
+ }
+
+ // 获取安装地址
+ Future get _apkLocalPath async {
+ final directory = await getExternalStorageDirectory();
+ return directory.path;
+ }
+
+ Future check(context, {showTips: false}) async {
+ _context = context;
+ if (!Platform.isAndroid) return;
+ // permission Status
+ bool _permissisonReady = await this._checkPermission();
+ if (!_permissisonReady) return;
+ //
+ PackageInfo packageInfo = await PackageInfo.fromPlatform();
+ String version = packageInfo.version;
+ String platform = Platform.isAndroid ? 'android' : 'ios';
+ print('version=$version $platform');
+ Map d = await checkVersion(version, platform);
+ print(d);
+ if (d['isNew']) {
+ this._showDialog(context, d);
+ } else if (showTips) {
+ Scaffold.of(context).showSnackBar(new SnackBar(
+ content: new Text('已经是最新版本'),
+ ));
+ }
+ }
+
+ void _showDialog(context, d) {
+ showDialog(
+ context: context,
+ builder: (BuildContext context) {
+ return AlertDialog(
+ title: Text('升级提示'),
+ content: Text('发现新版本 ${d['version']}'),
+ actions: [
+ FlatButton(
+ child: Text('取消'),
+ onPressed: () {
+ Navigator.pop(context);
+ },
+ ),
+ FlatButton(
+ textColor: Theme.of(context).primaryColor,
+ child: Text('确定'),
+ onPressed: () async {
+ await _downAndInstall(d['version']);
+ Navigator.pop(context);
+ },
+ )
+ ],
+ );
+ });
+ }
+
+ Future checkVersion(String version, String platform) async {
+ var res = await Http.get(
+ 'https://raw.githubusercontent.com/efoxTeam/flutter-ui/master/version.json');
+ res = json.decode(res);
+ print('res=${res['version']}');
+ String newVersion = (res['version'] != null) ? res['version'] : version;
+ //newVersion = '1.0.1'; //debug code
+ print('$newVersion $res $version');
+ bool isNewestVersion = (newVersion == version) ? false : true;
+ Map d = {
+ 'version': newVersion,
+ 'isNew': isNewestVersion,
+ 'platform': platform
+ };
+ return Future.value(d);
+ }
+
+ Future _downAndInstall(String version) async {
+ String _finalApkPath = await _apkLocalPath;
+ String fileName = 'app-release.apk';
+ final taskId = await FlutterDownloader.enqueue(
+ url:
+ 'https://github.com/efoxTeam/flutter-ui/releases/download/v$version/$fileName',
+ savedDir: _finalApkPath,
+ fileName: fileName,
+ showNotification:
+ true, // show download progress in status bar (for Android)
+ openFileFromNotification:
+ true, // click on notification to open downloaded file (for Android)
+ );
+ await FlutterDownloader.loadTasks();
+ FlutterDownloader.registerCallback((id, status, progress) {
+ print(
+ 'Download task ($id) is in status ($status) and process ($progress) status ${DownloadTaskStatus.complete} _finalApkPath=$_finalApkPath');
+ if (taskId == id && status == DownloadTaskStatus.complete) {
+ OpenFile.open(_finalApkPath);
+ FlutterDownloader.open(taskId: id);
+ }
+ });
+ }
+}
diff --git a/lib/utils/github.dart b/lib/utils/github.dart
new file mode 100644
index 0000000..a6553d4
--- /dev/null
+++ b/lib/utils/github.dart
@@ -0,0 +1,38 @@
+/* import 'dart:io';
+import 'package:dio/dio.dart';
+
+
+Dio _dio([Options options]) {
+ Dio dio = new Dio(BaseOptions(
+ baseUrl: 'https://api.github.com/graphql',
+ contentType: ContentType.parse('application/json;charset=UTF-8'),
+ connectTimeout: 30 * 1000,
+ receiveTimeout: 30 * 1000,
+ )); // with default Options
+ dio.interceptors.add(LogInterceptor(responseBody: true)); // debug
+ dio.interceptors
+ .add(InterceptorsWrapper(onRequest: (RequestOptions options) async {
+ options.headers["Authorization"] = 'Bearer $token';
+ return options;
+ }, onResponse: (Response response) {
+ return response;
+ }, onError: (DioError e) {
+ return e;
+ })); //debug
+ return dio;
+}
+
+Future fetch(String query) async {
+ Map map = {'query': query};
+ return _dio().post('', data: map);
+}
+
+
+github.fetch('''
+query {
+ viewer{
+ login
+ }
+}
+ ''');
+ */
diff --git a/lib/utils/localstage.dart b/lib/utils/localstage.dart
new file mode 100644
index 0000000..22d0c3d
--- /dev/null
+++ b/lib/utils/localstage.dart
@@ -0,0 +1,25 @@
+import 'dart:convert';
+import 'package:shared_preferences/shared_preferences.dart';
+
+class LocalStorage {
+ static Future get(String key) async {
+ SharedPreferences prefs = await SharedPreferences.getInstance();
+ return prefs.getString(key);
+ }
+
+ static Future set(String key, String value) async {
+ SharedPreferences prefs = await SharedPreferences.getInstance();
+ prefs.setString(key, value);
+ }
+
+ static Future setJSON(String key, value) async {
+ SharedPreferences prefs = await SharedPreferences.getInstance();
+ value = json.encode(value);
+ prefs.setString(key, value);
+ }
+
+ static Future remove(String key) async {
+ SharedPreferences prefs = await SharedPreferences.getInstance();
+ prefs.remove(key);
+ }
+}
diff --git a/lib/widget/gestures/gesturedetector/demo.dart b/lib/widget/gestures/gesturedetector/demo.dart
index ae1ef05..0e72d49 100644
--- a/lib/widget/gestures/gesturedetector/demo.dart
+++ b/lib/widget/gestures/gesturedetector/demo.dart
@@ -1,24 +1,128 @@
import 'package:flutter/material.dart';
-
class Index extends StatefulWidget {
@override
State createState() => _IndexState();
}
class _IndexState extends State {
+ bool isOn = false;
+ String _value = '';
+ String _value2 = '';
@override
void initState() {
super.initState();
}
+ updateText(txt) {
+ setState(() {
+ _value = txt;
+ });
+ }
+
+ updateText2(txt) {
+ setState(() {
+ _value2 = txt;
+ });
+ }
+
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('GestureDetector'),
+ automaticallyImplyLeading: false,
),
body: Center(
- child: Text('更新中'),
+ child: Column(
+ children: [
+ GestureDetector(
+ onTap: () {
+ Scaffold.of(context).showSnackBar(
+ SnackBar(content: Text('you click the button')));
+ },
+ child: Icon(
+ Icons.share,
+ color: Colors.red,
+ ),
+ ),
+ Divider(
+ height: 20,
+ ),
+ GestureDetector(
+ onDoubleTap: () {
+ updateText('onDoubleTap');
+ },
+ onTapDown: (TapDownDetails e) {
+ updateText('onTapDown');
+ print(e.globalPosition);
+ },
+ onTapCancel: () {
+ updateText('onTapCancel');
+ },
+ // 连接点击两次的话,不会触发onTap,只会触发 onDoubleTap
+ onTap: () {
+ updateText('onTap');
+ setState(() {
+ isOn = !isOn;
+ });
+ },
+ child: Container(
+ margin: EdgeInsets.all(10),
+ color: Colors.red,
+ child: ListTile(
+ leading: Icon(
+ Icons.lightbulb_outline,
+ color: isOn ? Colors.yellow : Colors.grey,
+ ),
+ title: Text("Click Here To Change Light"),
+ ),
+ ),
+ ),
+ Text('Event: $_value'),
+ Text('Try to Double Click'),
+ Divider(
+ height: 40,
+ ),
+ Text("使用ForcePress相关属性将不会触发Tap属性"),
+ GestureDetector(
+ onForcePressEnd: (ev) {
+ updateText2('onForcePressEnd ${ev.globalPosition}');
+ },
+ onForcePressStart: (ev) {
+ updateText2('onForcePressStart ${ev.globalPosition}');
+ },
+ onForcePressUpdate: (ev) {
+ updateText2('onForcePressUpdate ${ev.globalPosition}');
+ },
+ onForcePressPeak: (ev) {
+ updateText2('onForcePressPeak ${ev.globalPosition}');
+ },
+ // 连接点击两次的话,不会触发onTap,只会触发 onDoubleTap
+ onTap: () {
+ updateText2('onTap');
+ setState(() {
+ isOn = !isOn;
+ });
+ },
+ child: Container(
+ margin: EdgeInsets.all(10),
+ alignment: Alignment.center,
+ height: 50,
+ color: Colors.red,
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Text('Tap or Double Tap is not useful'),
+ ],
+ ),
+ ),
+ ),
+ Text(_value2),
+ Divider(
+ height: 20,
+ ),
+ ],
+ ),
),
);
}
diff --git a/lib/widget/gestures/gesturedetector/demo_force_press.dart b/lib/widget/gestures/gesturedetector/demo_force_press.dart
new file mode 100644
index 0000000..3796dec
--- /dev/null
+++ b/lib/widget/gestures/gesturedetector/demo_force_press.dart
@@ -0,0 +1,117 @@
+import 'package:flutter/material.dart';
+import 'package:random_pk/random_pk.dart' show RandomContainer;
+
+class Index extends StatefulWidget {
+ @override
+ State createState() => _IndexState();
+}
+
+class _IndexState extends State {
+ String _value1 = '';
+ String _value2 = '';
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ updateText(txt) {
+ print(txt);
+ setState(() {
+ _value1 = txt;
+ });
+ }
+
+ updateText2(txt) {
+ print(txt);
+ setState(() {
+ _value2 = txt;
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text('GestureDetector'),
+ ),
+ body: Center(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Text("使用ForcePress相关属性将不会触发Tap属性"),
+ GestureDetector(
+ onForcePressEnd: (ForcePressDetails ev) {
+ updateText('onForcePressEnd ${ev} ${ev.globalPosition}');
+ },
+ onForcePressStart: (ForcePressDetails ev) {
+ updateText('onForcePressStart ${ev} ${ev.globalPosition}');
+ },
+ onForcePressUpdate: (ForcePressDetails ev) {
+ updateText('onForcePressUpdate ${ev} ${ev.globalPosition}');
+ },
+ onForcePressPeak: (ForcePressDetails ev) {
+ updateText('onForcePressPeak ${ev} ${ev.globalPosition}');
+ },
+ child: RandomContainer(
+ height: 100,
+ width: 200,
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Text(
+ 'Use onForcePressXX properties and Tap or DoubleTap are not useful'),
+ ],
+ ),
+ ),
+ ),
+ Divider(
+ height: 10,
+ ),
+ Text(_value1),
+ Divider(
+ height: 20,
+ ),
+ Text("监听水平或垂直滚动"),
+ Text('以下是水平滚动,垂直不变化为0'),
+ Divider(
+ height: 20,
+ ),
+ SizedBox(
+ height: 100,
+ width: 200,
+ child: GestureDetector(
+ onHorizontalDragDown: (DragDownDetails e) {
+ updateText2('onHorizontalDragDown $e ${e.globalPosition}');
+ },
+ onHorizontalDragStart: (DragStartDetails e) {
+ updateText2('onHorizontalDragStart $e ${e.globalPosition}');
+ },
+ onHorizontalDragUpdate: (DragUpdateDetails e) {
+ updateText2('onHorizontalDragUpdate $e ${e.globalPosition}');
+ },
+ onHorizontalDragEnd: (DragEndDetails e) {
+ updateText2('onHorizontalDragEnd $e ${e.velocity}');
+ },
+ onHorizontalDragCancel: () {
+ updateText2('onHorizontalDragCancel');
+ },
+ child: RandomContainer(
+ height: 100,
+ width: 100,
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Text(
+ 'Use onForcePressXX properties and Tap or DoubleTap are not useful'),
+ ],
+ ),
+ ),
+ ),
+ ),
+ Text(_value2),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/widget/gestures/gesturedetector/demo_pan.dart b/lib/widget/gestures/gesturedetector/demo_pan.dart
new file mode 100644
index 0000000..bf85e9d
--- /dev/null
+++ b/lib/widget/gestures/gesturedetector/demo_pan.dart
@@ -0,0 +1,73 @@
+import 'package:flutter/material.dart';
+
+class Index extends StatefulWidget {
+ @override
+ State createState() => _IndexState();
+}
+
+class _IndexState extends State {
+ double _top = 0;
+ double _left = 0;
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ setPanEvent(txt, [ev]) {
+ print('$txt $ev');
+
+ if (ev != null && ev.delta != null) {
+ setState(() {
+ _top += ev.delta.dy;
+ _left += ev.delta.dx;
+ });
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text('GestureDetectorDrag'),
+ automaticallyImplyLeading: false,
+ ),
+ body: ConstrainedBox(
+ // 占位撑开全屏
+ constraints: BoxConstraints.expand(),
+ child: Stack(
+ alignment: Alignment.center,
+ children: [
+ Text('Top: $_top, Left: $_left'),
+ Positioned(
+ width: 80,
+ height: 80,
+ top: _top,
+ left: _left,
+ child: GestureDetector(
+ child: CircleAvatar(
+ child: Text("Drag"),
+ ),
+ onPanStart: (DragStartDetails ev) {
+ print('onPanStart $ev');
+ },
+ // DragEndDetails结束时用户滑动的瞬间速度
+ onPanEnd: (DragEndDetails ev) {
+ print('end $ev');
+ },
+ onPanCancel: () {
+ setPanEvent('onPanCancel');
+ },
+ // DragDownDetails返回相对屏幕的位置
+ onPanDown: (DragDownDetails ev) {
+ print('DragDownDetails ${ev.globalPosition}');
+ },
+ onPanUpdate: (DragUpdateDetails ev) {
+ setPanEvent('onPanUpdate', ev);
+ },
+ ),
+ ),
+ ],
+ ),
+ ));
+ }
+}
diff --git a/lib/widget/gestures/gesturedetector/demo_scale.dart b/lib/widget/gestures/gesturedetector/demo_scale.dart
new file mode 100644
index 0000000..9b8843b
--- /dev/null
+++ b/lib/widget/gestures/gesturedetector/demo_scale.dart
@@ -0,0 +1,53 @@
+import 'package:flutter/material.dart';
+import 'package:random_pk/random_pk.dart' show RandomContainer;
+
+class Index extends StatefulWidget {
+ @override
+ State createState() => _IndexState();
+}
+
+class _IndexState extends State {
+ double _width = 100;
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text('GestureDetector'),
+ automaticallyImplyLeading: false,
+ ),
+ body: Center(
+ child: RandomContainer(
+ changeOnRedraw: true,
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Text("手势操作图片放大或缩小"),
+ Divider(
+ height: 10,
+ ),
+ GestureDetector(
+ child: Image.network(
+ 'https://avatars3.githubusercontent.com/u/15372930?s=460&v=4',
+ fit: BoxFit.contain,
+ width: _width,
+ ),
+ onScaleStart: (ScaleStartDetails ev) {
+ print('ScaleStartDetails $ev');
+ },
+ onScaleUpdate: (ScaleUpdateDetails ev) {
+ print("$ev");
+ setState(() {
+ _width = 200 * ev.scale.clamp(.8, 10.0);
+ });
+ },
+ onScaleEnd: (ScaleEndDetails ev) {
+ print('ScaleEndDetails $ev');
+ },
+ )
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/widget/gestures/gesturedetector/demo_tap.dart b/lib/widget/gestures/gesturedetector/demo_tap.dart
new file mode 100644
index 0000000..7173768
--- /dev/null
+++ b/lib/widget/gestures/gesturedetector/demo_tap.dart
@@ -0,0 +1,85 @@
+import 'package:flutter/material.dart';
+
+class Index extends StatefulWidget {
+ @override
+ State createState() => _IndexState();
+}
+
+class _IndexState extends State {
+ bool isOn = false;
+ String _value = '';
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ updateText(txt) {
+ setState(() {
+ _value = txt;
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text('GestureDetector'),
+ ),
+ body: Center(
+ child: Column(
+ mainAxisAlignment:MainAxisAlignment.center,
+ children: [
+ Text("点击时,会先触发Tap事件,再触发Pan事件"),
+ Text("触发外层滚动时,会触发onPanCancel事件"),
+ GestureDetector(
+ onPanDown: (DragDownDetails ev) {
+ print('onPanDown');
+ updateText('onPanDown $ev');
+ },
+ onPanStart: (DragStartDetails ev) {
+ print('onPanStart');
+ updateText('onPanStart $ev');
+ },
+ onPanUpdate: (DragUpdateDetails ev) {
+ print('onPanUpdate');
+ updateText('onPanUpdate $ev');
+ },
+ onPanEnd: (DragEndDetails ev) {
+ print('onPanEnd');
+ updateText('onPanEnd $ev');
+ },
+ onPanCancel: () {
+ print('onPanCancel');
+ updateText('onPanCancel');
+ },
+ // 连接点击两次的话,不会触发onTap,只会触发 onDoubleTap
+ onTap: () {
+ updateText('onTap');
+ setState(() {
+ isOn = !isOn;
+ });
+ },
+ child: Container(
+ margin: EdgeInsets.all(10),
+ color: Colors.red,
+ alignment: Alignment.center,
+ height: 50,
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Text('TURN LIGHTS ON'),
+ Icon(
+ Icons.lightbulb_outline,
+ color: isOn ? Colors.yellow : Colors.grey,
+ )
+ ],
+ ),
+ ),
+ ),
+ Text(_value),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/widget/gestures/gesturedetector/index.dart b/lib/widget/gestures/gesturedetector/index.dart
index e1b039b..7e27b43 100644
--- a/lib/widget/gestures/gesturedetector/index.dart
+++ b/lib/widget/gestures/gesturedetector/index.dart
@@ -1,6 +1,10 @@
import 'package:flutter/material.dart';
import 'package:efox_flutter/components/widgetComp.dart' as WidgetComp;
import 'demo.dart' as Demo;
+import 'demo_tap.dart' as DemoTap;
+import 'demo_pan.dart' as DemoPanDrag;
+import 'demo_force_press.dart' as DemoForcePress;
+import 'demo_scale.dart' as DemoScale;
class Index extends StatefulWidget {
static String title = 'GestureDetector';
@@ -20,6 +24,10 @@ class _IndexState extends State {
mdUrl: Index.mdUrl,
demoChild: [
Demo.Index(),
+ DemoTap.Index(),
+ DemoPanDrag.Index(),
+ DemoForcePress.Index(),
+ DemoScale.Index(),
],
);
}
diff --git a/lib/widget/vision/transform/demo.dart b/lib/widget/vision/transform/demo.dart
index 7774d92..6307466 100644
--- a/lib/widget/vision/transform/demo.dart
+++ b/lib/widget/vision/transform/demo.dart
@@ -15,10 +15,16 @@ class _IndexState extends State {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
- title: Text('SingleChildScrollView'),
+ title: Text('Transform'),
),
- body: Center(
- child: Text('更新中'),
+ body: Transform(
+ alignment: Alignment.center,
+ transform: Matrix4.skewY(0.1),
+ child: Container(
+ padding: const EdgeInsets.all(8.0),
+ color: const Color(0xFFE8581C),
+ child: const Text('Apartment for rent!'),
+ ),
),
);
}
diff --git a/locale/en.json b/locale/en.json
index de5a86f..46c2ff3 100644
--- a/locale/en.json
+++ b/locale/en.json
@@ -11,13 +11,15 @@
"changeVersion": "checkVersion",
"compProgress": "Components Progress"
},
- "common_mine_1" : {
+ "common_mine_1": {
"cn": "CN",
"en": "EN",
"language": "Select Language",
"environment": "Select Environment",
"compProgress": "Components Progress",
- "success": "Success To Change "
+ "success": "Success To Change ",
+ "theme": "Select Theme",
+ "version": "Version"
},
"mine": {
"loadNetwork": "Load Network Document Resources",
diff --git a/locale/zh.json b/locale/zh.json
index 1afd018..8a782c6 100644
--- a/locale/zh.json
+++ b/locale/zh.json
@@ -11,13 +11,15 @@
"changeVersion": "更新版本",
"compProgress": "组件进度"
},
- "common_mine_1" : {
- "cn": "CN",
- "en": "EN",
+ "common_mine_1": {
+ "cn": "中文",
+ "en": "英文",
"language": "选择语言",
"environment": "选择环境",
"compProgress": "组件进度",
- "success": "切换成功"
+ "success": "切换成功",
+ "theme": "选择主题",
+ "version": "版本"
},
"mine": {
"loadNetwork": "网络优良,可选择加载线上文档资源",
diff --git a/pubspec.yaml b/pubspec.yaml
index 0ac674d..44564e6 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -7,7 +7,7 @@ description: A new Flutter project.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# Read more about versioning at semver.org.
-version: 1.0.1+1
+version: 1.0.2+1
environment:
sdk: ">=2.1.0 <3.0.0"
@@ -34,6 +34,12 @@ dependencies:
fluro: ^1.4.0
flutter_screenutil: ^0.5.1
firebase_analytics: ^2.0.2+1
+ random_pk: ^0.0.3
+ device_info: ^0.4.0+1
+ package_info: ^0.4.0+2
+ flutter_downloader: ^1.1.6
+ open_file: ^2.0.1+1
+ permission_handler: ^3.0.0
dev_dependencies:
flutter_test:
diff --git a/readme.md b/readme.md
index 557e220..f28ff36 100644
--- a/readme.md
+++ b/readme.md
@@ -1,178 +1,33 @@
-# Flutter UI
-
+# Flutter UI
v1.0.2
-> flutter ui 开发者社区 提供各种flutter相关开发教程 与 demo
-## 项目背景
-* Google推出Flutter跨平台解决方案,渐渐地受到了开发者们的关注,结合dart使用,能够用一套代码实现开发iOS与Android两套应用,同时也是谷歌的下一代操作系统 Fuchsia 的开发框架,未来还将可以直接编译成桌面应用。
-* Flutter拥有丰富的组件库,多样化的主题与UI风格,让开发者更简单的上手完成界面交互,从而提高了开发效率。
-* 此套组件库在几次没有硝烟的研讨中,命名为"Flutter UI",使命为"知识千万点,学习第一条。代码快点敲,bug无数行"。没错,就是这么不押韵。
+> flutter 开发者社区
+## 功能清单
++ widget 组件教程
++ 多语言切换
++ 多主题切换
++ 自动更新检测
++ firebase 崩溃监控
+
+## apk 下载
+
+[安卓包下载](https://github.com/efoxTeam/flutter-ui/releases/download/v1.0.2/app-release.apk)
-## Release Apk 安装包
-
-[历史版本](https://github.com/efoxTeam/flutter-ui/releases)
+## Demo 预览
+
+
-## 开发者如何参与完善控件
-
+## 项目相关
++ [apk包历史版本](https://github.com/efoxTeam/flutter-ui/releases)
++ [组件开发进度](readme/widget_progress.md)
++ [贡献PR参考](readme/pr.md)
-欢迎有兴趣的小伙伴QQ扫描以上二维码参与进来,一同完善组件
-同时也可以把相关问题通过[issues](https://github.com/efoxTeam/flutter-ui/issues)方式与我们联系
-[开发者如何参与完善控件](readme/pr.md)
+## 项目交流
+
-## 环境与构建
-* 自行完成flutter环境配置
-* 通过 fork 项目master分支代码,进入项目
-* 切换flutter到master分支,步骤如下(若已切换可跳过)
- 1. flutter channel master // 选择master分支
- 2. flutter upgrade // 更新代码
-* 运行模拟器或真机
-* flutter run //运行程序
-* flutter build apk //生成apk
-## app预览
-
-
-## 目录
-```
-Flutter UI
- ├─assets 静态资源
- ├─docs 教程文件
- ├─locale 语言包
- ├─lib dart执行代码
- ├─components
- ├─config 配置文件
- ├─controller
- ├─lang 多语言控制类
- ├─page 路由关联页面
- │ ├─component
- │ └─mine
- ├─router 路由
- ├─store 数据管理
- │ ├─models
- │ └─objects
- ├─utils 项目工具类
- └─widget 项目组件库
- ├─animate
- │ ├─animatedbuilder 【✔️ v1.0】
- │ ├─animatedcontainer
- │ ├─animatedcrossfade
- │ ├─animateddefaulttextstyle
- │ ├─animatedliststate
- │ ├─animatedmodalbarrier
- │ ├─animatedopacity
- │ ├─animatedphysicalmodel
- │ ├─animatedpositioned
- │ ├─animatedsize
- │ ├─animatedwidget
- │ ├─animatedwidgetbasestate
- │ ├─animationcontroller
- │ ├─decoratedboxtransition
- │ ├─fadetransition
- │ ├─hero
- │ ├─positionedtransition
- │ ├─rotationtransition
- │ ├─scaletransition
- │ ├─sizetransition
- │ └─slidetransition
- ├─bulletbox
- │ ├─alertdialog 【✔️ v1.0】
- │ ├─bottomsheet 【✔️ v1.0】
- │ ├─expansionPanel 【✔️ v1.0】
- │ ├─simpledialog 【✔️ v1.0】
- │ └─snackbar 【✔️ v1.0】
- ├─common
- │ ├─assetbundle
- │ ├─buttonbar
- │ ├─chip
- │ ├─container 【✔️ v1.0】
- │ ├─divider 【✔️ v1.0】
- │ ├─flatbutton 【✔️ v1.0】
- │ ├─icon 【✔️ v1.0】
- │ ├─iconbutton
- │ ├─image
- │ ├─listtile
- │ ├─placeholder
- │ ├─raisedbutton
- │ ├─rawimage
- │ ├─stepper
- │ ├─text 【✔️ v1.0】
- │ └─tooltip
- ├─form
- │ ├─checkbox 【✔️ v1.0】
- │ ├─checkboxlisttile 【✔️ v1.0】
- │ ├─slider 【✔️ v1.0】
- │ ├─switch 【✔️ v1.0】
- │ ├─switchListTile 【✔️ v1.0】
- │ ├─daypicker 【✔️ v1.0】
- │ ├─radio 【✔️ v1.0】
- │ ├─radioListTile 【✔️ v1.0】
- │ ├─form
- │ ├─formfield
- │ ├─rawkeyboard
- │ ├─textfield 【✔️ v1.0】
- │ └─textinput
- ├─gestures
- │ ├─absorbpointer
- │ ├─dismissible
- │ ├─dragtarget
- │ ├─gesturedetector
- │ ├─ignorepointer
- │ └─longpressdraggable 【✔️ v1.0】
- ├─navigator
- │ ├─appbar 【✔️ v1.0】
- │ ├─bottomnavigationbar 【✔️ v1.0】
- │ ├─drawer 【✔️ v1.0】
- │ ├─floatingactionbutton 【✔️ v1.0】
- │ ├─materialapp
- │ ├─navigator
- │ ├─popupmenubutton
- │ ├─scaffold 【✔️ v1.0】
- │ ├─tabbar
- │ ├─tabbarview
- │ └─widgetsapp
- ├─regular
- │ ├─align 【✔️ v1.0】
- │ ├─aspectratio 【✔️ v1.0】
- │ ├─center 【✔️ v1.0】
- │ ├─column 【✔️ v1.0】
- │ ├─constrainedbox 【✔️ v1.0】
- │ ├─container 【✔️ v1.0】
- │ ├─fittedbox 【✔️ v1.0】
- │ ├─flow 【✔️ v1.0】
- │ ├─layoutbuilder 【✔️ v1.0】
- │ ├─listbody 【✔️ v1.0】
- │ ├─listview 【✔️ v1.0】
- │ ├─padding 【✔️ v1.0】
- │ ├─row 【✔️ v1.0】
- │ ├─stack 【✔️ v1.0】
- │ ├─table 【✔️ v1.0】
- │ └─wrap 【✔️ v1.0】
- ├─scrollview
- │ ├─customscrollview 【✔️ v1.0】
- │ ├─gridview 【✔️ v1.0】
- │ ├─listview 【✔️ v1.0】
- │ ├─nestedscrollview 【✔️ v1.0】
- │ ├─scrollable 【✔️ v1.0】
- │ ├─scrollbar 【✔️ v1.0】
- │ ├─scrollcontroller 【✔️ v1.0】
- │ └─singlechildscrollview 【✔️ v1.0】
- └─vision
- ├─backdropfilter
- ├─clipoval
- ├─clippath
- ├─cliprect
- ├─custompaint
- ├─decoratedbox
- ├─fractionaltranslation
- ├─mediaquery
- ├─opacity
- ├─rotatedbox
- ├─theme
- └─transform
-```
-
diff --git a/readme/1.0.2/1.jpg b/readme/1.0.2/1.jpg
new file mode 100644
index 0000000..4ff83ed
Binary files /dev/null and b/readme/1.0.2/1.jpg differ
diff --git a/readme/1.0.2/2.jpg b/readme/1.0.2/2.jpg
new file mode 100644
index 0000000..ad90299
Binary files /dev/null and b/readme/1.0.2/2.jpg differ
diff --git a/readme/1.0.2/3.jpg b/readme/1.0.2/3.jpg
new file mode 100644
index 0000000..4db129e
Binary files /dev/null and b/readme/1.0.2/3.jpg differ
diff --git a/readme/1.0.2/4.jpg b/readme/1.0.2/4.jpg
new file mode 100644
index 0000000..9d1b4dc
Binary files /dev/null and b/readme/1.0.2/4.jpg differ
diff --git a/readme/1.0.2/5.jpg b/readme/1.0.2/5.jpg
new file mode 100644
index 0000000..0875087
Binary files /dev/null and b/readme/1.0.2/5.jpg differ
diff --git a/readme/1.0.2/6.jpg b/readme/1.0.2/6.jpg
new file mode 100644
index 0000000..0070e0f
Binary files /dev/null and b/readme/1.0.2/6.jpg differ
diff --git a/readme/apk.png b/readme/apk.png
index da4584b..2d9503f 100644
Binary files a/readme/apk.png and b/readme/apk.png differ
diff --git a/readme/background.md b/readme/background.md
new file mode 100644
index 0000000..52da3d6
--- /dev/null
+++ b/readme/background.md
@@ -0,0 +1,4 @@
+# 项目背景
+* Google推出Flutter跨平台解决方案,渐渐地受到了开发者们的关注,结合dart使用,能够用一套代码实现开发iOS与Android两套应用,同时也是谷歌的下一代操作系统 Fuchsia 的开发框架,未来还将可以直接编译成桌面应用。
+* Flutter拥有丰富的组件库,多样化的主题与UI风格,让开发者更简单的上手完成界面交互,从而提高了开发效率。
+* 此套组件库在几次没有硝烟的研讨中,命名为"Flutter UI",使命为"知识千万点,学习第一条。代码快点敲,bug无数行"。没错,就是这么不押韵。
\ No newline at end of file
diff --git a/readme/pr.md b/readme/pr.md
index 25deb2c..6101f11 100644
--- a/readme/pr.md
+++ b/readme/pr.md
@@ -4,6 +4,7 @@
* fork 一份到自己的仓库
* git clone (您的仓库地址) 拉取项目到本地
* 打开项目 flutter-ui/lib/config/index.dart,修改里面isPro变量为false,(目的加载本地文件)
+*
### 完善文档
* 完善控件文档的,如要完善Animate下的AnimationController控件的文档,您可打开flutter-ui/docs/widget/animate/animationcontroller/index.md,构建AnimationController控件的说明文档,该文档包括但不限于(控件介绍,控件构造方法,控件属性介绍)
@@ -41,3 +42,13 @@
+ test:增加测试
+ chore:构建过程或辅助工具的变动
+## 环境与构建
+* 自行完成flutter环境配置
+* 通过 fork 项目master分支代码,进入项目
+* 切换flutter到master分支,步骤如下(若已切换可跳过)
+ 1. flutter channel master // 选择master分支
+ 2. flutter upgrade // 更新代码
+* 运行模拟器或真机
+* flutter run //运行程序
+* flutter build apk //生成apk
+
diff --git a/readme/qq.md b/readme/qq.md
new file mode 100644
index 0000000..e0f248d
--- /dev/null
+++ b/readme/qq.md
@@ -0,0 +1,5 @@
+# 开发者如何参与完善控件
+
+
+欢迎有兴趣的小伙伴QQ扫描以上二维码参与进来,一同完善组件
+同时也可以把相关问题通过[issues](https://github.com/efoxTeam/flutter-ui/issues)方式与我们联系
diff --git a/readme/v1.0.0_preview.md b/readme/v1.0.0_preview.md
new file mode 100644
index 0000000..afc9e73
--- /dev/null
+++ b/readme/v1.0.0_preview.md
@@ -0,0 +1,5 @@
+
+# app预览
+
+
+
\ No newline at end of file
diff --git a/readme/widget_progress.md b/readme/widget_progress.md
new file mode 100644
index 0000000..a107eaa
--- /dev/null
+++ b/readme/widget_progress.md
@@ -0,0 +1,138 @@
+# 组件开发进度
+```
+Flutter UI
+ ├─assets 静态资源
+ ├─docs 教程文件
+ ├─locale 语言包
+ ├─lib dart执行代码
+ ├─components
+ ├─config 配置文件
+ ├─controller
+ ├─lang 多语言控制类
+ ├─page 路由关联页面
+ │ ├─component
+ │ └─mine
+ ├─router 路由
+ ├─store 数据管理
+ │ ├─models
+ │ └─objects
+ ├─utils 项目工具类
+ └─widget 项目组件库
+ ├─animate
+ │ ├─animatedbuilder 【✔️ v1.0】
+ │ ├─animatedcontainer
+ │ ├─animatedcrossfade
+ │ ├─animateddefaulttextstyle
+ │ ├─animatedliststate
+ │ ├─animatedmodalbarrier
+ │ ├─animatedopacity
+ │ ├─animatedphysicalmodel
+ │ ├─animatedpositioned
+ │ ├─animatedsize
+ │ ├─animatedwidget
+ │ ├─animatedwidgetbasestate
+ │ ├─animationcontroller
+ │ ├─decoratedboxtransition
+ │ ├─fadetransition
+ │ ├─hero
+ │ ├─positionedtransition
+ │ ├─rotationtransition
+ │ ├─scaletransition
+ │ ├─sizetransition
+ │ └─slidetransition
+ ├─bulletbox
+ │ ├─alertdialog 【✔️ v1.0】
+ │ ├─bottomsheet 【✔️ v1.0】
+ │ ├─expansionPanel 【✔️ v1.0】
+ │ ├─simpledialog 【✔️ v1.0】
+ │ └─snackbar 【✔️ v1.0】
+ ├─common
+ │ ├─assetbundle
+ │ ├─buttonbar
+ │ ├─chip
+ │ ├─container 【✔️ v1.0】
+ │ ├─divider 【✔️ v1.0】
+ │ ├─flatbutton 【✔️ v1.0】
+ │ ├─icon 【✔️ v1.0】
+ │ ├─iconbutton
+ │ ├─image
+ │ ├─listtile
+ │ ├─placeholder
+ │ ├─raisedbutton
+ │ ├─rawimage
+ │ ├─stepper
+ │ ├─text 【✔️ v1.0】
+ │ └─tooltip
+ ├─form
+ │ ├─checkbox 【✔️ v1.0】
+ │ ├─checkboxlisttile 【✔️ v1.0】
+ │ ├─slider 【✔️ v1.0】
+ │ ├─switch 【✔️ v1.0】
+ │ ├─switchListTile 【✔️ v1.0】
+ │ ├─daypicker 【✔️ v1.0】
+ │ ├─radio 【✔️ v1.0】
+ │ ├─radioListTile 【✔️ v1.0】
+ │ ├─form
+ │ ├─formfield
+ │ ├─rawkeyboard
+ │ ├─textfield 【✔️ v1.0】
+ │ └─textinput
+ ├─gestures
+ │ ├─absorbpointer
+ │ ├─dismissible
+ │ ├─dragtarget
+ │ ├─gesturedetector
+ │ ├─ignorepointer
+ │ └─longpressdraggable 【✔️ v1.0】
+ ├─navigator
+ │ ├─appbar 【✔️ v1.0】
+ │ ├─bottomnavigationbar 【✔️ v1.0】
+ │ ├─drawer 【✔️ v1.0】
+ │ ├─floatingactionbutton 【✔️ v1.0】
+ │ ├─materialapp
+ │ ├─navigator
+ │ ├─popupmenubutton
+ │ ├─scaffold 【✔️ v1.0】
+ │ ├─tabbar
+ │ ├─tabbarview
+ │ └─widgetsapp
+ ├─regular
+ │ ├─align 【✔️ v1.0】
+ │ ├─aspectratio 【✔️ v1.0】
+ │ ├─center 【✔️ v1.0】
+ │ ├─column 【✔️ v1.0】
+ │ ├─constrainedbox 【✔️ v1.0】
+ │ ├─container 【✔️ v1.0】
+ │ ├─fittedbox 【✔️ v1.0】
+ │ ├─flow 【✔️ v1.0】
+ │ ├─layoutbuilder 【✔️ v1.0】
+ │ ├─listbody 【✔️ v1.0】
+ │ ├─listview 【✔️ v1.0】
+ │ ├─padding 【✔️ v1.0】
+ │ ├─row 【✔️ v1.0】
+ │ ├─stack 【✔️ v1.0】
+ │ ├─table 【✔️ v1.0】
+ │ └─wrap 【✔️ v1.0】
+ ├─scrollview
+ │ ├─customscrollview 【✔️ v1.0】
+ │ ├─gridview 【✔️ v1.0】
+ │ ├─listview 【✔️ v1.0】
+ │ ├─nestedscrollview 【✔️ v1.0】
+ │ ├─scrollable 【✔️ v1.0】
+ │ ├─scrollbar 【✔️ v1.0】
+ │ ├─scrollcontroller 【✔️ v1.0】
+ │ └─singlechildscrollview 【✔️ v1.0】
+ └─vision
+ ├─backdropfilter
+ ├─clipoval
+ ├─clippath
+ ├─cliprect
+ ├─custompaint
+ ├─decoratedbox
+ ├─fractionaltranslation
+ ├─mediaquery
+ ├─opacity
+ ├─rotatedbox
+ ├─theme
+ └─transform
+```
\ No newline at end of file