Commit faeec501 authored by 林生雨's avatar 林生雨

Initial commit

parents
.DS_Store
.dart_tool/
.packages
.pub/
.idea/
.vagrant/
.sconsign.dblite
.svn/
*.swp
profile
DerivedData/
.generated/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
xcuserdata
*.moved-aside
*.pyc
*sync/
Icon?
.tags*
build/
.android/
.ios/
.flutter-plugins
.flutter-plugins-dependencies
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# gm_flutter
A new flutter module project.
## Getting Started
For help getting started with Flutter, view our online
[documentation](https://flutter.dev/).
flutter packages get
flutter packages pub run build_runner clean
flutter packages pub run build_runner build --delete-conflicting-outputs
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/lib" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/.idea" />
<excludeFolder url="file://$MODULE_DIR$/.pub" />
<excludeFolder url="file://$MODULE_DIR$/build" />
</content>
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Dart SDK" level="project" />
<orderEntry type="library" name="Flutter Plugins" level="project" />
<orderEntry type="library" name="Dart Packages" level="project" />
</component>
</module>
\ No newline at end of file
/*
* @author lsy
* @date 2020/6/24
**/
import 'package:flutter_common/Annotations/RouterBaser.dart';
import 'package:flutter_common/Annotations/anno/Router.dart';
import 'package:flutter_common/Annotations/anno/RouterCenter.dart';
import 'package:gm_flutter/ClueModel/ClueRouterImpl.dart';
@Router("ClueRouter",ClueRouterImpl,true)
abstract class ClueRouter implements RouterBaser{
}
\ No newline at end of file
/*
* @author lsy
* @date 2020/6/24
**/
import 'package:gm_flutter/ClueModel/ClueRouter.dart';
class ClueRouterImpl implements ClueRouter{
}
\ No newline at end of file
/*
* @author lsy
* @date 2020/6/20
**/
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class DemoPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return DemoState();
}
}
class DemoState extends State<DemoPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text("ww"),
),
body: Stack(
children: <Widget>[
Stack(
children: <Widget>[
Column(
children: <Widget>[
Container(
width: 50,
height: 50,
color: Colors.redAccent,
)
],
)
],
)
],
),
);
}
}
/*
* @author lsy
* @date 2019-10-15
**/
library GMBase;
export 'base/BaseComponent.dart';
export 'base/BaseUtil.dart';
export 'net/Api.dart';
export 'net/DioUtil.dart';
export 'picker/loadingPicker.dart';
export 'util/DartUtil.dart';
/*
* @author lsy
* @date 2019-10-13
**/
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_common/commonModel/eventbus/GlobalEventBus.dart';
import 'package:flutter_common/commonModel/view/iOSLoading.dart';
import 'package:flutter_svg/svg.dart';
import 'package:gm_flutter/commonModel/GMBase.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
double SCREENWIDTH;
double SCREENHEIGHT;
AppBar baseAppBar(
{String title,
List<Widget> action,
bool centerTitle,
VoidCallback backClick,
Color backgroundColor,
Key key,
bool showBack = true,
double elevation = 0.0,
Widget titleWidget = null}) {
return _baseAppBarChangeTitle(
title: title == null
? Container()
: baseText(title, 16, Color(0xff323232)),
action: action,
centerTitle: centerTitle,
backClick: backClick,
backgroundColor: backgroundColor,
key: key,
showBack: showBack,
elevation: elevation,
titleWidget: titleWidget);
}
AppBar _baseAppBarChangeTitle(
{Widget title,
List<Widget> action,
bool centerTitle,
VoidCallback backClick,
Color backgroundColor,
Key key,
bool showBack,
double elevation,
Widget titleWidget}) {
return AppBar(
key: key,
// backgroundColor:
// backgroundColor == null ? ALColors.ColorFFFFFF : backgroundColor,
title: titleWidget == null ? title : titleWidget,
centerTitle: centerTitle,
elevation: elevation,
leading: showBack
? GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: backClick,
child: Hero(
tag: "left_arrow",
child: Container(
alignment: Alignment.centerLeft,
margin: EdgeInsets.only(left: 10),
child: Container(
width: 30,
height: 30,
child: Image.asset(
"images/left_arrow.png",
color: Color(0xff323232),
),
))),
)
: Container(),
actions: action == null ? List<Widget>() : action,
);
}
Text baseText(String text, double fontSize, Color color, {bool bold = false}) {
return Text(
text,
textScaleFactor: 1.0,
style: TextStyle(
decoration: TextDecoration.none,
fontSize: fontSize,
color: color,
fontStyle: FontStyle.normal,
fontWeight: bold ? FontWeight.w500 : FontWeight.w400),
);
}
Widget baseDivide(double padding) {
return Container(
height: 0.5,
width: double.maxFinite,
margin: EdgeInsets.only(left: padding, right: padding),
color: Color(0xffE5E5E5),
);
}
Widget baseDivideWidth(double width, double padding) {
return Container(
height: 0.5,
width: width,
margin: EdgeInsets.only(left: padding, right: padding),
color: Color(0xffE5E5E5),
);
}
Widget loadingItem({bool needBackground = false}) {
return Center(
child: Container(
width: 77,
height: 77,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: needBackground ? Colors.black : Colors.transparent),
alignment: Alignment.center,
child: MyCupertinoActivityIndicator(
backColor: needBackground ? Colors.white : Colors.black,
),
));
}
Widget netErrorItem() {}
Widget errorItem(VoidCallback retry, {String errorText, String retryText}) {
return Container(
width: SCREENWIDTH,
height: SCREENHEIGHT,
color: Colors.white,
alignment: Alignment.center,
child: Container(
height: SCREENHEIGHT,
child: Container(
margin: EdgeInsets.only(top: 70),
width: 175,
height: 249,
child: Stack(
children: <Widget>[
Positioned(
left: 0,
top: 0,
child: Container(
width: 175,
height: 199,
child: Image.asset("assets/error.png"),
),
),
Positioned(
left: 0,
top: 166,
child: Container(
width: 175,
alignment: Alignment.center,
child: baseText(errorText ?? "网络错误", 15, Color(0xff666666)),
),
),
Positioned(
top: 216,
left: 12,
child: Container(
width: 150,
height: 33,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(22.5),
color: Color(0xff51CDC7)),
alignment: Alignment.center,
child: baseText(retryText ?? "重新加载", 16, Colors.white),
).gestureDetector(() {
retry();
}),
)
],
),
)));
}
//TODO
Widget refreshViewTop(RefreshController refreshController, VoidCallback refresh,
Widget topFix, Widget List) {
return SmartRefresher(
enablePullDown: true,
enablePullUp: false,
header: WaterDropMaterialHeader(
backgroundColor: Color.fromARGB(255, 236, 236, 236),
),
controller: refreshController,
onRefresh: refresh,
child: CustomScrollView(
slivers: <Widget>[
SliverToBoxAdapter(
child: topFix,
),
List
],
));
}
Widget refreshViewbottom(RefreshController refreshController,
VoidCallback refresh, Widget topFix, Widget List) {
return SmartRefresher(
enablePullDown: true,
enablePullUp: false,
header: WaterDropMaterialHeader(
backgroundColor: Color.fromARGB(255, 236, 236, 236),
),
controller: refreshController,
onRefresh: refresh,
child: CustomScrollView(
slivers: <Widget>[
List,
// SliverToBoxAdapter(
// child: topFix,
// ),
],
));
}
Widget baseTextField(TextEditingController editingController,
TextInputType inputType, String hintText) {
return TextField(
cursorColor: Color(0xff20BDBB),
style: TextStyle(fontSize: 14),
decoration: InputDecoration(
hintText: hintText,
hintStyle: TextStyle(fontSize: 14, color: Color(0xffCCCCCC)),
isDense: true,
border: InputBorder.none,
contentPadding:
const EdgeInsets.symmetric(horizontal: 0.0, vertical: 17.0),
),
maxLines: 1,
enableInteractiveSelection: true,
autocorrect: false,
autofocus: true,
keyboardType: inputType,
controller: editingController,
minLines: 1,
);
}
Widget baseRedPoint(int num) {
return Container(
alignment: Alignment.center,
width: 15,
height: 15,
decoration:
BoxDecoration(shape: BoxShape.circle, color: Color(0xffFF5963)),
child: baseText("${num}", 11, Color(0xffFFFFFF)),
);
}
/*
* @author lsy
* @date 2019-12-17
**/
import 'package:flutter/material.dart';
abstract class BaseState<T extends StatefulWidget> extends State<T> {
Widget buildItem(BuildContext context);
@override
Widget build(BuildContext context) {
return WillPopScope(
child: buildItem(context),
onWillPop: () {
onWillPop();
},
);
}
void onWillPop(){
Navigator.pop(context);
}
}
/*
* @author lsy
* @date 2019-10-14
**/
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
const _miniChannle = const MethodChannel('gengmei_mini');
const bool isDebug = ! const bool.fromEnvironment("dart.vm.product");
Future backApp() async {
return await _miniChannle.invokeMethod("backApp");
}
void jumpToPage(Widget page, BuildContext context) {
Navigator.push(context, MaterialPageRoute(builder: ((context) {
return page;
})));
}
This diff is collapsed.
/*
* @author lsy
* @date 2020/5/25
**/
const LOADING = 0;
const ENDLOADING = 1;
const FAIL = 2;
class Pair<T, S> {
dynamic first;
dynamic second;
Pair(this.first, this.second);
}
/*
* @author lsy
* @date 2020/5/28
**/
import 'dart:typed_data';
class PushBean {
int newMessage = 0;
String userKey;
List<int> state = [];
String name;
int time;
String headUrl;
String content;
int doctorUserId;
bool isStarFromDoctor;
int conversation_id;
String place;
Map<int, MessageItem> messageList = {};
}
const CARD_TYPE_DARY = "CARD_TYPE_DARY";
const CARD_TYPE_NORMAL = "CARD_TYPE_NORMAL";
const CARD_TYPE_VOICE = "CARD_TYPE_VOICE";
const CARD_TYPE_PIC = "CARD_TYPE_PIC";
const CARD_TYPE_MONEY = "CARD_TYPE_MONEY";
const CARD_TYPE_BEAUTY = "CARD_TYPE_BEAUTY";
const CARD_TYPE_TIME = "CARD_TYPE_TIME";
class MessageItem {
int id;
int sendTime;
String cardType;
bool isMe;
String headUrl;
String sendState;
MessageDiary diary;
MessageNormal normal;
MessageTime time;
MessageMoney money;
MessageVoice voice;
MessageBeauty beauty;
MessageNativePic pic;
MessageItem(this.id, this.sendTime,
{this.cardType,
this.isMe,
this.pic,
this.sendState,
this.diary,
this.normal,
this.time,
this.money,
this.voice,
this.beauty,
this.headUrl});
static MessageItem buildTime(int id, int sendTime, String time) {
return MessageItem(id, sendTime,
cardType: CARD_TYPE_TIME, time: MessageTime(time));
}
static MessageItem buildNormal(
int id, int sendTime, bool isMe, String content, String url) {
return MessageItem(id, sendTime,
cardType: CARD_TYPE_NORMAL,
isMe: isMe,
headUrl: url,
normal: MessageNormal(content));
}
static MessageItem buildMeNativePic(
int id, int sendTime, String url, String nativePic, String recordPath) {
return MessageItem(id, sendTime,
cardType: CARD_TYPE_PIC,
isMe: true,
headUrl: url,
pic: MessageNativePic(null, nativePic, null, recordPath));
}
static MessageItem buildNetPic(
int id, int sendTime, bool isMe, String url, String headUrl) {
return MessageItem(id, sendTime,
cardType: CARD_TYPE_PIC,
isMe: isMe,
headUrl: headUrl,
pic: MessageNativePic(url, null, null, null));
}
static MessageItem buildBeauty(int id, int sendTime, String headUrl,
String showUrl, String title, String money, String beautyId) {
return MessageItem(id, sendTime,
cardType: CARD_TYPE_BEAUTY,
isMe: true,
headUrl: headUrl,
beauty: MessageBeauty(beautyId, showUrl, title, money));
}
static MessageItem buildMoney(
int id, int sendTime, String headUrl, String picUrl) {
return MessageItem(id, sendTime,
cardType: CARD_TYPE_MONEY,
isMe: true,
headUrl: headUrl,
money: MessageMoney(picUrl));
}
static MessageItem buildDiary(
int id,
int sendTime,
String headUrl,
String leftUrl,
String rightUrl,
String userName,
List<String> tags,
String jumpUrl) {
return MessageItem(id, sendTime,
cardType: CARD_TYPE_DARY,
isMe: true,
headUrl: headUrl,
diary: MessageDiary(leftUrl, rightUrl, userName, tags, jumpUrl));
}
static MessageItem buildVoice(int id, int sendTime, bool isMe, String headUrl,
String path, String url, String during) {
return MessageItem(id, sendTime,
cardType: CARD_TYPE_VOICE,
isMe: isMe,
headUrl: headUrl,
voice: MessageVoice(during, path, url));
}
}
class MessageNativePic {
String url;
String nativePath;
Uint8List data;
String recordPath;
MessageNativePic(this.url, this.nativePath, this.data, this.recordPath);
}
class MessageBeauty {
String id;
String url;
String title;
String money;
MessageBeauty(this.id, this.url, this.title, this.money);
}
class MessageMoney {
String url;
MessageMoney(this.url);
}
class MessageVoice {
String during;
String url;
String path;
MessageVoice(this.during, this.path, this.url);
}
class MessageTime {
String time;
MessageTime(this.time);
}
class MessageNormal {
String content;
MessageNormal(this.content);
}
class MessageDiary {
String leftUrl;
String rightUrl;
String userName;
String jumpUrl;
List<String> tags;
MessageDiary(
this.leftUrl, this.rightUrl, this.userName, this.tags, this.jumpUrl);
}
/*
* @author lsy
* @date 2019-10-08
**/
import 'package:shared_preferences/shared_preferences.dart';
import 'MemoryCache.dart';
import 'ShareCache.dart';
const MEMORY_CACHE = "MEMORY_CACHE";
const SHARE_CACHE = "SHARE_CACHE";
SharedPreferences sharedPreferences;
class CacheManager {
MemoryCache memoryCache;
ShareCache shareCache;
static CacheManager _instance = CacheManager._();
CacheManager._() {
memoryCache = new MemoryCache();
shareCache = new ShareCache();
}
static CacheManager getInstance() {
return _instance;
}
ICache get(String whichCache) {
if (whichCache == MEMORY_CACHE) {
return memoryCache;
} else if (whichCache == SHARE_CACHE) {
return shareCache;
}
}
}
class ICache {
dynamic get(String key) {}
void save(String key, dynamic value) {}
void clearAll(){}
}
/*
* @author lsy
* @date 2019-10-08
**/
import 'CacheManager.dart';
class MemoryCache implements ICache {
Map<String, dynamic> _cacheMap = new Map();
@override
get(String key) {
return _cacheMap[key];
}
@override
void save(String key, value) {
_cacheMap[key] = value;
}
@override
void clearAll() {
_cacheMap.clear();
}
}
/*
* @author lsy
* @date 2019-10-08
**/
import 'package:gm_flutter/commonModel/base/BaseUtil.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'CacheManager.dart';
class ShareCache implements ICache {
@override
get(String key) {
return sharedPreferences.get(key);
}
@override
void save(String key, value) {
if (value is String) {
sharedPreferences.setString(key, value).whenComplete(() {
if (isDebug) {
print("save String ${value} success");
}
});
} else if (value is bool) {
sharedPreferences.setBool(key, value).whenComplete(() {
if (isDebug) {
print("save bool ${value} success");
}
});
} else if (value is double) {
sharedPreferences.setDouble(key, value).whenComplete(() {
if (isDebug) {
print("save double ${value} success");
}
});
} else if (value is int) {
sharedPreferences.setInt(key, value).whenComplete(() {
if (isDebug) {
print("save int ${value} success");
}
});
} else if (value is List<String>) {
sharedPreferences.setStringList(key, value).whenComplete(() {
if (isDebug) {
print("save StringList ${value} success");
}
});
} else {
if (isDebug) {
throw Exception("save error type");
}
}
}
@override
void clearAll() {
sharedPreferences.clear().whenComplete(() {});
}
}
/*
* @author lsy
* @date 2020/6/15
**/
/*
* @author lsy
* @date 2019-10-24
**/
class LoginEvent {
final String userID;
final String cookie;
LoginEvent(this.userID, this.cookie);
}
/*
* @author lsy
* @date 2019-10-24
**/
class SyncMessageEvent {
SyncMessageEvent();
}
/*
* @author lsy
* @date 2020/6/12
**/
import 'package:flutter/material.dart';
class NavigationService {
final GlobalKey<NavigatorState> navigatorKey =
new GlobalKey<NavigatorState>();
Future<dynamic> navigateTo(String routeName) {
return navigatorKey.currentState.pushNamed(routeName);
}
void goBack() {
return navigatorKey.currentState.pop();
}
}
/*
* @author lsy
* @date 2019-09-16
**/
import 'dart:math';
import 'package:dio/dio.dart';
import 'package:gm_flutter/commonModel/base/BaseUtil.dart';
import 'DioUtil.dart';
/**
* 生产环境
*/
const String APP_HOST_RELEASE = "http://profession.paas-merchant.env";
/**
* 测试环境
*/
//const String APP_HOST_DEBUG = "http://backend.paas-merchant.envs";
//const String APP_HOST_DEBUG = "http://doctor.paas-merchant.env";
const String APP_HOST_DEBUG = "http://profession.paas-merchant.env";
/**
* 开发环境
*/
const String APP_HOST_DEV = "http://profession.paas-merchant.env";
class Api {
static String BUILD_CONFIG;
static String PROVIDER_NAME;
static Api intance = new Api._();
Api._();
static Api getInstance() {
return intance;
}
String getBaseUrl() {
if (!isDebug) {
return APP_HOST_RELEASE;
} else {
return APP_HOST_DEBUG;
}
}
}
/*
* @author lsy
* @date 2020/5/14
**/
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:cookie_jar/cookie_jar.dart';
class DioCookieManager {
static DioCookieManager _cookieManager;
DefaultCookieJar cookieJar;
CookieManager cookieManager;
DioCookieManager._() {
cookieJar = new DefaultCookieJar();
cookieManager = new CookieManager(cookieJar);
}
static DioCookieManager getInstance() {
if (_cookieManager == null) {
_cookieManager = new DioCookieManager._();
}
return _cookieManager;
}
CookieManager getCookieManager() {
return cookieManager;
}
void clearCookie() {
cookieJar.deleteAll();
}
}
/*
* @author lsy
* @date 2020/5/14
**/
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:gm_flutter/commonModel/cache/CacheManager.dart';
import 'DioUtil.dart';
class DioInterceptorManager {
static DioInterceptorManager _interceptorManager;
DioInterceptorManager._() {}
static DioInterceptorManager getInstance() {
if (_interceptorManager == null) {
_interceptorManager = new DioInterceptorManager._();
}
return _interceptorManager;
}
InterceptorsWrapper getIntercept() {
return new InterceptorsWrapper(onRequest: (opt) {
if (CacheManager.getInstance().get(SHARE_CACHE).get(NET_COOKIE) != null) {
if (opt.headers == null) {
opt.headers = Map();
}
opt.headers[HttpHeaders.cookieHeader] =
CacheManager.getInstance().get(SHARE_CACHE).get(NET_COOKIE);
}
print("请求之前 onRequest${opt.headers}");
}, onResponse: (response) {
print("响应之前 onResponse${response}");
}, onError: (e) {
print("网络错误 $e message ${e.message}");
});
}
String formatError(DioError e) {
String reason = "";
if (e.type == DioErrorType.CONNECT_TIMEOUT) {
// It occurs when url is opened timeout.
reason = "连接超时 ${e.message}";
} else if (e.type == DioErrorType.SEND_TIMEOUT) {
// It occurs when url is sent timeout.
reason = "请求超时 ${e.message}";
} else if (e.type == DioErrorType.RECEIVE_TIMEOUT) {
//It occurs when receiving timeout
reason = "响应超时 ${e.message}";
} else if (e.type == DioErrorType.RESPONSE) {
// When the server response, but with a incorrect status, such as 404, 503...
reason = "出现异常 ${e.message}";
} else if (e.type == DioErrorType.CANCEL) {
// When the request is cancelled, dio will throw a error with this type.
reason = "请求取消 ${e.message}";
} else {
//DEFAULT Default error type, Some other Error. In this case, you can read the DioError.error if it is not null.
reason = "未知错误 ${e.message}";
}
return reason;
}
}
import 'dart:convert';
import 'dart:io';
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:gm_flutter/commonModel/base/BaseUtil.dart';
import 'Api.dart';
import 'DioCookieManager.dart';
import 'DioInterceptor.dart';
const NET_COOKIE = "NET_COOKIE";
class DioUtil {
static final DioUtil _instance = DioUtil._init();
static Dio _dio;
static BaseOptions _options = getDefOptions();
static Map<String, dynamic> addHeadMap;
/// 是否是debug模式.
static bool _isDebug = isDebug;
static DioUtil getInstance() {
return _instance;
}
factory DioUtil() {
return _instance;
}
static var interceptor = InterceptorsWrapper();
DioUtil._init() {
_dio = new Dio(_options);
_dio.interceptors.add(DioInterceptorManager.getInstance().getIntercept());
_dio.interceptors.add(DioCookieManager.getInstance().getCookieManager());
}
void clearCookie() {
DioCookieManager.getInstance().clearCookie();
}
void setProxy(String proxy) {
_dio = new Dio(_options);
_dio.interceptors.add(DioInterceptorManager.getInstance().getIntercept());
_dio.interceptors.add(DioCookieManager.getInstance().getCookieManager());
(_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(client) {
client.findProxy = (url) {
return 'PROXY $proxy:8888';
};
};
}
Dio getDio() {
return _dio;
}
static BaseOptions getDefOptions() {
BaseOptions options = BaseOptions();
options.connectTimeout = 10 * 1000;
options.receiveTimeout = 20 * 1000;
options.responseType = ResponseType.plain;
Map<String, dynamic> headers = Map<String, dynamic>();
headers['Accept'] = 'application/json';
headers['version'] = '1.0.0';
options.headers = headers;
options.baseUrl = Api.getInstance().getBaseUrl() + "/";
return options;
}
}
/*
* @author lsy
* @date 2019-09-05
**/
import 'package:flutter_common/Annotations/anno/ServerEntity.dart';
@ServerEntity()
class SimpleResponce {
int error;
String message;
Null extra;
Data data;
SimpleResponce({this.error, this.message, this.extra, this.data});
SimpleResponce.fromJson(Map<String, dynamic> json) {
error = json['error'];
message = json['message'];
extra = json['extra'];
data = json['data'] != null ? new Data.fromJson(json['data']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['error'] = this.error;
data['message'] = this.message;
data['extra'] = this.extra;
if (this.data != null) {
data['data'] = this.data.toJson();
}
return data;
}
}
class Data {
int error;
String message;
Data({this.error, this.message});
Data.fromJson(Map<String, dynamic> json) {
error = json['error'];
message = json['message'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['error'] = this.error;
data['message'] = this.message;
return data;
}
}
/*
* @author lsy
* @date 2019-10-18
**/
import 'package:flutter/material.dart';
class DialogRouter extends PageRouteBuilder {
final Widget page;
DialogRouter(this.page)
: super(
opaque: false,
pageBuilder: (context, animation, secondaryAnimation) => page,
transitionsBuilder:
(context, animation, secondaryAnimation, child) {
return child;
});
}
/*
* @author lsy
* @date 2020/5/20
**/
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter_common/commonModel/picker/base/BaseCenterPicker.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
class TwoTextPicker implements ICenterPicker {
final String title;
final String content1;
final String content2;
VoidCallback dismissCall;
TwoTextPicker(this.title, this.content1, this.content2);
@override
Widget build(BuildContext context, int alp) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Color.fromARGB(alp, 255, 255, 255),
),
width: 285,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 16),
child: Text(
title,
textScaleFactor: 1.0,
style: TextStyle(
decoration: TextDecoration.none,
fontSize: 16,
color: Color.fromARGB(alp, 40, 40, 40),
fontStyle: FontStyle.normal,
fontWeight: FontWeight.w600),
),
),
Container(
margin: EdgeInsets.only(top: 18),
child: baseText(content1, 14, Color.fromARGB(alp, 102, 102, 102)),
),
Container(
margin: EdgeInsets.only(top: 12),
child: baseText(content2, 14, Color.fromARGB(alp, 102, 102, 102)),
),
Container(
height: 18,
),
baseDivide(0),
InkWell(
onTap: () {
dismissCall();
},
child: Container(
width: double.maxFinite,
height: 48,
alignment: Alignment.center,
child: baseText("确定", 16, Color.fromARGB(alp, 32, 189, 187)),
),
)
],
),
);
}
@override
void dispose() {}
@override
void initState(dismissCall, BuildContext context) {
this.dismissCall = dismissCall;
}
}
/*
* @author lsy
* @date 2019-10-18
**/
import 'package:flutter/material.dart';
import 'package:flutter_common/commonModel/view/iOSLoading.dart';
import 'base/DialogRouter.dart';
Future popLoadingDialogText(BuildContext context, bool canceledOnTouchOutside,
String text, ChangeNotifier dismiss) {
return Navigator.push(context,
DialogRouter(LoadingDialog(canceledOnTouchOutside, text, dismiss)));
}
class LoadingDialog extends StatefulWidget {
LoadingDialog(this.canceledOnTouchOutside, this.text, this.dismiss) : super();
///点击背景是否能够退出
final bool canceledOnTouchOutside;
final String text;
final ChangeNotifier dismiss;
@override
State<StatefulWidget> createState() => LoadingDialogState();
}
class LoadingDialogState extends State<LoadingDialog> {
@override
void initState() {
super.initState();
widget.dismiss.addListener(() {
if (widget.dismiss != null) {
Navigator.pop(context);
widget.dismiss.dispose();
}
});
}
@override
Widget build(BuildContext context) {
return Center(
child: new Material(
///背景透明
color: Colors.transparent,
///保证控件居中效果
child: Stack(
children: <Widget>[
GestureDetector(
///点击事件
onTap: () {
if (widget.canceledOnTouchOutside) {
Navigator.pop(context);
}
},
),
_dialog()
],
)),
);
}
Widget _dialog() {
return new Center(
///弹框大小
child: new Container(
width: 120.0,
height: 120.0,
child: new Container(
///弹框背景和圆角
decoration: ShapeDecoration(
color: Colors.black,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(8.0),
),
),
),
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new MyCupertinoActivityIndicator(
backColor: Colors.white,
),
new Padding(
padding: const EdgeInsets.only(
top: 20.0,
),
child: new Text(
widget.text,
style: new TextStyle(fontSize: 16.0, color: Colors.white),
),
),
],
),
),
),
);
}
}
/*
* @author lsy
* @date 2020/5/19
**/
import 'package:flutter/material.dart';
class BaseMenuListener extends ChangeNotifier {
bool isShow = false;
void show() {
isShow = true;
notifyListeners();
}
void hide() {
isShow = false;
notifyListeners();
}
void reverse() {
isShow = !isShow;
notifyListeners();
}
}
/*
* @author lsy
* @date 2020/5/19
**/
import 'package:flutter/cupertino.dart';
import 'package:flutter_common/commonModel/live/LiveData.dart';
import 'BaseMenuListener.dart';
class BasePopMenu extends StatefulWidget {
final double leftPos;
final double topPos;
final double width;
final double height;
final int maxHeight;
final Widget child;
final BaseMenuListener listener;
BasePopMenu(
{this.leftPos,
this.topPos,
this.maxHeight,
this.width,
this.height,
this.child,
this.listener});
@override
State<StatefulWidget> createState() {
return BasePopMenuState();;
}
}
class BasePopMenuState extends State<BasePopMenu>
with TickerProviderStateMixin {
Animation<double> animation;
AnimationController animationController;
LiveData<double> _liveData = LiveData();
bool isOpen = false;
@override
void initState() {
super.initState();
animationController = new AnimationController(
duration: const Duration(milliseconds: 300), vsync: this)
..addListener(() {
_liveData.notifyView(animation.value * widget.maxHeight);
});
animation = new Tween(begin: 0.0, end: 1.0).animate(animationController);
widget.listener.addListener(() {
if(widget.listener.isShow){
animationController.forward();
}else{
animationController.reverse();
}
});
}
@override
Widget build(BuildContext context) {
return Positioned(
left: widget.leftPos,
top: widget.topPos,
width: widget.width,
height: widget.height,
child: StreamBuilder(
stream: _liveData.stream,
initialData: 0.0,
builder: (c, data) {
return Container(
height: data.data,
child: widget.child,
);
},
));
}
@override
void dispose() {
_liveData.dispost();
animationController.dispose();
super.dispose();
}
}
/*
* @author lsy
* @date 2020/5/22
**/
import 'dart:async';
class RxDispose {
List<StreamSubscription> rx;
RxDispose() {
rx = List();
}
void addDispose(StreamSubscription streamSubscription) {
rx.add(streamSubscription);
}
void dispose() {
rx.forEach((element) {
element.cancel();
});
}
}
extension StreamSubscriptionExt on StreamSubscription {
StreamSubscription addToDispose(RxDispose rxDispose) {
rxDispose.addDispose(this);
return this;
}
}
/*
* @author lsy
* @date 2020/6/4
**/
class SingleNotify {
static SingleNotify _notify;
static SingleNotify instance() {
if (_notify == null) {
_notify = SingleNotify._();
}
return _notify;
}
SingleNotify._() {}
}
/*
* @author lsy
* @date 2020/5/22
**/
import 'package:flutter/material.dart';
import 'package:gm_flutter/commonModel/view/ActivePage.dart';
class DartUtil {
//为了导包
}
extension WidgetExt on Widget {
Widget margin(EdgeInsets edgeInsets, double width, double height) {
return Container(
width: width,
height: height,
margin: edgeInsets,
child: this,
);
}
Widget padding(EdgeInsets edgeInsets, double width, double height) {
return Container(
width: width,
height: height,
padding: edgeInsets,
child: this,
);
}
Widget gestureDetector(VoidCallback onTap) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: onTap,
child: this,
);
}
Widget minColumn(List<Widget> list) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: list,
);
}
Widget toActive() {
return ActivePage(this);
}
}
extension StringExt on String {
bool isPhone() {
return new RegExp(
'^((13[0-9])|(15[^4])|(166)|(17[0-8])|(18[0-9])|(19[8-9])|(147,145))\\d{8}\$')
.hasMatch(this);
}
}
/*
* @author lsy
* @date 2019-10-21
**/
import 'dart:isolate';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
class IsolateUtil {
static ReceivePort receivePort = ReceivePort();
static Future<T> paseJsonByIsolate<T>(Function function) async {
// 通过spawn新建一个isolate,并绑定静态方法
await Isolate.spawn(dataLoader, receivePort.sendPort);
// 获取新isolate的监听port
SendPort sendPort = await receivePort.first;
// 调用sendReceive自定义方法
return await sendReceive(sendPort, function);
}
// isolate的绑定方法
static dataLoader(SendPort sendPort) async {
// 创建监听port,并将sendPort传给外界用来调用
ReceivePort receivePort = ReceivePort();
sendPort.send(receivePort.sendPort);
// 监听外界调用
await for (var msg in receivePort) {
SendPort callbackPort = msg[0];
Function function = msg[1];
callbackPort.send(function());
}
}
// 创建自己的监听port,并且向新isolate发送消息
static Future sendReceive(SendPort sendPort, Function function) {
ReceivePort receivePort = ReceivePort();
sendPort.send([receivePort.sendPort, function]);
// 接收到返回值,返回给调用者
return receivePort.first;
}
}
/*
* @author lsy
* @date 2020/5/29
**/
import 'dart:convert';
import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';
const MD5KEY="aYMX5Wk7Cu";
class MD5Util {
static String generateMd5(String data) {
var content = new Utf8Encoder().convert(data);
var digest = md5.convert(content);
// 这里其实就是 digest.toString()
return hex.encode(digest.bytes);
}
}
/*
* @author lsy
* @date 2020/6/1
**/
class NumberUtil {
static String formatNum(double num, int postion) {
if ((num.toString().length - num.toString().lastIndexOf(".") - 1) <
postion) {
//小数点后有几位小数
return num.toStringAsFixed(postion)
.substring(0, num.toString().lastIndexOf(".") + postion + 1)
.toString();
} else {
return num.toString()
.substring(0, num.toString().lastIndexOf(".") + postion + 1)
.toString();
}
}
}
/*
* @author lsy
* @date 2020/5/22
**/
import 'package:flutter_common/commonModel/toast/NativeToast.dart';
import 'package:flutter_common/commonModel/toast/toast.dart';
class PrintUtil {
static void printBug(err) {
print(err.toString());
NativeToast.showNativeToast("网络错误");
}
}
/*
* @author lsy
* @date 2020/5/14
**/
import 'package:flutter/material.dart';
class WidgetUtil {
static RelativeRect buttonMenuPosition(BuildContext c) {
final RenderBox bar = c.findRenderObject();
final RenderBox overlay = Overlay.of(c).context.findRenderObject();
final RelativeRect position = RelativeRect.fromRect(
Rect.fromPoints(
bar.localToGlobal(bar.size.bottomRight(Offset.zero), ancestor: overlay),
bar.localToGlobal(bar.size.bottomRight(Offset.zero), ancestor: overlay),
),
Offset.zero & overlay.size,
);
return position;
}
static RelativeRect buttonLeftMenuPosition(BuildContext c) {
final RenderBox bar = c.findRenderObject();
final RenderBox overlay = Overlay.of(c).context.findRenderObject();
final RelativeRect position = RelativeRect.fromRect(
Rect.fromPoints(
bar.localToGlobal(bar.size.bottomLeft(Offset.zero), ancestor: overlay),
bar.localToGlobal(bar.size.bottomLeft(Offset.zero), ancestor: overlay),
),
Offset.zero & overlay.size,
);
return position;
}
}
/*
* @author lsy
* @date 2020/6/4
**/
import 'package:flutter/cupertino.dart';
class ActivePage extends StatefulWidget {
Widget child;
ActivePage(this.child);
@override
State<StatefulWidget> createState() {
return ActiveState();
}
}
class ActiveState extends State<ActivePage> with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
return widget.child;
}
}
/*
* @author lsy
* @date 2020/5/20
**/
import 'package:flutter/cupertino.dart';
import 'DarkToastView.dart';
class DarkToastManager {
static OverlayEntry showDartToast(
BuildContext context, Widget left, String right) {
OverlayEntry overlayEntry = OverlayEntry(builder: (c) {
return DartToastView(
leftChild: left,
rightText: right,
);
});
Overlay.of(context).insert(overlayEntry);
return overlayEntry;
}
}
/*
* @author lsy
* @date 2020/5/20
**/
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
class DartToastView extends StatelessWidget {
final Widget leftChild;
final String rightText;
DartToastView({this.leftChild, this.rightText});
@override
Widget build(BuildContext context) {
return Container(
height: 43,
alignment: Alignment.center,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Color(0xcc1D2530)),
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.only(left: 19, top: 13.5, bottom: 13.5),
width: 16,
height: 16,
child: leftChild,
),
Container(
width: 8,
height: 1,
),
baseText(rightText, 13, Colors.white),
Container(
width: 19,
height: 1,
)
],
)),
);
}
}
/*
* @author lsy
* @date 2020/5/20
**/
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_svg/flutter_svg.dart';
const Duration _kExpand = Duration(milliseconds: 200);
class ExpansionLayout extends StatefulWidget {
const ExpansionLayout({
Key key,
this.leading,
@required this.title,
this.subtitle,
this.backgroundColor,
this.onExpansionChanged,
this.children = const <Widget>[],
this.trailing,
this.initiallyExpanded = false,
}) : assert(initiallyExpanded != null),
super(key: key);
final Widget leading;
final Widget title;
final Widget subtitle;
final ValueChanged<bool> onExpansionChanged;
final List<Widget> children;
final Color backgroundColor;
final Widget trailing;
final bool initiallyExpanded;
@override
_ExpansionTileState createState() => _ExpansionTileState();
}
class _ExpansionTileState extends State<ExpansionLayout>
with SingleTickerProviderStateMixin {
static final Animatable<double> _easeOutTween =
CurveTween(curve: Curves.easeOut);
static final Animatable<double> _easeInTween =
CurveTween(curve: Curves.easeIn);
static final Animatable<double> _halfTween =
Tween<double>(begin: 0.0, end: 0.5);
final ColorTween _borderColorTween = ColorTween();
final ColorTween _headerColorTween = ColorTween();
final ColorTween _backgroundColorTween = ColorTween();
AnimationController _controller;
Animation<double> _iconTurns;
Animation<double> _heightFactor;
Animation<Color> _borderColor;
Animation<Color> _headerColor;
Animation<Color> _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));
_backgroundColor =
_controller.drive(_backgroundColorTween.chain(_easeOutTween));
_isExpanded = PageStorage.of(context)?.readState(context) as bool ??
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>((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?? Color(0xffe5e5e5);
return Container(
decoration: BoxDecoration(
// color: _backgroundColor.value ?? Colors.transparent,
border: Border(
bottom: BorderSide(color: borderSideColor),
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTileTheme.merge(
contentPadding: EdgeInsets.only(),
textColor: _headerColor.value,
child: ListTile(
onTap: _handleTap,
leading: widget.leading,
title: widget.title,
subtitle: widget.subtitle,
trailing: widget.trailing ??
RotationTransition(
turns: _iconTurns,
child: Container(
width: 15,
height: 16,
child: SvgPicture.asset("images/bottom_arrow_black.svg"),
),
),
),
),
ClipRect(
child: Align(
heightFactor: _heightFactor.value,
child: child,
),
),
],
),
);
}
@override
void didChangeDependencies() {
final ThemeData theme = Theme.of(context);
_borderColorTween.begin=Color(0xffe5e5e5);
_borderColorTween.end = Colors.transparent;
_headerColorTween
..begin = theme.textTheme.subtitle1.color
..end = theme.accentColor;
_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),
);
}
}
/*
* @author lsy
* @date 2020/5/28
**/
import 'package:flutter/material.dart';
class ImagesAnimation extends StatefulWidget {
final double w;
final double h;
final ImagesAnimationEntry entry;
final int durationSeconds;
ImagesAnimation(
{Key key, this.w: 80, this.h: 80, this.entry, this.durationSeconds: 3000})
: super(key: key);
@override
_InState createState() {
return _InState();
}
}
class _InState extends State<ImagesAnimation> with TickerProviderStateMixin {
AnimationController _controller;
Animation<int> _animation;
@override
void initState() {
super.initState();
_controller = new AnimationController(
vsync: this, duration: Duration(milliseconds: widget.durationSeconds))
..repeat();
_animation =
new IntTween(begin: widget.entry.lowIndex, end: widget.entry.highIndex)
.animate(_controller);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return new AnimatedBuilder(
animation: _animation,
builder: (BuildContext context, Widget child) {
String frame = _animation.value.toString();
if (frame.length == 1) {
frame = "0" + frame;
}
return new Image.asset(
"${widget.entry.basePath}${frame}.png",
gaplessPlayback: true, //避免图片闪烁
width: widget.w,
height: widget.h,
);
},
);
}
}
class ImagesAnimationEntry {
int lowIndex = 0;
int highIndex = 0;
String basePath;
ImagesAnimationEntry(this.lowIndex, this.highIndex, this.basePath);
}
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_boost/flutter_boost.dart';
import 'package:flutter_common/Annotations/anno/RouterCenter.dart';
import 'package:flutter_common/commonModel/util/WindowUtil.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
import 'DemoPage.dart';
import 'commonModel/base/BaseUtil.dart';
import 'commonModel/nav/NavigationService.dart';
NavigationService navigationService;
void main() {
navigationService = NavigationService();
WidgetsFlutterBinding.ensureInitialized();
FlutterError.onError = (FlutterErrorDetails details) async {
if (isDebug) {
FlutterError.dumpErrorToConsole(details);
Zone.root.handleUncaughtError(details.exception, details.stack);
Zone.current.handleUncaughtError(details.exception, details.stack);
} else {
Zone.current.handleUncaughtError(details.exception, details.stack);
}
};
runZonedGuarded(() {
WidgetsFlutterBinding.ensureInitialized();
runApp(
MyAppWidget(),
);
}, (Object error, StackTrace stack) {
//TODO
print("lsy EEEEEE ${error.toString()} ${stack.toString()}");
});
}
@RouterCenter()
class MyAppWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return MyApp();
}
}
class MyApp extends State<MyAppWidget> {
@override
void initState() {
super.initState();
FlutterBoost.singleton.registerPageBuilders({
'demoPage': (pageName, params, _) {
return DemoPage();
},
});
// FlutterBoost.singleton.addBoostContainerLifeCycleObserver((state, settings) {
// });
// FlutterBoost.singleton.addBoostNavigatorObserver(TestBoostNavigatorObserver());
}
@override
Widget build(BuildContext context) {
WindowUtil.setBarStatus(true);
return MaterialApp(
theme: ThemeData(),
builder: FlutterBoost.init(postPush: _onRoutePushed),
home: isDebug
? Container(
color: Colors.red,
)
: Container(
color: Colors.white,
child: Center(
child: loadingItem(),
),
));
}
void _onRoutePushed(
String pageName,
String uniqueId,
Map<String, dynamic> params,
Route<dynamic> route,
Future<dynamic> _,
) {}
}
// GENERATED CODE - DO NOT MODIFY BY HAND
// **************************************************************************
// RouterCenterGenerator
// **************************************************************************
//ClueRouterImpl is resign : true
import "package:gm_flutter/ClueModel/ClueRouterImpl.dart";
import "package:gm_flutter/ClueModel/ClueRouter.dart";
import "package:flutter_common/Annotations/RouterBaser.dart";
class RouterCenterImpl {
Map<String, RouterBaser> map;
factory RouterCenterImpl() => _sharedInstance();
static RouterCenterImpl _instance;
RouterCenterImpl._() {
if (map == null) {
map = new Map();
init();
} else {
throw Exception("too many RouterCenter instance!!! fix it ");
}
}
static RouterCenterImpl _sharedInstance() {
if (_instance == null) {
_instance = RouterCenterImpl._();
}
return _instance;
}
void init() {
map.putIfAbsent("ClueRouter", () => ClueRouterImpl());
}
RouterBaser getModel(String modelName) {
return map[modelName];
}
ClueRouter findClueRouter() {
if (map["ClueRouter"] == null) {
return null;
}
return map["ClueRouter"] as ClueRouter;
}
}
This diff is collapsed.
name: gm_flutter
description: A new flutter module project.
version: 1.0.0+1
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
# cupertino_icons: ^0.1.3
cached_network_image: ^2.2.0+1
flutter_boost:
git:
url: 'https://github.com/alibaba/flutter_boost.git'
ref: 'v1.17.1-hotfixes'
flutter_common:
git:
url: 'https://github.com/asd451398533/flutter_common.git'
ref: 'de509ebaf4724de7c70d05ea403dbe13ecc775ea'
#网络库
dio: ^3.0.0
dio_cookie_manager: ^1.0.0
#Rx编程
rxdart: ^0.24.0
#上拉下拉
pull_to_refresh: ^1.5.8
#获取文件夹/沙盒路径
path_provider: ^1.6.7
#权限
permission_handler: ^5.0.0
#轻量级存储
shared_preferences: ^0.5.7+1
dev_dependencies:
flutter_test:
sdk: flutter
source_gen: '>=0.8.0'
build_runner: ^1.9.0
flutter:
uses-material-design: true
module:
androidX: true
androidPackage: com.example.gm_flutter
iosBundleIdentifier: com.example.gmFlutter
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility that Flutter provides. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:gm_flutter/main.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(MyAppWidget());
// Verify that our counter starts at 0.
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
// Tap the '+' icon and trigger a frame.
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
// Verify that our counter has incremented.
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
});
}
#!/usr/bin/env bash
echo START
projectDir=`pwd`
rootFlutter=`which flutter`
rootDir=${rootFlutter%/*}
dif=debug
#dif=release
message=增加他人的专家页面
#====clean
cd ${projectDir}
${rootFlutter} clean
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
${rootFlutter} packages get
#cd ${projectDir}/android
#./gradlew assembleRelease
rm -rf ${projectDir}/build
flutter build apk --release --target-platform android-arm
#rm -rf /Users/apple/lsy/aar_update/
#mkdir /Users/apple/lsy/aar_update/
#rm -rf /Users/apple/lsy/update/
#mkdir /Users/apple/lsy/update/
#mkdir /Users/apple/lsy/update/android${message}${dif}/
#mkdir /Users/apple/lsy/update/ios${message}${dif}/
#cp -r /Users/apple/lsy/gm_flutter/build/app/outputs/aar/app-release.aar /Users/apple/lsy/aar_update/app.zip
#cd /Users/apple/lsy/aar_update/
cp -r /Users/apple/lsy/gm_flutter/build/host/outputs/apk/release/app-release.apk /Users/apple/lsy/gm_flutter/build/host/outputs/apk/release/app-release.zip
unzip ${projectDir}/build/host/outputs/apk/release/app-release.zip -d ${projectDir}/build/host/outputs/apk/release
#cp -r /Users/apple/lsy/gm_flutter/build/host/outputs/apk/release/app-release/lib/armeabi-v7a/* /Users/apple/lsy/update/androd${message}${dif}/
rm -rf /Users/apple/Downloads/PLLL/app/libs/armeabi-v7a/*
cp -r /Users/apple/lsy/gm_flutter/build/host/outputs/apk/release/lib/armeabi-v7a/* /Users/apple/Downloads/PLLL/app/libs/armeabi-v7a/
#cd ${projectDir}
#flutter build ios --release --no-codesign
#cp -r /Users/apple/lsy/gmalpha_flutter/ios/Flutter/App.framework /Users/apple/lsy/update/ios${message}${dif}/
#cp -r /Users/apple/lsy/gmalpha_flutter/ios/Flutter/Flutter.framework /Users/apple/lsy/update/ios${message}${dif}/
#cd /Users/apple/lsy/update/
#open .
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment