Open xietian0908 opened 1 year ago
tabbar_v_square_indicator.zip ExtendedTabBar( // labelPadding: EdgeInsets.symmetric(horizontal: 50.w), indicatorPadding: const EdgeInsets.all(0), labelPadding: const EdgeInsets.only(bottom: 0), isScrollable: true, indicatorWeight: 0, scrollDirection: Axis.vertical, tabs: _tabs(read.airDevicesModelList), indicator: TabbarVSquareIndicator( length: read.airDevicesModelList.length, ), );
只有在快速滑动extendtabview 的时候点击extendtabbar才会出现,等待移动动画完成之后点击是没有问题的
- 错误信息呢?
- 提供可以运行的最小的例子
import 'package:extended_tabs/extended_tabs.dart';
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter/src/widgets/placeholder.dart';
class ExtendedTabsBug extends StatefulWidget {
const ExtendedTabsBug({super.key});
@override
State<ExtendedTabsBug> createState() => _ExtendedTabsBugState();
}
class _ExtendedTabsBugState extends State<ExtendedTabsBug> {
int length = 16;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: DefaultTabController(
length: length,
child: Row(
children: [
ExtendedTabBar(
// labelPadding: EdgeInsets.symmetric(horizontal: 50.w),
indicatorPadding: const EdgeInsets.all(0),
labelPadding: const EdgeInsets.only(bottom: 0),
isScrollable: true,
indicatorWeight: 0,
scrollDirection: Axis.vertical,
tabs: _tabs(),
indicator: TabbarVSquareIndicator(
length: length,
),
),
Expanded(
child: ExtendedTabBarView(
scrollDirection: Axis.vertical,
children: [
for (int i = 0; i < length; i++)
Container(
color: Colors.primaries[i],
alignment: Alignment.center,
child: Text('tabview $i'),
)
],
),
)
],
),
),
);
}
List<Widget> _tabs() {
return List.generate(
length,
(index) => Container(
height: 100,
margin: const EdgeInsets.only(bottom: 16),
alignment: Alignment.center,
child: Text('tab $index'),
),
);
}
}
class TabbarVSquareIndicator extends Decoration {
/// Height of the indicator. Defaults to 4
final double height;
final double width;
/// topRight radius of the indicator, default to 5.
final double topRightRadius;
/// topLeft radius of the indicator, default to 5.
final double topLeftRadius;
/// bottomRight radius of the indicator, default to 0.
final double bottomRightRadius;
/// bottomLeft radius of the indicator, default to 0
final double bottomLeftRadius;
/// Color of the indicator, default set to [Colors.black]
final Color color;
/// Horizontal padding of the indicator, default set 0
final double horizontalPadding;
/// [PagingStyle] determines if the indicator should be fill or stroke, default to fill
final PaintingStyle paintingStyle;
/// StrokeWidth, used for [PaintingStyle.stroke], default set to 2
final double strokeWidth;
final int length;
const TabbarVSquareIndicator({
this.length = 0,
this.height = 4,
this.width = 10,
this.topRightRadius = 2,
this.topLeftRadius = 2,
this.bottomRightRadius = 2,
this.bottomLeftRadius = 2,
this.color = Colors.red,
this.horizontalPadding = 0,
this.paintingStyle = PaintingStyle.fill,
this.strokeWidth = 4,
});
@override
CustomPainter createBoxPainter([VoidCallback? onChanged]) {
return CustomPainter(
this,
onChanged,
bottomLeftRadius: bottomLeftRadius,
bottomRightRadius: bottomRightRadius,
color: color,
height: height,
width: width,
horizontalPadding: horizontalPadding,
topLeftRadius: topLeftRadius,
topRightRadius: topRightRadius,
paintingStyle: paintingStyle,
strokeWidth: strokeWidth,
length: length,
);
}
}
class CustomPainter extends BoxPainter {
final TabbarVSquareIndicator decoration;
final double height;
final double topRightRadius;
final double topLeftRadius;
final double bottomRightRadius;
final double bottomLeftRadius;
final Color color;
final double horizontalPadding;
final double strokeWidth;
final PaintingStyle paintingStyle;
final double width;
final gradient = const LinearGradient(
colors: [Color(0xff0C87F3), Color(0xff0961AE)],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
);
final int length;
CustomPainter(
this.decoration,
VoidCallback? onChanged, {
required this.height,
required this.topRightRadius,
required this.topLeftRadius,
required this.bottomRightRadius,
required this.bottomLeftRadius,
required this.color,
required this.horizontalPadding,
required this.paintingStyle,
required this.strokeWidth,
required this.width,
required this.length,
}) : super(onChanged);
double yfun = 0;
double yfun2 = 0;
int index2 = 0;
Path path = Path();
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
Size mysize = Size(configuration.size!.width, configuration.size!.height - 16);
Size mysizeReal = Size(configuration.size!.width, configuration.size!.height);
radius = Size(configuration.size!.width, (configuration.size!.height - 16));
// Offset myoffset = Offset(offset.dx, offset.dy);
// final Rect rect = myoffset & mysize;
final Paint paint = Paint()
..strokeCap = StrokeCap.round
..color = color
..style = paintingStyle
..strokeWidth = strokeWidth;
int curIndex = (offset.dy / mysizeReal.height).round();
if (axis == Axis.horizontal) {
for (int i = 0; i < length; i++) {
Rect rect = Rect.fromCenter(center: Offset(0, 0 + i * configuration.size!.width), width: radius.width, height: radius.height);
RRect rrect = RRect.fromRectAndRadius(rect, const Radius.circular(10));
canvas.drawRRect(rrect, paint..color = const Color(0xff38424B));
}
curIndex = (offset.dx / mysizeReal.width).round();
canvas.translate(mysize.width / 2, mysize.height / 2);
// print('yfun index2:$index2 curIndex:$curIndex ${offset.dy} before:$before');
if (yfun == 0) {
yfun = mysizeReal.width;
}
if (curIndex != index2) {
yfun2 = (curIndex) * mysizeReal.width;
yfun = (curIndex - index2).abs() * mysizeReal.width;
index2 = curIndex;
}
_canvasInitRectangle(
canvas,
offset.dx,
yfun,
paint: paint..color = Colors.green,
path: path,
);
} else {
canvas.translate(mysize.width / 2, mysize.height / 2);
for (int i = 0; i < length; i++) {
Rect rect = Rect.fromCenter(center: Offset(0, 0 + i * configuration.size!.height), width: radius.width, height: radius.height);
RRect rrect = RRect.fromRectAndRadius(rect, const Radius.circular(10));
canvas.drawRRect(rrect, paint..color = const Color(0xff38424B));
}
curIndex = (offset.dy / mysizeReal.height).round();
print('${offset.dy}');
if (yfun == 0) {
yfun = mysizeReal.height;
before = (curIndex) * mysizeReal.height;
}
// if (!_isUsePosition(offset.dy, mysizeReal)) return;
if (curIndex != index2) {
yfun2 = (curIndex) * mysizeReal.height;
yfun = (curIndex - index2).abs() * mysizeReal.height;
index2 = curIndex;
}
_canvasInitRectangle(
canvas,
offset.dy,
yfun,
paint: paint..color = Colors.green,
path: path,
);
}
// print('=====y:${offset.dy} ${(offset.dy - yfun2).abs() / yfun} $yfun $yfun2');
// if (flag) yfun = 0;
// if (index2 != index.value) index2 = index.value;
// path = Path()
// ..moveTo(0, y)
// ..relativeLineTo(mysize.width, 0)
// ..relativeLineTo(0, mysize.height)
// ..relativeLineTo(-mysize.width + yfun, 0)
// ..close();
// canvas.drawPath(path, paint..color = color);
// canvas.translate(0, mysize.height);
// _canvasInit(
// canvas,
// offset.dy,
// yfun,
// paint: paint..color = Colors.green,
// path: path,
// );
}
late double changeValue = radius.width / 2; //变化值
Size radius = Size(60, 20);
Size get ctrlRadius => Size(radius.width * mX, radius.height * mY); //控制点radius
// final double mX = 0.551915024494; // 圆形
final double mY = 1; // 圆形
final double mX = 1; // 矩形
// final double mY = 1.1; // 矩形
Axis axis = Axis.vertical;
double before = 0;
bool isLeft(double offsetMove) {
bool flag = true;
if (before > offsetMove) flag = false;
before = offsetMove;
return flag;
}
Future<void> _canvasInitRectangle(
Canvas canvas,
double offsetMove,
double offsetEnd, {
required Path path,
required Paint paint,
}) async {
double percent = 0;
double cutOffsetLeft = 0; // 左 下
double cutOffsetRight = 0;
percent = (offsetMove - yfun2).abs() / yfun;
if (axis == Axis.horizontal) {}
if (!isLeft(offsetMove)) {
if (percent > 0 && percent <= 0.5) {
cutOffsetLeft = changeValue * percent;
} else if (percent > 0.5 && percent < 1.0) {
///坐标恢复,原本的位置 + 位移距离✖系数,系数为: 0.5 ~ 0
cutOffsetLeft = changeValue * (1 - percent);
}
radius = Size(radius.width - cutOffsetLeft, radius.height);
} else {
if (percent > 0 && percent <= 0.5) {
cutOffsetRight = changeValue * percent;
} else if (percent > 0.5 && percent < 1.0) {
///坐标恢复,原本的位置 + 位移距离✖系数,系数为: 0.5 ~ 0
cutOffsetRight = changeValue * (1 - percent);
}
radius = Size(radius.width - cutOffsetRight, radius.height);
}
cutOffsetLeft = 0; // 左 下
cutOffsetRight = 0;
// print('percent ${isLeft(offsetMove)} $percent cutOffsetRight:$cutOffsetRight cutOffsetLeft:$cutOffsetLeft }');
if (axis == Axis.vertical) {
Rect rect = Rect.fromCenter(center: Offset(0, 0 + offsetMove), width: radius.width, height: radius.height);
RRect rrect = RRect.fromRectAndRadius(rect, const Radius.circular(10));
canvas.drawRRect(rrect, paint);
} else {
Rect rect = Rect.fromCenter(center: Offset(0 + offsetMove, 0), width: radius.width, height: radius.height);
RRect rrect = RRect.fromRectAndRadius(rect, const Radius.circular(10));
canvas.drawRRect(rrect, paint);
}
}
Future<void> _canvasInit(
Canvas canvas,
double offsetMove,
double offsetEnd, {
required Path path,
required Paint paint,
}) async {
double percent = 0;
double cutOffsetLeft = 0; // 左 下
double cutOffsetRight = 0;
percent = (offsetMove - yfun2).abs() / yfun;
if (axis == Axis.horizontal) {}
if (!isLeft(offsetMove)) {
if (percent > 0 && percent <= 0.5) {
cutOffsetLeft = changeValue * percent;
} else if (percent > 0.5 && percent < 1.0) {
///坐标恢复,原本的位置 + 位移距离✖系数,系数为: 0.5 ~ 0
cutOffsetLeft = changeValue * (1 - percent);
}
radius = Size(radius.width - cutOffsetLeft, radius.height);
} else {
if (percent > 0 && percent <= 0.5) {
cutOffsetRight = changeValue * percent;
} else if (percent > 0.5 && percent < 1.0) {
///坐标恢复,原本的位置 + 位移距离✖系数,系数为: 0.5 ~ 0
cutOffsetRight = changeValue * (1 - percent);
}
radius = Size(radius.width - cutOffsetRight, radius.height);
}
cutOffsetLeft = 0; // 左 下
cutOffsetRight = 0;
// print('percent ${isLeft(offsetMove)} $percent cutOffsetRight:$cutOffsetRight cutOffsetLeft:$cutOffsetLeft }');
if (axis == Axis.vertical) {
Offset topPoint = Offset(0, -radius.height + offsetMove - cutOffsetRight);
Offset topPointEnd = Offset(radius.width, -radius.height - cutOffsetRight);
Offset topPointLeft = Offset(radius.width - ctrlRadius.width, -radius.height);
Offset topPointRight = Offset(ctrlRadius.width, 0 + cutOffsetRight);
Offset rPoint = Offset(radius.width, radius.height + cutOffsetRight);
Offset rPointTop = Offset(radius.width, radius.height - ctrlRadius.height + cutOffsetRight);
Offset rPointBottom = Offset(0, ctrlRadius.height);
Offset bottomPoint = Offset(-radius.width, radius.height + cutOffsetLeft);
Offset bottomPointLeft = Offset(-ctrlRadius.width, 0 - cutOffsetLeft);
Offset bottomPointRight = Offset(-(radius.width - ctrlRadius.width), radius.height);
Offset lPoint = Offset(-radius.width, -radius.height - cutOffsetLeft);
Offset lPointTop = Offset(0, -ctrlRadius.height);
Offset lPointBottom = Offset(-radius.width, -(radius.height - ctrlRadius.height) - cutOffsetLeft);
path.reset();
path.moveTo(topPoint.dx, topPoint.dy);
path.relativeCubicTo(topPointRight.dx, topPointRight.dy, rPointTop.dx, rPointTop.dy, rPoint.dx, rPoint.dy);
path.relativeCubicTo(rPointBottom.dx, rPointBottom.dy, bottomPointRight.dx, bottomPointRight.dy, bottomPoint.dx, bottomPoint.dy);
path.relativeCubicTo(bottomPointLeft.dx, bottomPointLeft.dy, lPointBottom.dx, lPointBottom.dy, lPoint.dx, lPoint.dy);
path.relativeCubicTo(lPointTop.dx, lPointTop.dy, topPointLeft.dx, topPointLeft.dy, topPointEnd.dx, topPointEnd.dy);
canvas.drawPath(path, paint);
} else {
Offset topPoint = Offset(0 + offsetMove, -radius.height);
Offset topPointEnd = Offset(radius.width + cutOffsetRight, -radius.height);
Offset topPointLeft = Offset(radius.width - ctrlRadius.width, -radius.height);
Offset topPointRight = Offset(ctrlRadius.width, 0);
Offset rPoint = Offset(radius.width + cutOffsetLeft, radius.height);
Offset rPointTop = Offset(radius.width + cutOffsetLeft, radius.height - ctrlRadius.height);
Offset rPointBottom = Offset(0, ctrlRadius.height);
Offset bottomPoint = Offset(-radius.width - cutOffsetLeft, radius.height);
Offset bottomPointLeft = Offset(-ctrlRadius.width, 0);
Offset bottomPointRight = Offset(-(radius.width - ctrlRadius.width) - cutOffsetLeft, radius.height);
Offset lPoint = Offset(-radius.width - cutOffsetRight, -radius.height);
Offset lPointTop = Offset(0, -ctrlRadius.height);
Offset lPointBottom = Offset(-radius.width - cutOffsetRight, -(radius.height - ctrlRadius.height));
path.reset();
path.moveTo(topPoint.dx, topPoint.dy);
path.relativeCubicTo(topPointRight.dx, topPointRight.dy, rPointTop.dx, rPointTop.dy, rPoint.dx, rPoint.dy);
path.relativeCubicTo(rPointBottom.dx, rPointBottom.dy, bottomPointRight.dx, bottomPointRight.dy, bottomPoint.dx, bottomPoint.dy);
path.relativeCubicTo(bottomPointLeft.dx, bottomPointLeft.dy, lPointBottom.dx, lPointBottom.dy, lPoint.dx, lPoint.dy);
path.relativeCubicTo(lPointTop.dx, lPointTop.dy, topPointLeft.dx, topPointLeft.dy, topPointEnd.dx, topPointEnd.dy);
canvas.drawPath(path, paint);
}
}
/// 是否是有效的移动点
bool _isUsePosition(double dy, Size mysizeReal) {
bool flag = true;
// print('$before $dy ${(before - dy).abs()} ${mysizeReal.height}');
if ((before - dy).abs() > mysizeReal.height / 4) flag = false;
before = dy;
return flag;
}
}
这个问题只有在快速滑动tabview的时候,在移动动画未结束之前点击,tabbar才会发生,这个没有报错信息只有中间的值变化突然有问题了offset.dy
你可以自己debug下。出错的时候的堆栈信息,看看问题出在哪里
controller.indexIsChanging为true的情况下就会出错
这个属性表示正在动画,主要是你写的 TabbarVSquareIndicator 逻辑过于复杂。你用自带的 ColorTabIndicator 有这个问题吗?
class ExtendedTabsStackoverflow extends StatefulWidget {
const ExtendedTabsStackoverflow({super.key});
@override
State<ExtendedTabsStackoverflow> createState() => _ExtendedTabsStackoverflowState();
}
class _ExtendedTabsStackoverflowState extends State<ExtendedTabsStackoverflow> {
int length = 16;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: DefaultTabController(
length: length,
child: Row(
children: [
ExtendedTabBar(
// labelPadding: EdgeInsets.symmetric(horizontal: 50.w),
indicatorPadding: const EdgeInsets.all(0),
labelPadding: const EdgeInsets.only(bottom: 0),
isScrollable: true,
indicatorWeight: 0,
scrollDirection: Axis.vertical,
tabs: _tabs(),
indicator: TabbarVSquareIndicator(
length: length,
),
),
Expanded(
child: ExtendedTabBarView(
scrollDirection: Axis.vertical,
children: [
for (int i = 0; i < length; i++)
Container(
color: Colors.primaries[i],
alignment: Alignment.center,
child: Text('tabview $i'),
)
],
),
)
],
),
),
);
}
List<Widget> _tabs() {
return List.generate(
length,
(index) => Container(
height: 100,
margin: const EdgeInsets.only(bottom: 16),
alignment: Alignment.center,
child: Text('tab $index'),
),
);
}
}
class TabbarVSquareIndicator extends Decoration {
final Color color;
final PaintingStyle paintingStyle;
final int length;
const TabbarVSquareIndicator({
this.length = 0,
this.color = Colors.red,
this.paintingStyle = PaintingStyle.fill,
});
@override
CustomPainter createBoxPainter([VoidCallback? onChanged]) {
return CustomPainter(
this,
onChanged,
paintingStyle: paintingStyle,
color: color,
length: length,
);
}
}
class CustomPainter extends BoxPainter {
final TabbarVSquareIndicator decoration;
final Color color;
final PaintingStyle paintingStyle;
final int length;
CustomPainter(
this.decoration,
VoidCallback? onChanged, {
required this.color,
required this.paintingStyle,
required this.length,
}) : super(onChanged);
Path path = Path();
Size radius = const Size(60, 20);
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
Size mysize = Size(configuration.size!.width, configuration.size!.height - 16);
radius = Size(configuration.size!.width, (configuration.size!.height - 16));
// Offset myoffset = Offset(offset.dx, offset.dy);
// final Rect rect = myoffset & mysize;
final Paint paint = Paint()
..strokeCap = StrokeCap.round
..color = color
..style = paintingStyle
..strokeWidth = 4;
canvas.translate(mysize.width / 2, mysize.height / 2);
for (int i = 0; i < length; i++) {
Rect rect = Rect.fromCenter(center: Offset(0, 0 + i * configuration.size!.height), width: radius.width, height: radius.height);
RRect rrect = RRect.fromRectAndRadius(rect, const Radius.circular(10));
canvas.drawRRect(rrect, paint..color = const Color(0xff38424B));
}
print('offset ==> ${offset.dy}');
Rect rect = Rect.fromCenter(center: Offset(0, 0 + offset.dy), width: radius.width, height: radius.height);
RRect rrect = RRect.fromRectAndRadius(rect, const Radius.circular(10));
canvas.drawRRect(rrect, paint..color = color);
}
}
抱歉 我这里弄了个简单的demo 也是会出现视频中item突然到第一个再回来的情况
https://github.com/fluttercandies/extended_tabs/assets/64937500/71d52bab-a9bb-4ebe-a4bf-78d353332147 我用demo for web 里面的例子也复现了,这个问题在水平方向也同样存在;多tab情况下更明显
web 的代码比较老了。用官方的 tab 会有这种问题吗?
import 'package:flutter/material.dart';
import 'package:extended_tabs/extended_tabs.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: const ExtendedTabsStackoverflow(),
);
}
}
class ExtendedTabsStackoverflow extends StatefulWidget {
const ExtendedTabsStackoverflow({super.key});
@override
State<ExtendedTabsStackoverflow> createState() => _ExtendedTabsStackoverflowState();
}
class _ExtendedTabsStackoverflowState extends State<ExtendedTabsStackoverflow> {
int length = 16;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: DefaultTabController(
length: length,
child: Column(
children: [
ExtendedTabBar(
// labelPadding: EdgeInsets.symmetric(horizontal: 50.w),
indicatorPadding: const EdgeInsets.all(0),
labelPadding: const EdgeInsets.only(bottom: 0),
isScrollable: true,
indicatorWeight: 0,
// scrollDirection: Axis.vertical,
tabs: _tabs(),
indicator: TabbarVSquareIndicator(
length: length,
),
),
Expanded(
child: ExtendedTabBarView(
// scrollDirection: Axis.vertical,
children: [
for (int i = 0; i < length; i++)
Container(
color: Colors.primaries[i],
alignment: Alignment.center,
child: Text('tabview $i'),
)
],
),
)
],
),
),
);
}
List<Widget> _tabs() {
return List.generate(
length,
(index) => Container(
height: 100,
width: 100,
margin: const EdgeInsets.only(bottom: 16),
alignment: Alignment.center,
child: Text('tab $index'),
),
);
}
}
class TabbarVSquareIndicator extends Decoration {
final Color color;
final PaintingStyle paintingStyle;
final int length;
const TabbarVSquareIndicator({
this.length = 0,
this.color = Colors.red,
this.paintingStyle = PaintingStyle.fill,
});
@override
CustomPainter createBoxPainter([VoidCallback? onChanged]) {
return CustomPainter(
this,
onChanged,
paintingStyle: paintingStyle,
color: color,
length: length,
);
}
}
class CustomPainter extends BoxPainter {
final TabbarVSquareIndicator decoration;
final Color color;
final PaintingStyle paintingStyle;
final int length;
CustomPainter(
this.decoration,
VoidCallback? onChanged, {
required this.color,
required this.paintingStyle,
required this.length,
}) : super(onChanged);
Path path = Path();
Size radius = const Size(60, 20);
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
Size mysize = Size(configuration.size!.width, configuration.size!.height - 16);
radius = Size(configuration.size!.width, (configuration.size!.height - 16));
// Offset myoffset = Offset(offset.dx, offset.dy);
// final Rect rect = myoffset & mysize;
final Paint paint = Paint()
..strokeCap = StrokeCap.round
..color = color
..style = paintingStyle
..strokeWidth = 4;
canvas.translate(mysize.width / 2, mysize.height / 2);
for (int i = 0; i < length; i++) {
Rect rect = Rect.fromCenter(center: Offset(0 + i * configuration.size!.width, 0), width: radius.width, height: radius.height);
RRect rrect = RRect.fromRectAndRadius(rect, const Radius.circular(10));
canvas.drawRRect(rrect, paint..color = const Color(0xff38424B));
}
print('offset ==> ${offset.dy}');
Rect rect = Rect.fromCenter(center: Offset(0 + offset.dx, 0), width: radius.width, height: radius.height);
RRect rrect = RRect.fromRectAndRadius(rect, const Radius.circular(10));
canvas.drawRRect(rrect, paint..color = color);
}
}
官方只有水平的 我测试了extendedtabbar extendedtabview 、和 tabbar tabview 例子中换一下 官方的是没有问题的
你不是说水平也有问题吗? 水平跟官方的代码一模一样的
这是水平的
用你的例子在真机上面,没有重现。水平和垂直都没有重现
我就是用真机android平板测的, extended_tabs: ^4.0.2;然后那个异常好像必须得是连续移动两格移动未结束的时候点击tabbar会出现;你可以看那个视频都是同一套代码只是换了个widget
Version
extended_tabs: ^4.0.2
Platforms
Android
Device Model
galaxy tab A7 (Android 11)
flutter info
How to reproduce?
https://github.com/fluttercandies/extended_tabs/assets/64937500/063f7772-2b35-4563-84ca-fb948a37e20c
Logs
No response
Example code (optional)
No response
Contact
No response