之前开发电商的功能时,需要做商品界面,UI基本是参考京东、淘宝的效果,以前android原生开发的时候觉得很好做,切到Flutter之后只能自己想办法,所以自己后来做出了这样的效果,分享下实现方案。 先看效果图吧
效果图比较
这是京东的效果 下图是我做的效果,基本和京东的保持一致,点击tab可快速切换到某一页,滑动列表tab自动切换。
思路
仔细查看京东的商品详情页,可以整理出下面三点
1.tabbar随着慢慢滑动一定距离会变透明,再次滑到顶部则重新变成不透明 2.滑动的过程中,到达新的页面内容,顶部的tab下标会自动切换到当前的内容下标 3.点击tab中的某一项,页面则会自动滑动到相应页面
整体的思路其实就是最重要的一点,得到商品页的高度。得到了商品页的高度,再通过滑动事件针对偏移量进行操作,我们就可以做到上面的三件事。
方案
-
上面提到最重要的是得到商品的高度,那么在flutter中如何得到widget的高度呢?我通过查询资料得到了最后的答案。获取到widget的size,从而获得它的height属性。这里还有一个坑,一些异步加载的布局,你有时候直接去拿获取不到正确值,需要等页面加载完成才能真正获取到大小。 在flutter中可以使用GlobalKey获取到控件的大小,使用 GlobalKey 的步骤如下:
1.创建globalkey对象 ,GlobalKey _globalKey = GlobalKey(); 2.将widget设置globalkey属性,key: _goodsKey, 3.通过globalkey字段获取到Size
这三个步骤是获取到上面效果最关键的步骤。 -
还有一个就是滑动监听,这边用到了flutter的SingleChildScrollView控件中的ScrollController,通过监听回调,返回当前的偏移量,从而与商品高度进行比较更新界面。 _scrollController.addListener(() {
...
});
-
另外两个简单的逻辑是tab的切换和点击,这个flutter自带的tab控件使用方法很简单,可以自行参考。
编码实现
这里只放部分代码,我会把整个demo上传到github上面去,需要的可以自己拿。
计算商品页面widget高度的代码:
void calculateHeight() {
_goodHeight =
getSize(_goodsKey.currentContext) - (Platform.isIOS ? 88 : 50);
print("calculateHeight $_goodHeight");
}
double getSize(BuildContext buildContext) {
final RenderBox box = buildContext.findRenderObject();
final size = box.size;
return size.height;
}
整体布局界面代码:
@override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: buildBottomBar(),
body: Stack(
children: [
SingleChildScrollView(
controller: _scrollController,
child: Column(
children: [
Container(
key: _goodsKey,
child: GoodsInfoPage(),
),
Container(
child: _html,
),
],
),
),
Opacity(
opacity: toolbarOpacity,
child: Container(
height: 78,
color: Colors.red,
child: buildTopBar(),
),
)
],
),
);
}
还有滑动监听的处理逻辑
_scrollController.addListener(() {
double t = _scrollController.offset / DEFAULT_SCROLLER;
if (t < 0.0) {
t = 0.0;
} else if (t > 1.0) {
t = 1.0;
}
if (mounted) {
setState(() {
toolbarOpacity = t;
});
}
if (_scrollController.offset >= _goodHeight) {
_tabController.animateTo(1);
} else {
_tabController.animateTo(0);
}
});
难度其实也不是很大,但是整体的思路和方案才是最难的,当然也有其他一些实现方式,欢迎交流。
源码
Demo地址:https://github.com/shudaizisd/Flutter_Shop 如果有不对的地方,欢迎指出。
|