先看效果
实现代码
class OptionsTab extends StatefulWidget {const OptionsTab({Key key,}) : super(key: key);@override_OptionsTabState createState() => _OptionsTabState();}class _OptionsTabState extends State<OptionsTab> {ScrollController scrollController;List optionList;int _currentSelectedIndex = 0;@overridevoid initState() {optionList = ['全部','通知','作业','打卡','通知','作业','打卡','通知','作业','打卡','通知','作业','打卡',];scrollController = ScrollController();super.initState();}@overrideWidget build(BuildContext context) {return Container(padding: EdgeInsets.symmetric(vertical: 5),height: 30,color: Colors.white,child: ListView.builder(scrollDirection: Axis.horizontal,controller: scrollController,itemBuilder: (BuildContext context, int index) {bool selected = _currentSelectedIndex == index;return GestureDetector(behavior: HitTestBehavior.translucent,onTap: () {if (_currentSelectedIndex == index) {return;}ScrollPosition position = scrollController.position;print('position index:$index viewportDimension:${position.viewportDimension} minScrollExtent:${position.minScrollExtent} maxScrollExtent${position.maxScrollExtent}');/// 计算当前选中的 Tab 的 offsetdouble currentOffset = 50 * index.toDouble();/// 计算居中的 offsetdouble centerOffset = currentOffset + 25;/// 计算最终滚动的 offset 距离double absOffset = (centerOffset - position.viewportDimension / 2).clamp(position.minScrollExtent, position.maxScrollExtent).toDouble();print('currentOffset:$currentOffset centerOffset:$centerOffset absOffset:$absOffset');/// 通过 controller 滚动到对于的距离scrollController.animateTo(absOffset,duration: kTabScrollDuration, curve: Curves.ease);_currentSelectedIndex = index;setState(() {});},child: Container(margin: EdgeInsets.symmetric(horizontal: 5),decoration: BoxDecoration(color: selected ? Colors.white : Colors.grey[200],border: Border.all(color: selected ? Colors.blue : Colors.grey[300],),borderRadius: BorderRadius.circular(4)),child: Text('${optionList[index]}',style: TextStyle(color: selected ? Colors.blue : Colors.grey[500],fontSize: 10,),),alignment: Alignment.center,height: 30,width: 50,),);},itemCount: optionList?.length ?? 0,),);}}
使用上面的小算法就可以实现 listview 滚动到对应的 item
ScrollPosition position = scrollController.position;print('position index:$index viewportDimension:${position.viewportDimension} minScrollExtent:${position.minScrollExtent} maxScrollExtent${position.maxScrollExtent}');/// 计算当前选中的 Tab 的 offsetdouble currentOffset = 50 * index.toDouble();/// 计算居中的 offsetdouble centerOffset = currentOffset + 25;/// 计算最终滚动的 offset 距离double absOffset = (centerOffset - position.viewportDimension / 2).clamp(position.minScrollExtent, position.maxScrollExtent).toDouble();print('currentOffset:$currentOffset centerOffset:$centerOffset absOffset:$absOffset');/// 通过 controller 滚动到对于的距离scrollController.animateTo(absOffset,duration: kTabScrollDuration, curve: Curves.ease);

