Commit b14e5400 authored by 朱璇's avatar 朱璇

Merge branch 'test' of git.wanmeizhensuo.com:linshengyu/gm_flutter into zx/gmFlutter

parents acad4994 2c64c381
class CallBackCompareItem {
checkedItem(int id) {}
}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_common/commonModel/toast/NativeToast.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlansCompareFeed.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
import 'package:gm_flutter/commonModel/base/BaseState.dart';
class PlansCompareFeedItemView extends StatelessWidget {
import 'CallBackCompareItem.dart';
class PlansCompareFeedItemView extends StatefulWidget {
Plans plan;
int groupValue = 1;
CallBackCompareItem compareItem;
Set<int> _setCompare;
PlansCompareFeedItemView(this.plan, this.compareItem, this._setCompare);
@override
State<StatefulWidget> createState() => _PlansCompareFeedItemViewState();
}
class _PlansCompareFeedItemViewState
extends BaseState<PlansCompareFeedItemView> {
ImageIcon _checked = ImageIcon(AssetImage("assets/icon_compare_select.png"));
PlansCompareFeedItemView(this.plan);
ImageIcon _unchecked =
ImageIcon(AssetImage("assets/icon_compare_unselect.png"));
ImageIcon _icon = ImageIcon(AssetImage("assets/icon_compare_unselect.png"));
@override
Widget build(BuildContext context) {
return Container(child: getItem());
Widget buildItem(BuildContext context) {
return Container(
margin: EdgeInsets.only(left: 15, right: 15), child: getItem());
}
getItem() {
if (plan.planType == 1) {
if (widget.plan.planType == 2) {
return getFirstLevelItem();
} else {
return getSecondLevelItem();
......@@ -26,21 +45,19 @@ class PlansCompareFeedItemView extends StatelessWidget {
width: double.maxFinite,
height: 90,
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(left: 15, right: 15, top: 20, bottom: 20),
padding: EdgeInsets.only(top: 20, bottom: 20),
child: Row(
children: <Widget>[
Radio(
value: 1,
groupValue: groupValue,
onChanged: (value) {
groupValue = value;
}),
IconButton(
icon: _icon,
onPressed: () => onClickCheckBox(_icon),
),
Container(
margin: EdgeInsets.only(left: 15, right: 15),
child: ClipRRect(
borderRadius: BorderRadius.circular(2.0),
child: Image.network(
plan.projectImage,
widget.plan.projectImage,
width: 50,
height: 50,
fit: BoxFit.fill,
......@@ -56,42 +73,20 @@ class PlansCompareFeedItemView extends StatelessWidget {
margin: EdgeInsets.only(top: 2, bottom: 5),
child: Row(
children: <Widget>[
Text(
plan.name,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
color: Color(0xFF282828)),
maxLines: 1,
),
Text(
"好评率 ",
style:
TextStyle(fontSize: 11, color: Color(0xFF282828)),
maxLines: 1,
),
Text(
plan.positiveRate,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
color: Color(0xFFFF5963)),
maxLines: 1,
),
baseText(widget.plan.name, 14, Color(0xFF282828),
bold: true),
baseText(" 好评率 ", 11, Color(0xFF282828)),
baseText(widget.plan.positiveRate, 14, Color(0xFFFF5963),
bold: true),
],
),
),
Row(
children: <Widget>[
Text(
'¥${plan.minPrice}-${plan.maxPrice}',
style: TextStyle(fontSize: 13, color: Color(0xFFFF5963)),
),
Text(
"销量${plan.salesCount}",
style: TextStyle(fontSize: 11, color: Color(0xFF282828)),
maxLines: 1,
)
baseText('¥${widget.plan.minPrice}-${widget.plan.maxPrice}',
13, Color(0xFFFF5963)),
baseText(" 销量${widget.plan.salesCount}", 11,
Color(0xFF282828))
],
)
],
......@@ -104,58 +99,55 @@ class PlansCompareFeedItemView extends StatelessWidget {
getSecondLevelItem() {
return Container(
width: double.maxFinite,
height: 77,
alignment: Alignment.centerLeft,
margin: EdgeInsets.only(left: 15, right: 15),
child: Row(
children: <Widget>[
Radio(
value: 1,
groupValue: groupValue,
onChanged: (value) {
groupValue = value;
}),
Container(
margin: EdgeInsets.only(left: 15.0),
height: 77,
margin: EdgeInsets.only(right: 15.0),
alignment: Alignment.centerLeft,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 13.0, bottom: 12),
child: Text(
plan.name,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
color: Color(0xFF282828)),
maxLines: 1,
),
),
Row(
children: <Widget>[
Text(
'¥${plan.minPrice}-${plan.maxPrice}',
style: TextStyle(fontSize: 13, color: Color(0xFFFF5963)),
),
Container(
alignment: Alignment.centerRight,
child: Text(
"指导价:¥${plan.guidePrice}",
style:
TextStyle(fontSize: 11, color: Color(0xFF282828)),
maxLines: 1,
),
),
],
)
],
child: IconButton(
icon: _icon,
onPressed: () => onClickCheckBox(_icon),
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 13.0, bottom: 12),
child: baseText(widget.plan.name, 14, Color(0xFF282828),
bold: true),
),
Row(
children: <Widget>[
baseText('¥${widget.plan.minPrice}-${widget.plan.maxPrice}',
13, Color(0xFFFF5963)),
Container(
width: 160,
alignment: Alignment.centerRight,
child: baseText("指导价:¥${widget.plan.guidePrice}", 11,
Color(0xFF282828))),
],
),
],
)
],
),
);
}
onClickCheckBox(ImageIcon icon) {
if (icon == _checked) {
_icon = _unchecked;
} else {
if (widget._setCompare.length == 2) {
NativeToast.showNativeToast("不许再选了两个够了!");
return;
}
_icon = _checked;
}
setState(() {
widget.compareItem.checkedItem(widget.plan.planId);
});
}
}
......@@ -10,33 +10,37 @@ import 'package:gm_flutter/ClueModel/server/entity/PlansCompareFeed.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
import 'package:gm_flutter/commonModel/base/BaseState.dart';
import 'CallBackCompareItem.dart';
import 'PlansCompareFeedItemView.dart';
class PlansCompareFeedPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => PlansCompareFeedState();
State<StatefulWidget> createState() => _PlansCompareFeedState();
}
class PlansCompareFeedState extends BaseState<PlansCompareFeedPage> {
PlansCompareFeedModel _model = new PlansCompareFeedModel();
class _PlansCompareFeedState extends BaseState<PlansCompareFeedPage>
implements CallBackCompareItem {
PlansCompareFeedModel _model;
Color _compareColor;
Set<int> _setCompare;
@override
void initState() {
super.initState();
_model = new PlansCompareFeedModel();
_model.init();
_compareColor = Color(0xFFCCCCCC);
_setCompare = Set();
}
@override
void dispose() {
_model.dispose();
super.dispose();
_model.dispose();
}
@override
Widget buildItem(BuildContext context) {}
@override
Widget build(BuildContext context) {
Widget buildItem(BuildContext context) {
return Scaffold(
appBar: baseAppBar(
title: "方案对比",
......@@ -50,31 +54,6 @@ class PlansCompareFeedState extends BaseState<PlansCompareFeedPage> {
);
}
getList(List<Plans> plans) {
return Stack(alignment: Alignment.bottomCenter, //指定未定位或部分定位widget的对齐方式
children: <Widget>[
ListView.builder(
itemCount: plans.length,
itemBuilder: (BuildContext context, int position) {
return PlansCompareFeedItemView(plans[position]);
}),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {},
child: Container(
margin:
EdgeInsets.only(left: 15, right: 15, top: 7.5, bottom: 7.5),
width: double.maxFinite,
height: 40,
decoration: BoxDecoration(
color: Color(0xff51CDC7),
borderRadius: BorderRadius.circular(20)),
alignment: Alignment.center,
child: baseText("对比", 14, Colors.white, bold: true),
))
]);
}
getBody() {
return StreamBuilder(
stream: _model.liveData.stream,
......@@ -96,4 +75,49 @@ class PlansCompareFeedState extends BaseState<PlansCompareFeedPage> {
},
);
}
getList(List<Plans> plans) {
return Stack(alignment: Alignment.bottomCenter, children: <Widget>[
ListView.builder(
itemCount: plans.length,
itemBuilder: (BuildContext context, int position) {
return PlansCompareFeedItemView(plans[position], this, _setCompare);
}),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => onClickCompare(),
child: Container(
margin: EdgeInsets.only(left: 15, right: 15, top: 7.5, bottom: 7.5),
width: double.maxFinite,
height: 40,
decoration: BoxDecoration(
color: _compareColor, borderRadius: BorderRadius.circular(20)),
alignment: Alignment.center,
child: baseText("对比", 14, Colors.white, bold: true),
))
]);
}
onClickCompare() {
if (_compareColor == Color(0xFFCCCCCC)) return;
setState(() {
print("onClickCompare=====_compareColor$_compareColor");
});
}
@override
checkedItem(int id) {
if (_setCompare.contains(id)) {
_setCompare.remove(id);
} else {
_setCompare.add(id);
}
setState(() {
if (_setCompare.length == 2) {
_compareColor = Color(0xff51CDC7);
} else {
_compareColor = Color(0xFFCCCCCC);
}
});
}
}
......@@ -6,52 +6,48 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:gm_flutter/ClueModel/server/entity/ProjectDetailsItem.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
class ProjectDetailsItemView extends StatelessWidget {
Groups listData;
List<Widget> listAttrs = [];
ProjectDetailsItemView(this.listData);
ProjectDetailsItemView(this.listData) {
init();
}
@override
Widget build(BuildContext context) {
List<Widget> tiles = [];
init() {
for (var item in listData.attrs) {
tiles.add(getItem(item));
listAttrs.add(getAttrItem(item));
}
var column = Column(
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 15.0),
margin: EdgeInsets.only(bottom: 16.0),
alignment: Alignment.centerLeft,
width: double.maxFinite,
height: 55,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/bg_project_detail_item.png"),
fit: BoxFit.cover)),
child: Text(
listData.name,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Color(0xFF000000),
fontSize: 15.0,
),
),
),
padding: EdgeInsets.only(left: 15.0),
margin: EdgeInsets.only(bottom: 16.0),
alignment: Alignment.centerLeft,
height: 55,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/bg_project_detail_item.png"),
fit: BoxFit.cover)),
child: baseText(listData.name, 15, Colors.black, bold: true)),
Column(
children: tiles,
children: listAttrs,
),
SizedBox(
height: 5,
)
],
);
return Container(
margin: EdgeInsets.only(bottom: 5),
child: column,
);
}
getItem(Attrs attrs) {
var row = Container(
getAttrItem(Attrs attrs) {
return Container(
width: double.maxFinite,
margin: EdgeInsets.only(bottom: 25, left: 15, right: 15),
child: Row(
......@@ -60,29 +56,13 @@ class ProjectDetailsItemView extends StatelessWidget {
margin: EdgeInsets.only(right: 25.0),
alignment: Alignment.centerLeft,
width: 78,
child: Text(
attrs.attrName,
style: TextStyle(
color: Color(0xFF999999),
fontSize: 13.0,
),
),
child: baseText(attrs.attrName, 13, Color(0xFF999999)),
),
Container(
alignment: Alignment.centerLeft,
child: Text(
attrs.attrValue,
style: TextStyle(
color: Color(0xFF282828),
fontSize: 14.0,
),
),
),
alignment: Alignment.centerLeft,
child: baseText(attrs.attrValue, 14, Color(0xFF282828))),
],
),
);
return Container(
child: row,
);
}
}
......@@ -14,15 +14,16 @@ import '../../server/entity/ProjectDetailsItem.dart';
class ProjectDetailsPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => ProjectDetailsState();
State<StatefulWidget> createState() => _ProjectDetailsState();
}
class ProjectDetailsState extends BaseState<ProjectDetailsPage> {
ProjectDetailsModel _model = new ProjectDetailsModel();
class _ProjectDetailsState extends BaseState<ProjectDetailsPage> {
ProjectDetailsModel _model;
@override
void initState() {
super.initState();
_model = new ProjectDetailsModel();
_model.init();
}
......@@ -33,10 +34,7 @@ class ProjectDetailsState extends BaseState<ProjectDetailsPage> {
}
@override
Widget buildItem(BuildContext context) {}
@override
Widget build(BuildContext context) {
Widget buildItem(BuildContext context) {
return Scaffold(
appBar: baseAppBar(
title: "项目说明",
......
/*
* @author lsy
* @date 2020/7/4
**/
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:gm_flutter/ClueModel/page/levelOne/LevelOneListModel.dart';
import 'package:gm_flutter/ClueModel/server/entity/LevelOneFeedList.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
import 'package:gm_flutter/commonModel/bean/Pair.dart';
import 'package:gm_flutter/commonModel/eventbus/SimpleEventBus.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'LevelOneItem.dart';
class LevelOneList extends StatefulWidget {
double topHeight;
int planId;
String tabName;
LevelOneList(this.planId, this.tabName, this.topHeight);
@override
State<StatefulWidget> createState() => LevelOneListState();
}
class LevelOneListState extends State<LevelOneList>
with AutomaticKeepAliveClientMixin{
LevelOneListModel _model = LevelOneListModel();
RefreshController refreshController = RefreshController();
Function(String str) refresh;
@override
void initState() {
super.initState();
_model.plan_id = widget.planId;
_model.tab_type = widget.tabName;
_model.refreshView(true);
refresh = (str) {
_model.stateLive.notifyView(LOADING);
_model.refreshView(true);
};
SimpleEventBus.instance().resignEvent("LevelOneList", refresh);
}
@override
void dispose() {
refreshController.dispose();
_model.dispose();
SimpleEventBus.instance().unResignEvent("LevelOneList", refresh);
super.dispose();
}
@override
Widget build(BuildContext context) {
super.build(context);
return baseStateView(MediaQuery.of(context).size.width,
MediaQuery.of(context).size.height, _model.stateLive, pages(), () {
_model.refreshView(true);
}, paddingTop: widget.topHeight);
}
Widget pages() {
return baseRefreshView(refreshController, () {}, null, null,
customScrollView: CustomScrollView(
// physics: NeverScrollableScrollPhysics(),
physics: ClampingScrollPhysics(),
// shrinkWrap: true,
slivers: <Widget>[
// SliverOverlapInjector(
// handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
// ),
StreamBuilder<List<Cards>>(
stream: _model.cardsLive.stream,
initialData: _model.cardsLive.data ?? [],
builder: (c, data) {
if (data.data.isEmpty && _model.page > 1) {
refreshController.loadNoData();
} else {
refreshController.loadComplete();
}
return SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
if(index==_model.data.length){
return Container(
height: 40,
color: Color(0xffF7F6FA),
);
}
return LevelOneItem(_model.data[index]);
},
childCount: _model.data.length+1,
),
);
},
),
StreamBuilder<List<Cards>>(
stream: _model.cardsLive.stream,
initialData: _model.data ?? [],
builder: (c, data) {
double totalHeight = 0;
_model.data.forEach((element) {
totalHeight += LevelOneItem.getCardTypeHeight(element);
});
double height = MediaQuery.of(context).size.height -
40 -
widget.topHeight -
totalHeight;
return SliverToBoxAdapter(
child: Container(
height: height < 0 ? 0 : height,
),
);
},
),
],
), onLoading: () {
_model.loadMore();
}, pullDown: false, pullUp: true);
}
@override
bool get wantKeepAlive => true;
}
/*
* @author lsy
* @date 2020/7/4
**/
import 'package:flutter_common/commonModel/live/BaseModel.dart';
import 'package:flutter_common/commonModel/live/LiveData.dart';
import 'package:flutter_common/commonModel/toast/NativeToast.dart';
import 'package:gm_flutter/ClueModel/server/api/ClueApi.serv.dart';
import 'package:gm_flutter/ClueModel/server/entity/LevelOneFeedList.dart';
import 'package:gm_flutter/commonModel/bean/Pair.dart';
import 'package:gm_flutter/commonModel/net/DioUtil.dart';
import 'package:gm_flutter/commonModel/rx/RxDispose.dart';
import 'package:gm_flutter/commonModel/util/PrintUtil.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
class LevelOneListModel extends BaseModel {
int plan_id;
String tab_type;
int page = 1;
LiveData<int> stateLive = LiveData();
LiveData<List<Cards>> cardsLive = LiveData();
List<Cards> data = [];
RxDispose rxDispose = RxDispose();
void refreshView(bool clear, {RefreshController refreshListener}) {
if (clear) {
data.clear();
page = 1;
}
ClueApiImpl.getInstance()
.getLevelOneList(
DioUtil.getInstance().getDio(), plan_id, tab_type, page)
.listen((event) {
if (event.error == 0) {
if ((event.data.cards == null || event.data.cards.isEmpty) &&
page == 1) {
stateLive.notifyView(EMPTY);
} else {
data.addAll(event.data.cards);
cardsLive.notifyView(data);
stateLive.notifyView(ENDLOADING);
}
} else {
NativeToast.showNativeToast(event.message);
stateLive.notifyView(FAIL);
}
})
.addToDispose(rxDispose)
.onError((err) {
PrintUtil.printBug(err);
stateLive.notifyView(FAIL);
});
}
@override
void dispose() {
rxDispose.dispose();
stateLive.dispost();
cardsLive.dispost();
}
void loadMore() {
page++;
refreshView(false);
}
}
......@@ -5,8 +5,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_common/commonModel/live/BaseModel.dart';
import 'package:flutter_common/commonModel/live/LiveData.dart';
import 'package:flutter_common/commonModel/toast/NativeToast.dart';
import 'package:gm_flutter/ClueModel/server/api/ClueApi.serv.dart';
import 'package:gm_flutter/ClueModel/server/entity/LevelOneFeedList.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlanOverViewBean.dart';
import 'package:gm_flutter/commonModel/GMBase.dart';
import 'package:gm_flutter/commonModel/bean/Pair.dart';
import 'package:gm_flutter/commonModel/rx/RxDispose.dart';
......@@ -14,92 +16,43 @@ import 'package:gm_flutter/commonModel/util/PrintUtil.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
class LevelOneModel extends BaseModel {
LiveData<double> appBarLive = LiveData();
LiveData<List<String>> rectLive = LiveData();
LiveData<List<String>> explainLive = LiveData();
LiveData<bool> showTab = LiveData();
LiveData<int> topIndexLive = new LiveData();
LiveData<double> topScrollLive = new LiveData();
LiveData<bool> loadingLive = LiveData();
RxDispose rxDispose = RxDispose();
LiveData<Pair<int, List<Cards>>> cardsLive = LiveData();
LiveData<int> stateLive = LiveData();
LiveData<double> textLive = LiveData();
Map<int, List<Cards>> data = new Map();
List list = ["plan", "hospital", "doctor", "diary"];
List pageList = [1, 1, 1, 1];
List pageHeightList = [118, 149, 118, 118];
RxDispose rxDispose = RxDispose();
void refreshView(bool clear, {RefreshController refreshListener}) {
Future.delayed(Duration(seconds: 1), () {
Cards cards = Cards(
cardType: "plan",
plan: Plan(planName: "ww", minPrice: "50", maxPrice: "500"));
List<Cards> a = [
cards,
cards,
cards,
cards,
cards,
cards,
cards,
cards,
cards,
cards,
cards,
cards,
];
List<Cards> b = [cards];
print("INDEX ${currentIndex}");
if (currentIndex == 1) {
data[currentIndex] = b;
} else {
data[currentIndex] = a;
}
List<Tabs> tabsList = [];
int plan_id = 0;
PlanOverData planoverItem;
cardsLive.notifyView(Pair(ENDLOADING, data));
});
int index = currentIndex;
if (clear) {
data.clear();
pageList = [1, 1, 1, 1];
}
void init(VoidCallback callback) {
ClueApiImpl.getInstance()
.getLevelOneList(
DioUtil.getInstance().getDio(), 123, list[index], pageList[index])
.listen((event) {})
.getPlanOverView(DioUtil.getInstance().getDio(), plan_id)
.listen((event) {
if (event.error == 0) {
planoverItem = event.data;
tabsList = event.data.tabs;
stateLive.notifyView(ENDLOADING);
callback();
} else {
NativeToast.showNativeToast(event.message);
stateLive.notifyView(FAIL);
}
})
.addToDispose(rxDispose)
.onError((err) {
PrintUtil.printBug(err);
});
stateLive.notifyView(FAIL);
});
}
int currentIndex = 0;
@override
void dispose() {
showTab.dispost();
cardsLive.dispost();
appBarLive.dispost();
rectLive.dispost();
topIndexLive.dispost();
topScrollLive.dispost();
loadingLive.dispost();
}
void selectPage(int index) {
if (currentIndex == index) {
return;
}
currentIndex = index;
if (data[currentIndex] == null) {
cardsLive.notifyView(Pair(LOADING, null));
refreshView(true);
} else {
cardsLive.notifyView(Pair(ENDLOADING, data[currentIndex]));
}
stateLive.dispost();
textLive.dispost();
}
void loadMore() {
}
void selectTab(int index) {}
}
......@@ -6,8 +6,11 @@ import 'package:flutter/material.dart';
import 'package:gm_flutter/ClueModel/page/plan/PlanItem.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlanFeedBean.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
import 'package:gm_flutter/commonModel/bean/Pair.dart';
import 'package:gm_flutter/commonModel/eventbus/SimpleEventBus.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'TopListModel.dart';
class TopList extends StatefulWidget {
......@@ -20,14 +23,21 @@ class TopList extends StatefulWidget {
State<StatefulWidget> createState() => TopListState();
}
class TopListState extends State<TopList> {
class TopListState extends State<TopList>
with AutomaticKeepAliveClientMixin{
RefreshController refreshController = RefreshController();
TopListModel _model = TopListModel();
Function(String str) refresh;
@override
void initState() {
super.initState();
_model.getData(true);
refresh = (str) {
_model.stateLive.notifyView(LOADING);
_model.getData(true);
};
SimpleEventBus.instance().resignEvent("TopList", refresh);
print("${this} INIT");
}
......@@ -35,12 +45,14 @@ class TopListState extends State<TopList> {
void dispose() {
refreshController.dispose();
_model.dispose();
SimpleEventBus.instance().unResignEvent("TopList", refresh);
print("${this} QUIT");
super.dispose();
}
@override
Widget build(BuildContext context) {
super.build(context);
return baseStateView(MediaQuery.of(context).size.width,
MediaQuery.of(context).size.height, _model.stateLive, home(), () {
_model.getData(true);
......@@ -54,14 +66,18 @@ class TopListState extends State<TopList> {
physics: ClampingScrollPhysics(),
// shrinkWrap: true,
slivers: <Widget>[
SliverOverlapInjector(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
SliverToBoxAdapter(
child: Container(
height: widget.topHeight,
),
),
// extend.SliverOverlapInjector(
// handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
// ),
StreamBuilder<List<Plans>>(
stream: _model.datasLive.stream,
initialData: _model.datas ?? [],
builder: (c, data) {
print("LLDATA ${data.data}");
if (data.data.isEmpty && _model.page > 1) {
refreshController.loadNoData();
} else {
......@@ -84,8 +100,8 @@ class TopListState extends State<TopList> {
builder: (c, data) {
double height = MediaQuery.of(context).size.height -
40 -
widget.topHeight -
100 * _model.datas.length;
100 * _model.datas.length
;
return SliverToBoxAdapter(
child: Container(
height: height < 0 ? 0 : height,
......@@ -98,4 +114,7 @@ class TopListState extends State<TopList> {
_model.loadMore();
}, pullDown: false, pullUp: true);
}
@override
bool get wantKeepAlive => true;
}
......@@ -2,6 +2,8 @@
* @author lsy
* @date 2020/7/2
**/
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_common/commonModel/live/BaseModel.dart';
import 'package:flutter_common/commonModel/live/LiveData.dart';
import 'package:flutter_common/commonModel/toast/NativeToast.dart';
......@@ -40,7 +42,7 @@ class TopModel extends BaseModel {
tabIndex = index;
}
void init(Function(int size) back) {
void init(VoidCallback back) {
ClueApiImpl.getInstance()
.getPlanBar(DioUtil.getInstance().getDio(), rank_type)
.listen((event) {
......@@ -48,7 +50,7 @@ class TopModel extends BaseModel {
stateLive.notifyView(ENDLOADING);
imageUrl = event.data.bannerImage;
tabs = event.data.tabs;
back(tabs.length);
back();
} else {
NativeToast.showNativeToast(event.message);
stateLive.notifyView(FAIL);
......
......@@ -3,16 +3,21 @@
* @date 2020/7/2
**/
import 'dart:async';
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart'
as extend;
import 'package:flutter/material.dart';
import 'package:gm_flutter/ClueModel/page/levelTwo/LevelTwoPage.dart';
import 'package:gm_flutter/ClueModel/page/top/TopModel.dart';
import 'package:gm_flutter/ClueModel/util/PosUtil.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
import 'package:gm_flutter/commonModel/base/BaseState.dart';
import 'package:gm_flutter/commonModel/eventbus/SimpleEventBus.dart';
import 'package:gm_flutter/commonModel/util/DartUtil.dart';
import 'package:gm_flutter/commonModel/view/baseRefreshIndicator.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'TopList.dart';
......@@ -25,7 +30,8 @@ class TopPage extends StatefulWidget {
class TopPageState extends BaseState<TopPage> with TickerProviderStateMixin {
RefreshController refreshController = RefreshController();
TopModel _model = TopModel();
GlobalKey globalKey = GlobalKey();
int index = 0;
TabController tabController;
@override
void initState() {
......@@ -34,18 +40,30 @@ class TopPageState extends BaseState<TopPage> with TickerProviderStateMixin {
}
void init() {
_model.init((i) {
setState(() {});
_model.init(() {
_initTabBar();
});
}
@override
void dispose() {
_model.dispose();
tabController?.removeListener(tabControlerListener);
tabController?.dispose();
refreshController.dispose();
super.dispose();
}
void _initTabBar() {
if (tabController != null) {
tabController.removeListener(tabControlerListener);
}
tabController = TabController(
initialIndex: index, length: _model.tabs.length, vsync: this);
tabController.addListener(tabControlerListener);
setState(() {});
}
@override
Widget buildItem(BuildContext context) {
return Scaffold(
......@@ -53,84 +71,99 @@ class TopPageState extends BaseState<TopPage> with TickerProviderStateMixin {
MediaQuery.of(context).size.width,
MediaQuery.of(context).size.height,
_model.stateLive,
Stack(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: NotificationListener(
onNotification: (scrollNotification) {
if (scrollNotification is KeepAliveNotification ||
scrollNotification is OverscrollIndicatorNotification) {
return false;
}
if (scrollNotification is ScrollUpdateNotification &&
scrollNotification.metrics.axisDirection.index == 2) {}
print(
"NOT ${scrollNotification} ${scrollNotification is KeepAliveNotification}");
if (scrollNotification.depth == 0) {
if (scrollNotification.metrics.pixels > 80) {
_model.textLive.notifyView(
(scrollNotification.metrics.pixels - 80) / 40 > 1.0
? 1.0
: (scrollNotification.metrics.pixels - 80) /
40);
} else {
_model.textLive.notifyView(0.0);
}
} else if (scrollNotification.depth == 2) {
if (scrollNotification.metrics.pixels < 50 &&
scrollNotification.metrics.pixels > 0) {
_model.textLive.notifyView(1.0);
}
}
return false;
},
child: home(),
),
),
baseSliverBack(() {
Navigator.of(context).pop();
}),
baseSliverTitle(
"title", MediaQuery.of(context).size.width, _model.textLive)
],
Container(
child: BaseNestedScrollViewRefreshIndicator(
onRefresh: () async {
Completer completer = new Completer();
_model.init(() {
_initTabBar();
SimpleEventBus.instance().notifyListener("TopList", "");
completer.complete();
});
return completer.future;
},
child: homeWarp()),
), () {
init();
}),
);
}
Widget homeWarp() {
return Stack(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: NotificationListener(
onNotification: (scrollNotification) {
if (scrollNotification is KeepAliveNotification ||
scrollNotification is OverscrollIndicatorNotification) {
return false;
}
if (scrollNotification is ScrollUpdateNotification &&
scrollNotification.metrics.axisDirection.index == 2) {}
if (scrollNotification.depth == 0) {
if (scrollNotification.metrics.pixels > 80) {
_model.textLive.notifyView(
(scrollNotification.metrics.pixels - 80) / 40 > 1.0
? 1.0
: (scrollNotification.metrics.pixels - 80) / 40);
} else {
_model.textLive.notifyView(0.0);
}
} else if (scrollNotification.depth == 2) {
if (scrollNotification.metrics.pixels < 50 &&
scrollNotification.metrics.pixels > 0) {
_model.textLive.notifyView(1.0);
}
}
return false;
},
child: home(),
),
),
baseSliverBack(() {
Navigator.of(context).pop();
}),
baseSliverTitle(
"title", MediaQuery.of(context).size.width, _model.textLive)
],
);
}
Widget home() {
List<Widget> list = [];
var d = MediaQueryData.fromWindow(window).padding.top;
for (int i = 0; i < _model.tabs.length; i++) {
list.add(TopList(_model.tabs[i].id, 48 + d).toActive());
list.add(extend.NestedScrollViewInnerScrollPositionKeyWidget(Key("Tab${i}"),
TopList(_model.tabs[i].id, kToolbarHeight + d)));
}
return DefaultTabController(
length: _model.tabs.length,
child: NestedScrollView(
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverOverlapAbsorber(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
context),
sliver: baseSliverAppBar(_model.imageUrl)),
SliverPersistentHeader(
pinned: true,
delegate: StickyTabBarDelegate(
child: Container(
height: 40,
color: Colors.white,
child: baseTabBar(null, getTabs(), (index) {
_model.selectTab(index);
}),
)),
),
];
},
body: TabBarView(children: list)));
return extend.NestedScrollView(
innerScrollPositionKeyBuilder: () {
String index = 'Tab${tabController.index.toString()}';
return Key(index);
},
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverOverlapAbsorber(
handle: extend.NestedScrollView.sliverOverlapAbsorberHandleFor(
context),
sliver: baseSliverAppBar(_model.imageUrl)),
SliverPersistentHeader(
pinned: true,
delegate: StickyTabBarDelegate(
child: Container(
height: 40,
color: Colors.white,
child: baseTabBar(tabController, getTabs(), (index) {
_model.selectTab(index);
}),
)),
),
];
},
body: TabBarView(controller: tabController, children: list));
}
List<Widget> getTabs() {
......@@ -142,4 +175,10 @@ class TopPageState extends BaseState<TopPage> with TickerProviderStateMixin {
}
return list;
}
void tabControlerListener() {
if (index != tabController.index) {
index = tabController.index;
}
}
}
......@@ -8,7 +8,7 @@ class PlanOverViewBean {
Null extra;
Null errorExtra;
UserType userType;
Data data;
PlanOverData data;
PlanOverViewBean(
{this.error,
......@@ -26,7 +26,7 @@ class PlanOverViewBean {
userType = json['user_type'] != null
? new UserType.fromJson(json['user_type'])
: null;
data = json['data'] != null ? new Data.fromJson(json['data']) : null;
data = json['data'] != null ? new PlanOverData.fromJson(json['data']) : null;
}
Map<String, dynamic> toJson() {
......@@ -56,7 +56,7 @@ class UserType {
}
}
class Data {
class PlanOverData {
Banner banner;
String name;
String positiveRate;
......@@ -67,7 +67,7 @@ class Data {
List<ExplanationAttrs> explanationAttrs;
List<Tabs> tabs;
Data(
PlanOverData(
{this.banner,
this.name,
this.positiveRate,
......@@ -78,7 +78,7 @@ class Data {
this.explanationAttrs,
this.tabs});
Data.fromJson(Map<String, dynamic> json) {
PlanOverData.fromJson(Map<String, dynamic> json) {
banner =
json['banner'] != null ? new Banner.fromJson(json['banner']) : null;
name = json['name'];
......
......@@ -4,9 +4,10 @@
**/
import 'package:flutter/services.dart';
import 'package:flutter_boost/flutter_boost.dart';
import 'package:gm_flutter/commonModel/base/BaseUtil.dart';
class MainManager {
static const EventChannel _channel = EventChannel("flutter_plugin_event");
MainManager._() {}
......@@ -20,8 +21,9 @@ class MainManager {
}
startInit() {
_channel.receiveBroadcastStream().listen((data) {
flutterEvent.receiveBroadcastStream().listen((data) {
print("LSY FLUTTER EVENT ${data}");
});
flutterChannel.invokeMethod("WHAT ","www");
}
}
......@@ -15,6 +15,7 @@ import 'package:gm_flutter/commonModel/GMBase.dart';
import 'package:gm_flutter/commonModel/bean/Pair.dart';
import 'package:gm_flutter/commonModel/util/DartUtil.dart';
import 'package:gm_flutter/commonModel/view/ImagesAnimation.dart';
import 'package:gm_flutter/commonModel/view/baseRefreshIndicator.dart';
import 'package:gm_flutter/commonModel/view/baseTabIndicator.dart';
import 'package:lottie/lottie.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
......@@ -143,42 +144,49 @@ Widget loadingItem({bool needBackground = false}) {
Widget netErrorItem() {}
Widget errorItem(double width, double height, VoidCallback retry,
{String errorText, String retryText}) {
{String errorText, String retryText,double paddingTop}) {
return Container(
width: width,
height: height,
color: Colors.white,
padding: EdgeInsets.only(top: paddingTop),
alignment: Alignment.topCenter,
child: Container(
width: 180,
height: 315.5,
margin: EdgeInsets.only(top: 62),
child: Stack(
alignment: AlignmentDirectional.center,
children: <Widget>[
Positioned(
left: 0,
top: 0,
child: Container(
width: 180,
height: 315.5,
margin: EdgeInsets.only(top: 62),
child: Column(
children: <Widget>[
Container(
width: 180,
height: 186.5,
child: Image.asset("assets/error.png"),
),
),
Positioned(
top: 166,
child: Container(
width: 180,
alignment: Alignment.center,
child: baseText(
errorText ?? "原谅我一看到美人就不淡定", 15, Color(0xff666666)),
child: Stack(
alignment: AlignmentDirectional.center,
children: <Widget>[
Positioned(
left: 0,
top: 0,
child: Container(
width: 180,
height: 186.5,
child: Image.asset("assets/error.png"),
),
),
Positioned(
top: 166,
child: Container(
width: 180,
alignment: Alignment.center,
child: baseText(
errorText ?? "原谅我一看到美人就不淡定", 15, Color(0xff666666)),
),
),
],
),
),
),
Positioned(
bottom: 60,
child: Container(
Container(
width: 150,
height: 40,
margin: EdgeInsets.only(top: 17),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
gradient: LinearGradient(
......@@ -190,12 +198,10 @@ Widget errorItem(double width, double height, VoidCallback retry,
).gestureDetector(() {
retry();
}),
),
Positioned(
bottom: 0,
child: Container(
Container(
width: 150,
height: 40,
margin: EdgeInsets.only(top: 20),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
border: Border.all(color: Color(0xffFF5963), width: 0.5)),
......@@ -204,10 +210,8 @@ Widget errorItem(double width, double height, VoidCallback retry,
).gestureDetector(() {
AppSettings.openWIFISettings();
}),
)
],
),
));
],
)));
}
//TODO
......@@ -373,8 +377,9 @@ Widget normalRefreshHeader() {
);
}
Widget emptyItem(double width, double height, {String detail}) {
Widget emptyItem(double width, double height, {String detail,double paddingTop}) {
return Container(
padding: EdgeInsets.only(top: paddingTop??0),
width: width,
height: height,
color: Colors.white,
......@@ -383,20 +388,34 @@ Widget emptyItem(double width, double height, {String detail}) {
width: 175,
height: 188,
margin: EdgeInsets.only(top: 62.5),
child: Stack(
alignment: AlignmentDirectional.bottomCenter,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
width: 175,
height: 188,
child: Image.asset("assets/empty.png"),
child: Stack(
alignment: AlignmentDirectional.bottomCenter,
children: <Widget>[
Container(
width: 175,
height: 188,
child: Image.asset("assets/empty.png"),
),
Positioned(
bottom: 17,
child: baseText(detail ?? "此处太寂寥,转转别处吧", 15, Color(0xff666666)),
)
],
),
),
Positioned(
bottom: 17,
child: baseText(detail ?? "此处太寂寥,转转别处吧", 15, Color(0xff666666)),
Container(
height:0,
color: Colors.white,
)
],
),
)
),
);
}
......@@ -491,7 +510,7 @@ Widget baseSliverTitle(String text, double width, LiveData liveData) {
}
Widget baseStateView(double width, double height, LiveData<int> stateLive,
Widget home, VoidCallback retry) {
Widget home, VoidCallback retry,{double paddingTop}) {
return StreamBuilder(
stream: stateLive.stream,
initialData: stateLive.data ?? LOADING,
......@@ -499,9 +518,9 @@ Widget baseStateView(double width, double height, LiveData<int> stateLive,
if (data.data == LOADING) {
return loadingItem();
} else if (data.data == FAIL) {
return errorItem(width, height, retry);
return errorItem(width, height, retry,paddingTop: paddingTop);
} else if (data.data == EMPTY) {
return emptyItem(width, height);
return emptyItem(width, height,paddingTop: paddingTop);
}
return home;
},
......
......@@ -9,4 +9,5 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
const flutterChannel = const MethodChannel('gm_method_channel');
const bool isDebug = ! const bool.fromEnvironment("dart.vm.product");
const flutterEvent = const EventChannel('flutter_plugin_event');
const bool isDebug = !const bool.fromEnvironment("dart.vm.product");
/*
* @author lsy
* @date 2020/7/5
**/
import 'package:dio/dio.dart';
class SimpleEventBus{
static SimpleEventBus _eventBus;
SimpleEventBus._();
static SimpleEventBus instance(){
if(_eventBus==null){
_eventBus=SimpleEventBus._();
}
return _eventBus;
}
Map<String,List<Function(String str)>> map=Map();
void resignEvent(String name,Function(String str) func){
if(map[name]==null){
map[name]=[];
}
map[name].add(func);
}
void unResignEvent(String name,Function(String str) func){
if(map[name]==null){
return;
}
map[name].remove(func);
}
void notifyListener(String name,String str){
if(map[name]==null){
return;
}
map[name].forEach((element) {
element(str);
});
}
}
\ No newline at end of file
This diff is collapsed.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.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:flutter_screenutil/screenutil.dart';
import 'package:gm_flutter/main.mark.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:gm_flutter/ClueModel/page/PlanCompareDetail/PlanCompareDetailPage.dart';
......@@ -37,7 +39,7 @@ void main() {
SharedPreferences.getInstance().then((value) {
sharedPreferences = value;
});
RouterCenterImpl().findMainRouter().init();
// RouterCenterImpl().findMainRouter().init();
}, (Object error, StackTrace stack) {
//TODO
print("lsy EEEEEE ${error.toString()} ${stack.toString()}");
......@@ -58,7 +60,7 @@ class MyApp extends State<MyAppWidget> {
super.initState();
FlutterBoost.singleton.registerPageBuilders({
'demoPage': (pageName, params, _) {
return DemoPage();
return RouterCenterImpl().findClueRouter().getLevelOnePage();
},
'demoPage1': (pageName, params, _) {
return DemoPage1();
......@@ -67,30 +69,30 @@ class MyApp extends State<MyAppWidget> {
FlutterBoost.singleton
.addBoostContainerLifeCycleObserver((state, settings) {
print("LSY ${state}");
if (state == ContainerLifeCycle.Init) {
const EventChannel flutterEvent = const EventChannel('flutter_plugin_event');
flutterEvent.receiveBroadcastStream().listen((data) {
print("LSY FLUTTER EVENT ${data}");
});
MethodChannel flutterChannel = const MethodChannel('gm_method_channel');
flutterChannel.invokeMethod("FFINIT", "Fff");
}
});
// FlutterBoost.singleton.addBoostNavigatorObserver(TestBoostNavigatorObserver());
}
@override
Widget build(BuildContext context) {
WindowUtil.setBarStatus(true);
WindowUtil.setBarStatus(false);
return MaterialApp(
theme: ThemeData(
primaryColor: Colors.white,
cursorColor: Color(0xff20BDBB),
highlightColor:Colors.transparent,
splashColor:Colors.transparent,
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
canvasColor: Colors.white),
builder: FlutterBoost.init(postPush: _onRoutePushed),
home: isDebug
? RouterCenterImpl().findMainRouter().getTestPage()
: Container(
color: Colors.white,
child: Center(
child: loadingItem(),
),
));
home: Home());
}
void _onRoutePushed(
......@@ -101,3 +103,23 @@ class MyApp extends State<MyAppWidget> {
Future<dynamic> _,
) {}
}
class Home extends StatefulWidget {
@override
State<StatefulWidget> createState() => HomeState();
}
class HomeState extends State<Home> {
@override
Widget build(BuildContext context) {
ScreenUtil.init(context, width: 375, height: 810);
return isDebug
? RouterCenterImpl().findMainRouter().getTestPage()
: Container(
color: Colors.white,
child: Center(
child: loadingItem(),
),
);
}
}
......@@ -262,6 +262,13 @@ packages:
url: "https://github.com/asd451398533/flutter_common.git"
source: git
version: "0.0.1"
flutter_screenutil:
dependency: "direct main"
description:
name: flutter_screenutil
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0"
flutter_svg:
dependency: transitive
description:
......@@ -745,7 +752,7 @@ packages:
name: uuid
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0"
version: "2.2.0"
vector_math:
dependency: transitive
description:
......
......@@ -34,6 +34,8 @@ dependencies:
lottie: ^0.4.0+1
app_settings: ^4.0.1+1
extended_nested_scroll_view: ^1.0.0
#适配库
flutter_screenutil: ^1.1.0
dev_dependencies:
......
#!/usr/bin/env bash
echo START
projectDir=`pwd`
rootFlutter=`which flutter`
rootDir=${rootFlutter%/*}
#====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
rm -rf ${projectDir}/build
flutter build aar --release --target-platform android-arm
#rm -rf /Users/apple/lsy/gengmei_android/gm-flutter/libs/flutterApp.aar
cp -r ${projectDir}/build/host/outputs/repo/com/example/gm_flutter/flutter_release/1.0/flutter_release-1.0.aar /Users/apple/lsy/gengmei_android/gm-flutter/libs/flutterApp.aar
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