效果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