Commit 4814802c authored by 杜欣's avatar 杜欣

二级方案

parent 21f25c43
import 'package:flutter/material.dart';
class StickyTabBarDelegate extends SliverPersistentHeaderDelegate {
final Widget child;
StickyTabBarDelegate({@required this.child});
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return this.child;
}
@override
double get maxExtent => 40;
@override
double get minExtent => 40;
@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
return true;
}
}
...@@ -25,7 +25,7 @@ class LevelOneList extends StatefulWidget { ...@@ -25,7 +25,7 @@ class LevelOneList extends StatefulWidget {
} }
class LevelOneListState extends State<LevelOneList> class LevelOneListState extends State<LevelOneList>
with AutomaticKeepAliveClientMixin{ with AutomaticKeepAliveClientMixin {
LevelOneListModel _model = LevelOneListModel(); LevelOneListModel _model = LevelOneListModel();
RefreshController refreshController = RefreshController(); RefreshController refreshController = RefreshController();
...@@ -83,7 +83,7 @@ class LevelOneListState extends State<LevelOneList> ...@@ -83,7 +83,7 @@ class LevelOneListState extends State<LevelOneList>
return SliverList( return SliverList(
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) { (BuildContext context, int index) {
if(index==_model.data.length){ if (index == _model.data.length) {
return Container( return Container(
height: 40, height: 40,
color: Color(0xffF7F6FA), color: Color(0xffF7F6FA),
...@@ -91,7 +91,7 @@ class LevelOneListState extends State<LevelOneList> ...@@ -91,7 +91,7 @@ class LevelOneListState extends State<LevelOneList>
} }
return LevelOneItem(_model.data[index]); return LevelOneItem(_model.data[index]);
}, },
childCount: _model.data.length+1, childCount: _model.data.length + 1,
), ),
); );
}, },
......
...@@ -11,9 +11,9 @@ import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart' ...@@ -11,9 +11,9 @@ import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart'
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:gm_flutter/ClueModel/page/common/StickyTabBarDelegate.dart';
import 'package:gm_flutter/ClueModel/page/levelOne/LevelOneList.dart'; import 'package:gm_flutter/ClueModel/page/levelOne/LevelOneList.dart';
import 'package:gm_flutter/ClueModel/page/levelOne/LevelOneModel.dart'; import 'package:gm_flutter/ClueModel/page/levelOne/LevelOneModel.dart';
import 'package:gm_flutter/ClueModel/page/levelTwo/LevelTwoPage.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart'; import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
import 'package:gm_flutter/commonModel/base/BaseState.dart'; import 'package:gm_flutter/commonModel/base/BaseState.dart';
import 'package:gm_flutter/commonModel/base/BaseUtil.dart'; import 'package:gm_flutter/commonModel/base/BaseUtil.dart';
......
...@@ -7,72 +7,50 @@ import 'package:flutter_common/commonModel/live/BaseModel.dart'; ...@@ -7,72 +7,50 @@ import 'package:flutter_common/commonModel/live/BaseModel.dart';
import 'package:flutter_common/commonModel/live/LiveData.dart'; import 'package:flutter_common/commonModel/live/LiveData.dart';
import 'package:flutter_common/commonModel/toast/NativeToast.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/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/ClueModel/server/entity/PlanOverviewBean.dart';
import 'package:gm_flutter/commonModel/GMBase.dart'; import 'package:gm_flutter/commonModel/GMBase.dart';
import 'package:gm_flutter/commonModel/bean/Pair.dart';
import 'package:gm_flutter/commonModel/rx/RxDispose.dart'; import 'package:gm_flutter/commonModel/rx/RxDispose.dart';
import 'package:gm_flutter/commonModel/util/PrintUtil.dart'; import 'package:gm_flutter/commonModel/util/PrintUtil.dart';
import 'package:gm_flutter/commonModel/bean/Pair.dart';
import '../../../commonModel/bean/Pair.dart';
class LevelTwoModel extends BaseModel {
LiveData<Pair<int, String>> nameLive = LiveData();
LiveData<Pair<int, String>> imageUrlLive = LiveData();
LiveData<Pair<int, List<OverviewAttrsEntity>>> overviewAttrsLive = LiveData();
LiveData<Pair<int, List<ExplanationAttrsEntity>>> explanationAttrsLive =
LiveData();
LiveData<Pair<int, List<Tabs>>> tabsLive = LiveData();
class LevelOneModel extends BaseModel {
LiveData<int> stateLive = LiveData(); LiveData<int> stateLive = LiveData();
LiveData<Pair<int, List<Cards>>> cardsLive = LiveData(); LiveData<double> textLive = LiveData();
RxDispose rxDispose = RxDispose(); RxDispose rxDispose = RxDispose();
getPlanOverview(int plan_id) { List<Tabs> tabsList = [];
int plan_id = 0;
PlanOverData planoverItem;
void init(VoidCallback callback) {
ClueApiImpl.getInstance() ClueApiImpl.getInstance()
.getPlanOverviewBean(DioUtil.getInstance().getDio(), plan_id) .getPlanOverView(DioUtil.getInstance().getDio(), plan_id)
.listen((event) { .listen((event) {
if (event.error == 0) { if (event.error == 0) {
planoverItem = event.data;
tabsList = event.data.tabs;
stateLive.notifyView(ENDLOADING); stateLive.notifyView(ENDLOADING);
nameLive.notifyView(Pair(ENDLOADING, event.data.name)); callback();
imageUrlLive
.notifyView(Pair(ENDLOADING, event.data.banner.imageUrl));
overviewAttrsLive
.notifyView(Pair(ENDLOADING, event.data.overviewAttrs));
explanationAttrsLive
.notifyView(Pair(ENDLOADING, event.data.explanationAttrs));
tabsLive.notifyView(Pair(ENDLOADING, event.data.tabs));
} else { } else {
NativeToast.showNativeToast(event.message); NativeToast.showNativeToast(event.message);
commonError(); stateLive.notifyView(FAIL);
} }
}) })
.addToDispose(rxDispose) .addToDispose(rxDispose)
.onError((err) { .onError((err) {
commonError();
PrintUtil.printBug(err); PrintUtil.printBug(err);
stateLive.notifyView(FAIL);
}); });
} }
commonError() { int currentIndex = 0;
stateLive.notifyView(FAIL);
nameLive.notifyView(Pair(FAIL, null));
imageUrlLive.notifyView(Pair(FAIL, null));
overviewAttrsLive.notifyView(Pair(FAIL, null));
explanationAttrsLive.notifyView(Pair(FAIL, null));
tabsLive.notifyView(Pair(FAIL, null));
}
@override @override
void dispose() { void dispose() {
nameLive.dispost();
imageUrlLive.dispost();
overviewAttrsLive.dispost();
explanationAttrsLive.dispost();
tabsLive.dispost();
stateLive.dispost(); stateLive.dispost();
rxDispose.dispose(); textLive.dispost();
} }
void loadMore() {} void selectTab(int index) {}
} }
/* /*
* @author dx * @author lsy
* @date 2020-06-29 * @date 2020/6/29
**/ **/
import 'dart:async';
import 'dart:math'; import 'dart:math';
import 'dart:ui';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart'
as extend;
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_common/commonModel/picker/base/BaseBottomPicker.dart'; import 'package:flutter_common/commonModel/picker/base/BaseBottomPicker.dart';
import 'package:gm_flutter/ClueModel/page/levelTwo/LevelTwoModel.dart'; import 'package:gm_flutter/ClueModel/page/common/StickyTabBarDelegate.dart';
import 'package:gm_flutter/ClueModel/page/levelOne/LevelOneList.dart';
import 'package:gm_flutter/ClueModel/page/levelOne/LevelOneModel.dart';
import 'package:gm_flutter/ClueModel/page/mechanismBox/MechanismBoxPage.dart'; import 'package:gm_flutter/ClueModel/page/mechanismBox/MechanismBoxPage.dart';
import 'package:gm_flutter/ClueModel/server/entity/LevelOneFeedList.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlanOverviewBean.dart';
import 'package:gm_flutter/ClueModel/view/FiveStarView.dart';
import 'package:gm_flutter/commonModel/base/BaseState.dart';
import 'package:gm_flutter/commonModel/base/BaseUtil.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.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/view/baseRefreshIndicator.dart';
import 'package:gm_flutter/main.mark.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:gm_flutter/commonModel/bean/Pair.dart';
import '../../../commonModel/bean/Pair.dart';
import '../../../commonModel/bean/Pair.dart';
import '../../../commonModel/bean/Pair.dart';
class LevelTwoPage extends StatefulWidget { class LevelTwoPage extends StatefulWidget {
@required
final int plan_id;
const LevelTwoPage({Key key, this.plan_id}) : super(key: key);
@override @override
_LevelTwoPageState createState() => _LevelTwoPageState(); State<StatefulWidget> createState() => LevelTwoState();
} }
class _LevelTwoPageState extends BaseState<LevelTwoPage> class LevelTwoState extends BaseState<LevelTwoPage>
with SingleTickerProviderStateMixin { with SingleTickerProviderStateMixin {
LevelTwoModel _model = new LevelTwoModel(); int planId = 10;
LevelOneModel _model = new LevelOneModel();
RefreshController _refreshController = RefreshController(); RefreshController _refreshController = RefreshController();
PageController pageController = new PageController(); GlobalKey keyTop = new GlobalKey();
GlobalKey key1 = new GlobalKey();
double screenWidth;
List<Widget> oneList = new List();
int lastPageIndex = 0;
TabController tabController; TabController tabController;
int index = 0;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
this.tabController = TabController(length: 2, vsync: this); _model.init(() {
_model.getPlanOverview(this.widget.plan_id); _initTabBar();
});
}
void _initTabBar() {
if (tabController != null) {
tabController.removeListener(tabControlerListener);
}
tabController = TabController(
initialIndex: index, length: _model.tabsList.length, vsync: this);
tabController.addListener(tabControlerListener);
setState(() {});
} }
@override @override
void dispose() { void dispose() {
tabController?.removeListener(tabControlerListener);
tabController?.dispose();
_model.dispose(); _model.dispose();
pageController.dispose();
_refreshController.dispose(); _refreshController.dispose();
super.dispose(); super.dispose();
} }
void tabControlerListener() {
if (index != tabController.index) {
index = tabController.index;
}
}
@override @override
Widget buildItem(BuildContext context) { Widget buildItem(BuildContext context) {
return Scaffold( oneList.clear();
body: StreamBuilder<int>( oneList.add(good());
stream: _model.stateLive.stream, oneList.add(rect());
initialData: _model.stateLive.data ?? LOADING, oneList.add(explain());
builder: (c, data) { oneList.add(Container(
print("ddsadsadsadsa"); height: 5,
print(data); color: Color(0xffF7F6FA),
if (data.data == FAIL) {
return loadingItem();
} else {
return home();
}
},
)); ));
screenWidth = MediaQuery.of(context).size.width;
return Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
top: false,
child: baseStateView(
MediaQuery.of(context).size.width,
MediaQuery.of(context).size.height,
_model.stateLive,
Container(
child: BaseNestedScrollViewRefreshIndicator(
onRefresh: () async {
Completer completer = new Completer();
_model.init(() {
_initTabBar();
SimpleEventBus.instance()
.notifyListener("LevelOneList", "");
completer.complete();
});
return completer.future;
},
child: newHomeWarp()),
), () {
_model.init(() {
_initTabBar();
});
})));
} }
Widget home() { Widget newHomeWarp() {
return Stack( return Stack(
children: <Widget>[ children: <Widget>[
CustomScrollView(slivers: <Widget>[ Container(
SliverAppBar( width: MediaQuery.of(context).size.width,
pinned: true, height: MediaQuery.of(context).size.height,
elevation: 0, child: NotificationListener(
expandedHeight: 0, onNotification: (scrollNotification) {
flexibleSpace: FlexibleSpaceBar(title: title((data) { if (scrollNotification is KeepAliveNotification ||
return Text(data); scrollNotification is OverscrollIndicatorNotification) {
})), return false;
), }
SliverToBoxAdapter( if (scrollNotification is ScrollUpdateNotification &&
child: Column( scrollNotification.metrics.axisDirection.index == 2) {}
crossAxisAlignment: CrossAxisAlignment.start, if (scrollNotification.depth == 0) {
mainAxisSize: MainAxisSize.max, if (scrollNotification.metrics.pixels > 80) {
children: <Widget>[good(), rect(), explain()], _model.textLive.notifyView(
)), (scrollNotification.metrics.pixels - 80) / 40 > 1.0
SliverPersistentHeader( ? 1.0
pinned: true, : (scrollNotification.metrics.pixels - 80) / 40);
delegate: StickyTabBarDelegate( } else {
child: baseTabBar(tabController, _model.textLive.notifyView(0.0);
[baseTabBarItem("医院"), baseTabBarItem("医生")], (index) {}, }
scroll: false), } else if (scrollNotification.depth == 2) {
), if (scrollNotification.metrics.pixels < 50 &&
), scrollNotification.metrics.pixels > 0) {
// SliverFillRemaining(child: pages()) _model.textLive.notifyView(1.0);
]), }
Positioned(left: 0, right: 0, bottom: 0, child: bottomWidget()) }
return false;
},
child: newHome(),
)),
baseSliverTitle(_model.planoverItem?.name,
MediaQuery.of(context).size.width, _model.textLive),
baseSliverBack(() {
Navigator.of(context).pop();
}),
bottomWidget()
], ],
); );
} }
// 方案名称 Widget newHome() {
Widget title(Function text) { List<Widget> list = [];
return StreamBuilder<Pair<int, String>>( var d = MediaQueryData.fromWindow(window).padding.top;
stream: _model.nameLive.stream, for (int i = 0; i < _model.tabsList.length; i++) {
initialData: _model.nameLive.data ?? Pair(LOADING, null), list.add(extend.NestedScrollViewInnerScrollPositionKeyWidget(
builder: (context, e) { Key("Tab${i}"),
if (e.data.first == FAIL) { LevelOneList(
return Text(''); planId, _model.tabsList[i].tabType, kToolbarHeight + d)));
} }
return text(e.data.second); final double statusBarHeight = MediaQuery.of(context).padding.top;
}, final double pinnedHeaderHeight = statusBarHeight + kToolbarHeight;
); return extend.NestedScrollView(
innerScrollPositionKeyBuilder: () {
String index = 'Tab${tabController.index.toString()}';
return Key(index);
},
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverList(
delegate: SliverChildBuilderDelegate((BuildContext c, int i) {
if (i == 0) {
return Container(
height: pinnedHeaderHeight,
);
}
return oneList[i - 1];
}, childCount: oneList.length + 1)),
SliverPersistentHeader(
pinned: true,
delegate: StickyTabBarDelegate(
child: Container(
height: 40,
color: Colors.white,
child: baseTabBar(tabController, getTabs(), (index) {
_model.selectTab(index);
}, scroll: false),
)),
),
];
},
body: TabBarView(controller: tabController, children: list));
}
List<Widget> getTabs() {
List<Widget> list = [];
for (int i = 0; i < _model.tabsList.length; i++) {
list.add(baseTabBarItem(_model.tabsList[i].name,
leftPadding: i == 0 ? 24 : 28,
rightPadding: i == _model.tabsList.length - 1 ? 24 : 28));
}
return list;
} }
// 方案顶部
Widget good() { Widget good() {
if (_model.planoverItem == null) {
return Container(
height: 54,
);
}
return Padding( return Padding(
padding: EdgeInsets.only(left: 15.0, right: 15.0, top: 8.0), padding: EdgeInsets.only(left: 15.0, right: 15.0, top: 8.0),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
children: <Widget>[ children: <Widget>[
StreamBuilder<Pair<int, String>>( ClipRRect(
stream: _model.imageUrlLive.stream, borderRadius: BorderRadius.circular(6),
initialData: _model.imageUrlLive.data ?? null, child: Container(
builder: (context, e) { decoration: BoxDecoration(
if (e.data.first == FAIL) { borderRadius: BorderRadius.circular(17),
return Container(); border: Border.all(color: Color(0xffF9F8FB), width: 1)),
} child: Image.network(
return ClipRRect( _model.planoverItem.banner.imageUrl,
borderRadius: BorderRadius.circular(6), width: 86,
child: Container( height: 86,
decoration: BoxDecoration( fit: BoxFit.cover,
borderRadius: BorderRadius.circular(17), ),
border: )),
Border.all(color: Color(0xffF9F8FB), width: 1)),
child: Image.network(
e.data.second,
width: 86,
height: 86,
fit: BoxFit.cover,
),
));
}),
Padding( Padding(
padding: EdgeInsets.only(left: 12, top: 5), padding: EdgeInsets.only(left: 12, top: 5),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
children: <Widget>[ children: <Widget>[
title((data) { Text(_model.planoverItem.name,
return Text(data, style: TextStyle(
style: TextStyle( color: Color(0xff333333),
color: Color(0xff333333), fontSize: 15,
fontSize: 15, fontWeight: FontWeight.bold)),
fontWeight: FontWeight.bold));
}),
Padding(padding: EdgeInsets.only(top: 5)), Padding(padding: EdgeInsets.only(top: 5)),
Row( Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
...@@ -172,7 +255,7 @@ class _LevelTwoPageState extends BaseState<LevelTwoPage> ...@@ -172,7 +255,7 @@ class _LevelTwoPageState extends BaseState<LevelTwoPage>
style: TextStyle( style: TextStyle(
color: Color(0xff999999), fontSize: 12)), color: Color(0xff999999), fontSize: 12)),
Text( Text(
2000-5000', ' + _model.planoverItem.guidePrice,
style: style:
TextStyle(color: Color(0xffFF5963), fontSize: 12), TextStyle(color: Color(0xffFF5963), fontSize: 12),
) )
...@@ -185,392 +268,169 @@ class _LevelTwoPageState extends BaseState<LevelTwoPage> ...@@ -185,392 +268,169 @@ class _LevelTwoPageState extends BaseState<LevelTwoPage>
); );
} }
// 方案属性
Widget rect() { Widget rect() {
return Padding( if (_model.planoverItem == null) {
padding: EdgeInsets.only(top: 20), return Container(
child: StreamBuilder<Pair<int, List<OverviewAttrsEntity>>>( height: 62,
stream: _model.overviewAttrsLive.stream, );
initialData: _model.overviewAttrsLive.data ?? Pair(LOADING, null), }
builder: (c, data) { List<Widget> list = List();
if (data.data.first == FAIL) { int i = 0;
return Center(); _model.planoverItem.overviewAttrs.forEach((element) {
} list.add(Expanded(
final overviewAttrs = data.data.second; child: Container(
List<Widget> list = List(); alignment: Alignment.center,
for (int i = 0; i < overviewAttrs.length; i += 2) { child: Column(
list.add(Expanded( mainAxisSize: MainAxisSize.min,
child: Container( crossAxisAlignment: CrossAxisAlignment.center,
alignment: Alignment.center,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
baseText(overviewAttrs[i].attrName, 14, Color(0xff282828),
bold: true),
baseText(overviewAttrs[i].attrValue, 11, Color(0xff999999)),
],
),
),
));
if (i < overviewAttrs.length - 2) {
list.add(Container(
width: 0.5,
height: 18,
color: Color(0xFFE5E5E5),
));
}
}
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
color: Color(0xffF9F8FB),
),
width: double.maxFinite,
height: 62,
margin: EdgeInsets.only(left: 15, right: 15, bottom: 20),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: list,
),
);
},
),
);
}
// 方案项目说明
Widget explain() {
return StreamBuilder<Pair<int, List<ExplanationAttrsEntity>>>(
stream: _model.explanationAttrsLive.stream,
initialData: _model.explanationAttrsLive.data ?? Pair(LOADING, null),
builder: (c, data) {
List<Widget> list = [];
List<ExplanationAttrsEntity> explanationAttrs = data.data.second;
list.add(Container(
height: 31,
child: Row(
children: <Widget>[ children: <Widget>[
baseText("项目说明", 15, Color(0xff282828)), baseText(element.attrName, 14, Color(0xff282828), bold: true),
Expanded( baseText(element.attrValue, 11, Color(0xff999999)),
child: Container(),
),
GestureDetector(
onTap: () {
//TODO
},
behavior: HitTestBehavior.opaque,
child: baseText("了解更多", 12, Color(0xff3FB5AF)),
)
], ],
), ),
),
));
if (i != _model.planoverItem?.overviewAttrs.length - 1) {
list.add(Container(
width: 0.5,
height: 18,
color: Color(0xFFE5E5E5),
)); ));
for (int i = 0; i < explanationAttrs.length; i += 2) { }
list.add(Container( i++;
height: 28, });
child: Row(
children: <Widget>[
baseText(explanationAttrs[i].attrName, 13, Color(0xff999999)),
Container(
margin: EdgeInsets.only(left: 12),
child: baseText(
explanationAttrs[i].attrValue, 13, Color(0xff666666)),
)
],
),
));
}
return Container(
margin: EdgeInsets.only(left: 15, right: 15, bottom: 20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: list,
),
);
},
);
}
// 底部按钮
Widget bottomWidget() {
return Container( return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
color: Color(0xffF9F8FB),
),
width: double.maxFinite, width: double.maxFinite,
height: 55, height: 62,
margin: EdgeInsets.only(left: 15, right: 15, bottom: 20),
child: Row( child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: list,
),
);
}
Widget explain() {
List<Widget> list = [];
list.add(Container(
height: 31,
child: Row(
children: <Widget>[ children: <Widget>[
Container( baseText("项目说明", 15, Color(0xff282828)),
margin: EdgeInsets.only(left: 18),
width: 30,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
width: 22,
height: 22,
child: Image.asset("assets/vs_black.png"),
),
Container(
margin: EdgeInsets.only(top: 3),
child: baseText("去比较", 10, Color(0xff282828)),
)
],
),
),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
BaseBottomPicker()
..setPicker(MechanismBox(12))
..show(context);
},
child: Container(
margin: EdgeInsets.only(left: 15),
width: 135,
height: 40,
decoration: BoxDecoration(
color: Color(0xff51CDC7),
borderRadius: BorderRadius.circular(20)),
alignment: Alignment.center,
child: baseText("咨询", 14, Colors.white, bold: true),
)),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {},
child: Container(
margin: EdgeInsets.only(left: 15),
width: 135,
height: 40,
decoration: BoxDecoration(
color: Color(0xffF96079),
borderRadius: BorderRadius.circular(20)),
alignment: Alignment.center,
child: baseText("获取底价", 14, Colors.white, bold: true),
)),
Expanded( Expanded(
child: Container(), child: Container(),
),
GestureDetector(
onTap: () {
//TODO
Map<String, dynamic> map = {};
map["page_name"] = "plan_home";
map["referrer_link"] = [];
RouterCenterImpl()
.findMainRouter()
.buriedEvent("on_click_navbar_search", map);
},
behavior: HitTestBehavior.opaque,
child: baseText("了解更多", 12, Color(0xff3FB5AF)),
) )
], ],
), ),
); ));
} if (_model.planoverItem != null) {
_model.planoverItem.explanationAttrs.forEach((element) {
// 列表页面 list.add(Container(
Widget pages() { height: 28,
return StreamBuilder<Pair<int, List<Cards>>>( child: Row(
stream: _model.cardsLive.stream, children: <Widget>[
initialData: _model.cardsLive.data ?? Pair(LOADING, null), baseText(element.attrName, 13, Color(0xff999999)),
builder: (c, data) { Container(
return Container( margin: EdgeInsets.only(left: 12),
margin: EdgeInsets.only(top: 5), child: baseText(element.attrValue, 13, Color(0xff666666)),
width: double.maxFinite, )
child: TabBarView( ],
controller: tabController, ),
children: data.data.second[tabController.index].map((e) { ));
return ListView.builder( });
physics: NeverScrollableScrollPhysics(),
itemBuilder: (c, index) {
return Text('$index');
},
itemCount: 5,
);
}).toList()));
});
}
// 医生卡片
Widget DoctorItem(BuildContext context, cards) {
if (cards.doctor == null && isDebug) {
throw new Exception();
} }
return GestureDetector( return Container(
child: Container( margin: EdgeInsets.only(left: 15, right: 15, bottom: 20),
margin: EdgeInsets.only(left: 15, right: 15), child: Column(
height: 127, mainAxisSize: MainAxisSize.min,
child: Stack( children: list,
children: <Widget>[
Positioned(
top: 15,
child: Container(
width: 45,
height: 45,
child: ClipOval(
child: CachedNetworkImage(
imageUrl: cards.doctor.portrait,
),
),
),
),
Positioned(
left: 57,
top: 18,
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
baseText(cards.doctor.name, 15, Color(0xff333333),
bold: true),
Container(
margin: EdgeInsets.only(left: 4),
child: baseText(cards.doctor.name, 15, Color(0xff333333),
bold: true),
)
],
),
),
Positioned(
top: 42,
right: 0,
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
baseText("¥", 12, Color(0xffFF5963)),
baseText("${cards.doctor.minPrice}-${cards.doctor.maxPrice}",
15, Color(0xffFF5963)),
],
),
),
Positioned(
bottom: 15,
right: 0,
child: lowPriceWidget(),
),
Positioned(
bottom: 15,
right: 187,
child: askWidget(),
),
],
),
), ),
); );
} }
// 医院卡片 // 底部按钮
Widget HospitalItem(BuildContext context, cards) { Widget bottomWidget() {
if (cards.hospital == null && isDebug) { return Align(
throw new Exception(); alignment: Alignment.bottomCenter,
}
return GestureDetector(
onTap: () {},
child: Container( child: Container(
margin: EdgeInsets.only(left: 15, right: 15), width: double.maxFinite,
height: 149, height: 55,
child: Stack( color: Colors.white,
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
Positioned( Container(
left: 0, margin: EdgeInsets.only(left: 18),
top: 15, width: 30,
child: Container( child: Column(
width: 45,
height: 45,
child: ClipOval(
child: CachedNetworkImage(
imageUrl: cards.hospital.portrait,
),
),
),
),
Positioned(
left: 57,
top: 17.5,
child: baseText(cards.hospital.name, 15, Color(0xff333333),
bold: true),
),
Positioned(
top: 42.5,
right: 0,
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
baseText("¥", 12, Color(0xffFF5963)), Container(
baseText( width: 22,
"${cards.hospital.minPrice}-${cards.hospital.maxPrice}", height: 22,
15, child: Image.asset("assets/vs_black.png"),
Color(0xffFF5963)), ),
Container(
margin: EdgeInsets.only(top: 3),
child: baseText("去比较", 10, Color(0xff282828)),
)
], ],
), ),
), ),
Positioned( GestureDetector(
bottom: 15, behavior: HitTestBehavior.opaque,
right: 0, onTap: () {
child: lowPriceWidget(), BaseBottomPicker()
), ..setPicker(MechanismBox(12))
Positioned( ..show(context);
bottom: 15, },
right: 187, child: Container(
child: askWidget(), margin: EdgeInsets.only(left: 15),
), width: 135,
Positioned( height: 40,
bottom: 67, decoration: BoxDecoration(
left: 57, color: Color(0xff51CDC7),
child: baseText(cards.hospital.address, 12, Color(0xff666666)), borderRadius: BorderRadius.circular(20)),
), alignment: Alignment.center,
Positioned( child: baseText("咨询", 14, Colors.white, bold: true),
left: 57, )),
top: 43.5, GestureDetector(
child: FiveStarView(cards.hospital.star, 5), behavior: HitTestBehavior.opaque,
onTap: () {},
child: Container(
margin: EdgeInsets.only(left: 15),
width: 135,
height: 40,
decoration: BoxDecoration(
color: Color(0xffF96079),
borderRadius: BorderRadius.circular(20)),
alignment: Alignment.center,
child: baseText("获取底价", 14, Colors.white, bold: true),
)),
Expanded(
child: Container(),
) )
], ],
), ),
)); ));
} }
// 获取低价按钮
Widget lowPriceWidget() {
return GestureDetector(
behavior: HitTestBehavior.opaque,
child: Container(
width: 122,
height: 37,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(18.5),
color: Color(0xffFFF5F5)),
alignment: Alignment.center,
child: baseText("获取底价", 14, Color(0xffFF5963), bold: true),
),
);
}
// 咨询按钮
Widget askWidget() {
return GestureDetector(
behavior: HitTestBehavior.opaque,
child: Container(
width: 122,
height: 37,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(18.5),
color: Color(0xffEEFDFD)),
alignment: Alignment.center,
child: baseText("咨询", 14, Color(0xff3FB5AF), bold: true),
),
);
}
}
class StickyTabBarDelegate extends SliverPersistentHeaderDelegate {
final Widget child;
StickyTabBarDelegate({@required this.child});
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return this.child;
}
@override
double get maxExtent => 40;
@override
double get minExtent => 40;
@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
return true;
}
} }
...@@ -25,30 +25,6 @@ class MechanismBox implements IBottomPicker { ...@@ -25,30 +25,6 @@ class MechanismBox implements IBottomPicker {
} }
Widget build(BuildContext context) { Widget build(BuildContext context) {
return StreamBuilder(
stream: _model.stateLive.stream,
initialData: _model.stateLive.data ?? LOADING,
builder: (c, data) {
if (data.data == FAIL) {
return errorItem(MediaQuery.of(context).size.width,
MediaQuery.of(context).size.height, () {
_model.getQuestions(plan_id);
});
}
if (data.data == LOADING) {
return loadingItem();
}
return setupHome(context);
},
);
}
@override
void dispose() {
textController.dispose();
}
setupHome(context) {
MediaQueryData mq = MediaQuery.of(context); MediaQueryData mq = MediaQuery.of(context);
double keyHeight = MediaQuery.of(context).viewInsets.bottom; double keyHeight = MediaQuery.of(context).viewInsets.bottom;
return ClipRRect( return ClipRRect(
...@@ -58,17 +34,41 @@ class MechanismBox implements IBottomPicker { ...@@ -58,17 +34,41 @@ class MechanismBox implements IBottomPicker {
width: mq.size.width, width: mq.size.width,
height: mq.size.height - 140, height: mq.size.height - 140,
color: Colors.white, color: Colors.white,
child: Column( child: StreamBuilder(
mainAxisSize: MainAxisSize.max, stream: _model.stateLive.stream,
children: <Widget>[ initialData: _model.stateLive.data ?? LOADING,
title(mq), builder: (c, data) {
mechanismList(mq, keyHeight), if (data.data == FAIL) {
bottomMessage() return errorItem(MediaQuery.of(context).size.width,
], MediaQuery.of(context).size.height, () {
_model.getQuestions(plan_id);
});
}
if (data.data == LOADING) {
return loadingItem();
}
return setupHome(mq, keyHeight);
},
)), )),
); );
} }
@override
void dispose() {
textController.dispose();
}
setupHome(mq, keyHeight) {
return Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
title(mq),
mechanismList(mq, keyHeight),
bottomMessage()
],
);
}
// 弹窗标题 // 弹窗标题
Widget title(mq) { Widget title(mq) {
return Container( return Container(
...@@ -217,16 +217,14 @@ class MechanismBox implements IBottomPicker { ...@@ -217,16 +217,14 @@ class MechanismBox implements IBottomPicker {
fontSize: 12), fontSize: 12),
)), )),
Expanded( Expanded(
child: StreamBuilder<Pair<int, List<String>>>( child: StreamBuilder<List<String>>(
stream: _model.questionsLive.stream, stream: _model.questionsLive.stream,
initialData: _model.questionsLive.data ?? null, initialData: _model.questionsLive.data ?? null,
builder: (c, e) { builder: (c, e) {
print('dssdadsadas');
print(e.data.toString());
if (e.data == null) { if (e.data == null) {
return Container(); return Container();
} }
List<String> questions = e.data.second; List<String> questions = e.data;
return ListView.builder( return ListView.builder(
scrollDirection: Axis.horizontal, //横向滚动 scrollDirection: Axis.horizontal, //横向滚动
itemBuilder: (c, index) { itemBuilder: (c, index) {
...@@ -286,11 +284,10 @@ class MechanismBox implements IBottomPicker { ...@@ -286,11 +284,10 @@ class MechanismBox implements IBottomPicker {
NativeToast.showNativeToast('text'); NativeToast.showNativeToast('text');
} else { } else {
_model.sendMessage(doctor_ids, txt, plan_id); _model.sendMessage(doctor_ids, txt, plan_id);
dismissCall();
textController.text = '';
NativeToast.showNativeToast('消息已发送成功');
} }
// dismissCall();
// textController.text = '';
// NativeToast.showNativeToast('消息已发送成功');
} }
}, },
style: TextStyle(fontSize: 12), style: TextStyle(fontSize: 12),
......
...@@ -15,7 +15,7 @@ import 'package:gm_flutter/commonModel/util/PrintUtil.dart'; ...@@ -15,7 +15,7 @@ import 'package:gm_flutter/commonModel/util/PrintUtil.dart';
import 'package:gm_flutter/commonModel/bean/Pair.dart'; import 'package:gm_flutter/commonModel/bean/Pair.dart';
class MechanismModel extends BaseModel { class MechanismModel extends BaseModel {
LiveData<Pair<int, List<String>>> questionsLive = LiveData(); LiveData<List<String>> questionsLive = LiveData();
LiveData<int> stateLive = LiveData(); LiveData<int> stateLive = LiveData();
LiveData messageLive = LiveData(); LiveData messageLive = LiveData();
...@@ -27,17 +27,17 @@ class MechanismModel extends BaseModel { ...@@ -27,17 +27,17 @@ class MechanismModel extends BaseModel {
.listen((event) { .listen((event) {
if (event.error == 0) { if (event.error == 0) {
stateLive.notifyView(ENDLOADING); stateLive.notifyView(ENDLOADING);
questionsLive.notifyView(Pair(ENDLOADING, event.data.questions)); questionsLive.notifyView(event.data.questions);
} else { } else {
stateLive.notifyView(FAIL); stateLive.notifyView(FAIL);
questionsLive.notifyView(Pair(FAIL, null)); questionsLive.notifyView(null);
NativeToast.showNativeToast(event.message); NativeToast.showNativeToast(event.message);
} }
}) })
.addToDispose(rxDispose) .addToDispose(rxDispose)
.onError((err) { .onError((err) {
stateLive.notifyView(FAIL); stateLive.notifyView(FAIL);
questionsLive.notifyView(Pair(FAIL, null)); questionsLive.notifyView(null);
PrintUtil.printBug(err); PrintUtil.printBug(err);
}); });
} }
......
...@@ -10,7 +10,7 @@ import 'package:flutter/cupertino.dart'; ...@@ -10,7 +10,7 @@ import 'package:flutter/cupertino.dart';
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart' import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart'
as extend; as extend;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gm_flutter/ClueModel/page/levelTwo/LevelTwoPage.dart'; import 'package:gm_flutter/ClueModel/page/common/StickyTabBarDelegate.dart';
import 'package:gm_flutter/ClueModel/page/top/TopModel.dart'; import 'package:gm_flutter/ClueModel/page/top/TopModel.dart';
import 'package:gm_flutter/ClueModel/util/PosUtil.dart'; import 'package:gm_flutter/ClueModel/util/PosUtil.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart'; import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
...@@ -136,8 +136,8 @@ class TopPageState extends BaseState<TopPage> with TickerProviderStateMixin { ...@@ -136,8 +136,8 @@ class TopPageState extends BaseState<TopPage> with TickerProviderStateMixin {
List<Widget> list = []; List<Widget> list = [];
var d = MediaQueryData.fromWindow(window).padding.top; var d = MediaQueryData.fromWindow(window).padding.top;
for (int i = 0; i < _model.tabs.length; i++) { for (int i = 0; i < _model.tabs.length; i++) {
list.add(extend.NestedScrollViewInnerScrollPositionKeyWidget(Key("Tab${i}"), list.add(extend.NestedScrollViewInnerScrollPositionKeyWidget(
TopList(_model.tabs[i].id, kToolbarHeight + d))); Key("Tab${i}"), TopList(_model.tabs[i].id, kToolbarHeight + d)));
} }
return extend.NestedScrollView( return extend.NestedScrollView(
innerScrollPositionKeyBuilder: () { innerScrollPositionKeyBuilder: () {
......
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