InteractiveViewer是Flutter比较少用到的组件,它的作用是能够通过手势放大和缩小某个Widget。 某些需求,比如报表需要可以通过手势去放大和缩小,报表本身又是可以上下滑动的。这个时候可能用InteractiveViewer包裹ScrollView。
但由于两个组件都是手势操作,而且ScrollView的优先级会更高,就造成InteractiveViewer在纵向上缩放不灵敏。
现在想到一个解决的笨办法就是通过判断手势的个数去禁用ScrollView的滑动。
以下为实现代码:
dart
import 'package:flutter/cupertino.dart';
//解决上下滑动与放大缩手势冲突问题,判断多点触控,如果大于一点则禁用滑动
class InteractiveScrollView extends StatefulWidget {
final List<Widget> slivers;
final double minScale;
final double maxScale;
const InteractiveScrollView(
{super.key, required this.slivers, this.minScale = 1, this.maxScale = 5});
@override
State<InteractiveScrollView> createState() => _InteractiveScrollViewState();
}
class _InteractiveScrollViewState extends State<InteractiveScrollView> {
int pointerCount = 0;
bool scrollable = true;
void checkScrollable() {
if (pointerCount >= 2) {
if (scrollable) {
setState(() {
scrollable = false;
});
}
} else {
if (!scrollable) {
setState(() {
scrollable = true;
});
}
}
}
void _onPointerDown(PointerDownEvent details) {
pointerCount++;
checkScrollable();
}
void _onPointerCancel(PointerCancelEvent details) {
pointerCount = 0;
checkScrollable();
}
void _onPointerUp(PointerUpEvent details) {
pointerCount--;
checkScrollable();
}
@override
Widget build(BuildContext context) {
return Listener(
onPointerDown: _onPointerDown,
onPointerUp: _onPointerUp,
onPointerCancel: _onPointerCancel,
child: InteractiveViewer(
minScale: widget.minScale,
maxScale: widget.maxScale,
child: CustomScrollView(
physics: scrollable
? const ClampingScrollPhysics()
: const NeverScrollableScrollPhysics(),
slivers: widget.slivers
)
)
);
}
@override
void didUpdateWidget(covariant InteractiveScrollView oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.maxScale != widget.maxScale ||
oldWidget.minScale != widget.minScale) {
setState(() {});
}
}
}
上面代码是将InteractiveViewer与CustomScrollView集合,实际上可以是任何滑动组件。 实现的原理也很简单粗暴,就是通过监听手势按下的数量pointerCount,如果大于2则将 CustomScrollView的physics属性设置为NeverScrollableScrollPhysics。
这种实现方式虽然能够达到需求,但感觉不够优雅,或许可以通过重写ScrollPhysics的方式达到目的。 如果有更好的实现方式可以在下方留言。