作为ListView的子级时,不会触发Flutter GestureDetector onScaleStart

waxmsbnn  于 2023-10-22  发布在  Flutter
关注(0)|答案(1)|浏览(140)

我有一个ListView,里面有一个GestureDetector +其他项目。我注意到,当页面有足够的内容需要滚动条时,onScaleStart从来不会被触发,但onTap会被触发(listview滚动正在“消耗”向上向下滑动事件)。
如果我把项目放在ListView之外,它会按预期工作并扩展
有办法解决吗?我需要有一个ListView内的gesturedetector,因为下面还有其他项目,我需要滚动条
请注意,如果内容很少并且滚动条未激活,onScaleStart可以正常工作。如果我有足够的小部件来触发ListView使用滚动条,那么onScaleStart永远不会被触发。
一些极简的代码来展示它,从真实的代码中提取

import 'package:flutter/material.dart';

class ExampleWidget extends StatelessWidget {
  const ExampleWidget({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        ListView(
          controller: _scrollController,
          padding: const EdgeInsets.only(bottom: 60),
          children: [
            Stack(
              alignment: Alignment.bottomCenter,
              children: <Widget>[
                GestureDetector(
                  onScaleStart: () {
                    // never called when there are enough widgets to enable the scroll of listview
                  },
                  onScaleUpdate: () {
                    // never called when there are enough widgets to enable the scroll of listview
                  },
                  child: Transform(
                    alignment: Alignment.centerLeft,
                    transform: Matrix4.identity()
                      ..scale(_scale, _scale),
                    child: SomeChild(),
                  ),
                ),
                Container(
                    alignment: Alignment.bottomRight,
                    child: IconButton(
                      icon: const Icon(
                        AppIcons.three_dots_vertical,
                        size: 20,
                        color: Colors.white70,
                      ),
                    )),
              ],
            ),
            Padding(
                padding: const EdgeInsets.all(Dimen.spacingSmall),
                child: OtherWidget())
          ],
        ),
        Positioned(
            bottom: 0,
            child: SomeOtherWidget())
      ],
    );
  }
}
wsewodh2

wsewodh21#

Flutter似乎在区分滚动和缩放手势方面存在问题。我建议使用Listener。根据记录的点击事件数,您可以调整ListView的滚动性。这里有一个快速指南,你可以破解系统。
引入两个状态变量:_touchPoints用于计算屏幕上活动触摸点的数量,_isScrollable用于确定ListView是否应可滚动。

int _touchPoints = 0;
bool _isScrollable = true;

使用Listener检测触摸点:用Listener包裹ListView以检测触摸点。

Listener(
  onPointerDown: (_) => _touchPoints++,
  onPointerUp: (_) => _touchPoints--,
  //...
)

切换可滚动性:在触摸点检测回调中,根据活动触摸点的数量切换_isScrollable

setState(() {
  if (_touchPoints > 1) _isScrollable = false;
  else _isScrollable = true;
});

设置ListView物理:concept基于_isScrollable设置了ListView的物理特性。

ListView(
  physics: _isScrollable ? AlwaysScrollableScrollPhysics() : NeverScrollableScrollPhysics(),
  //...
)

相关问题