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

相关推荐
技术任我行XTing7 小时前
【DFX系列】Flutter 鸿蒙应用外接纹理介绍及问题定位
flutter·harmonyos
恋猫de小郭9 小时前
Flutter GSoC 2026 提案进度解读,补上 DevTools、FFI 和原生平台的关键缺口
android·前端·flutter
●VON1 天前
Flutter 鸿蒙插件适配实战:用 flutter_native_timezone_2025 1.0.1 读取当前时区与系统目录
flutter·华为·harmonyos·鸿蒙
黑科技iOS上架1 天前
iOS深度混淆flutter应用的最佳实践
flutter·ios·混淆·审核·深度混淆
恋猫de小郭1 天前
CPF-Flutter 社区提出折叠场景分栏(平行视界) 方案
android·前端·flutter
程序员老刘2 天前
Android Studio Quail 4发布,看日志我以为谷歌放弃Flutter了
flutter·android studio·ai编程
Crazy_MT2 天前
Flutter 本地大模型实战:做一个自然语言记账工具
flutter·llm·ai编程
嵩风抚2 天前
一款HK银行APP的业务+技术
android·flutter·react native·html5
不羁的木木2 天前
给鸿蒙 App 增加广播收发能力 —— flutter_broadcasts 的鸿蒙使用指南
flutter·harmonyos