效果gif
定义属性
final tabBarHeight = useRef(42.0);
final items = useRef(['产品详情', '购买须知', '服务评价']
.map((e) => Tab(
height: 40,
text: e,
))
.toList());
final tabC = useTabController(initialLength: items.value.length);
final scroller = useScrollController();
final isTabClicked = useRef(false);
final keys = useRef([
GlobalKey(debugLabel: 'tab1'),
GlobalKey(debugLabel: 'tab2'),
GlobalKey(debugLabel: 'tab3'),
]);
定义监听
useEffect(() {
void tabCL() {
if (tabC.indexIsChanging) {
isTabClicked.value = true;
final keyRenderObject = keys.value[tabC.index].currentContext
?.findAncestorRenderObjectOfType();
scroller.position
.ensureVisible(keyRenderObject!,
duration: const Duration(milliseconds: 300),
curve: Curves.easeIn)
.then((value) {
isTabClicked.value = false;
});
}
}
void scrL() {
if (isTabClicked.value) return;
int i = 0;
for (; i < keys.value.length; i++) {
final keyRenderObject =
keys.value[i].currentContext?.findAncestorRenderObjectOfType();
if (keyRenderObject != null) {
final offsetY =
(keyRenderObject.parentData as SliverPhysicalParentData)
.paintOffset
.dy;
if (offsetY > tabBarHeight.value) {
break;
}
}
}
tabC.index = i > 0 ? i - 1 : 0;
}
tabC.addListener(tabCL);
scroller.addListener(scrL);
return () {
tabC.removeListener(tabCL);
scroller.removeListener(scrL);
tabC.dispose();
scroller.dispose();
};
}, [3]);
每个组件设置Key
CustomScrollView(
controller: scroller,
slivers: [
SliverAppBar(
backgroundColor: Colors.transparent,
pinned: true,
toolbarHeight: 0,
expandedHeight: 380,
flexibleSpace: const FlexibleSpaceBar(
background: HeaderProductDetail(),
),
bottom: PreferredSize(
preferredSize: Size.fromHeight(tabBarHeight.value),
child: Container(
color: Colors.white,
child: TabBar(
tabs: items.value,
controller: tabC,
unselectedLabelColor: Colors.grey,
indicator: context.extensions.underlineTabIndicator,
),
),
),
),
SliverToBoxAdapter(
child: Container(
key: keys.value[0],
height: Screens.height,
width: double.infinity,
color: Colors.red,
child: Text("==============="),
),
),
SliverToBoxAdapter(
child: Container(
key: keys.value[1],
height: Screens.height,
width: double.infinity,
color: Colors.yellow,
child: Text("==============="),
),
),
SliverToBoxAdapter(
child: Container(
key: keys.value[2],
height: Screens.height,
width: double.infinity,
color: Colors.blue,
child: Text("==============="),
),
)
],
)
参考
Flutter TabBar实现描点滚动绑定
源码 感觉有用的话,star一下
github地址
如果想一起学习进步 QQ群766903559