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

相关推荐
m0_738185828 分钟前
Flutter 鸿蒙化实战:qr_code_scanner 适配 OpenHarmony,相机扫码实时识别
数码相机·flutter·华为·harmonyos·鸿蒙
传奇开心果编程19 小时前
【现代声明式UI学与练】第4课 列表渲染与 key——如何高效渲染列表、key 的作用、列表重排时的状态保持
学习·flutter·react native·ui·swiftui·android jetpack
m0_738185821 天前
Flutter 鸿蒙化实战:media_info 适配 OpenHarmony,媒体信息与缩略图
flutter·华为·harmonyos·鸿蒙·媒体
m0_738185821 天前
Flutter 鸿蒙化实战:just_audio 适配 OpenHarmony,功能强大的播放器
flutter·华为·harmonyos·鸿蒙
传奇开心果编程1 天前
【现代声明式UI学与练】第7课 组件通信——父传子、子传父、跨层级通信、状态提升与 Context
学习·flutter·react native·ui·swiftui·android jetpack
律宏阔2 天前
Flutter 列表图片内存优化:CachedNetworkImage 与 ClipRRect 的取舍
前端·flutter
律宏阔2 天前
Dart 3 Record:解决 Future.wait 异构返回值的类型问题
前端·flutter
伯伯熊勞2 天前
GetX 巢狀路由教學:用三層 Navigator 做桌面多欄佈局
flutter
传奇开心果编程2 天前
【现代声明式UI学与练】第9课 性能优化——渲染优化、列表优化、内存优化、启动优化
学习·flutter·react native·ui·性能优化·swiftui·android jetpack
m0_738185822 天前
Flutter 鸿蒙化实战:foundation_fluttify 适配 OpenHarmony,Fluttify 桥接层
flutter·华为·harmonyos·鸿蒙