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

相关推荐
恋猫de小郭14 小时前
苹果 AirPods 协议,Android 也可以使用完整版 AirPods 能力
android·前端·flutter
张风捷特烈15 小时前
Flutter 类库大揭秘#01 | path_provider架构与设计
android·flutter
恋猫de小郭3 天前
Android 限制侧载新进展,谷歌联合国内厂商推验证计划
android·前端·flutter
恋猫de小郭3 天前
解读 Android 17 全新内存限制,有没有“豁免”后门?
android·前端·flutter
程序员老刘6 天前
跨平台开发地图 | 2026年6月
flutter·ai编程·客户端
悟空瞎说6 天前
Flutter 架构详解:新手必懂底层原理
flutter
SoaringHeart6 天前
Flutter最佳实践:IM聊天文字链接自动识别跳转
前端·flutter
恋猫de小郭7 天前
KMP / CMP 鸿蒙版本 Beta 发布,他有什么特别之处?
android·前端·flutter
风华圆舞7 天前
Flutter + 鸿蒙 Intents Kit:页面直达能力的完整接入方案
flutter·ui·华为·harmonyos
韩曙亮7 天前
【Flutter】Flutter 组件 ④ ( 组件渲染 的 三棵树理论 | Widget 树 → Element 树 → RenderObject 树 )
flutter·element·widget·renderobject