Fluter InteractiveViewer 与ScrollView滑动冲突问题解决

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的方式达到目的。 如果有更好的实现方式可以在下方留言。

相关推荐
kirk_wang6 小时前
Flutter 导航锁踩坑实录:从断言失败到类型转换异常
前端·javascript·flutter
往来凡尘7 小时前
Flutter运行iOS26真机的两个问题
flutter·ios
yfmingo10 小时前
flutter项目大量使用.obs会导致项目性能极度下降吗
flutter
山璞10 小时前
Flutter3.32 中使用 webview4.13 与 vue3 项目的 h5 页面通信,以及如何调试
前端·flutter
ezeroyoung10 小时前
环信em_chat_uikit(Flutter)适配鸿蒙
flutter·华为·harmonyos
恋猫de小郭10 小时前
再次紧急修复,Flutter 针对 WebView 无法点击问题增加新的快速修复
android·前端·flutter
庄雨山12 小时前
Flutter+Riverpod+开源鸿蒙:新一代跨端状态管理实战
flutter·开源·openharmonyos
遝靑13 小时前
深入 Flutter 底层:自定义 RenderObject 实现高性能异形列表项
flutter