【问题标题】:How to fix SingleChildScrollView and InteractiveViewer gesture conflict如何修复 SingleChildScrollView 和 InteractiveViewer 手势冲突
【发布时间】:2022-10-23 18:28:58
【问题描述】:

我在 SingleChildScrollView 中使用 InteractiveViewer,这是我的完整代码:

import 'package:flutter/material.dart';
import '../constants/images.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  final List<String> images = [Images.IMG1, Images.IMG2, Images.IMG3];

  MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: SingleChildScrollView(
          child: Column(
            children: [
              for (var image in images) ...[
                SizedBox(width:double.infinity,child: Divider(thickness: 5,)),
                Row(
                  children: [
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: ClipOval(
                        child: CircleAvatar(
                          radius: 24,
                          child: Image.asset(Images.PROFILE_IMAGE),
                        ),
                      ),
                    ),
                    Text('User1'),
                  ],
                ),
                InteractiveViewer(
                    child: Image.asset(
                  image,
                  fit: BoxFit.fitWidth,
                )),
                Row(
                  children: [
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Icon(Icons.favorite),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Icon(Icons.comment),
                    ),
                  ],
                )
              ]
            ],
          ),
        ),
      ),
    );
  }
}

问题是当我尝试放大或缩小我的 InteractiveViewer 时,它通常在第一次尝试时不起作用,我需要在不同的触摸位置尝试 5-6 次才能工作,在 SingleChildScrollView 中使用 InteractiveViewer 非常困难,但没有 SingleChildScrollView 也能完美运行,请参阅下面的剪辑:

有什么解决办法吗?

【问题讨论】:

    标签: flutter flutter-layout singlechildscrollview


    【解决方案1】:

    似乎SingleChildScrollViewInteractiveViewer 之间为了采取触摸动作而发生了争执。

    以 Instagram 的滚动机制为例,如果我们将两根手指放在帖子上并尝试滚动,滚动动作将不会完成,并且滚动会暂时被禁用。 所以如果我们能检测到这两个手指的触摸动作:

    谢谢: https://stackoverflow.com/a/72421013/14083299

    我们可以禁用滚动,然后放大/缩小。

    这是一个示例代码:

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatefulWidget {
      MyApp({Key? key}) : super(key: key);
    
      @override
      State<MyApp> createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      final List<String> images = [
        'assets/prof2.jpg',
        'assets/prof2.jpg',
        'assets/prof2.jpg'
      ];
    
      final events = [];
      bool canScroll = true;
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          home: Scaffold(
            body: SingleChildScrollView(
              physics: canScroll
                  ? const ScrollPhysics()
                  : const NeverScrollableScrollPhysics(),
              child: Listener(
                onPointerDown: (event) {
                  events.add(event.pointer);
                  print("new event");
                },
                onPointerUp: (event) {
                  events.clear();
                  print("events cleared");
                  setState(() {
                    canScroll = true;
                  });
                },
                onPointerMove: (event) {
                  if (events.length == 2) {
                    setState(() {
                      canScroll = false;
                    });
                    //   int sensitivity = 8;
                    //   if (event.delta.dy > sensitivity) {
                    //     // code for two finger swipe up event
    
                    //   } else if (event.delta.dy < -sensitivity) {
                    //     // code for two finger swipe down event
    
                    //   }
                  }
                },
                child: Container(
                  child: Column(
                    children: [
                      for (var image in images) ...[
                        const SizedBox(
                            width: double.infinity,
                            child: Divider(
                              thickness: 5,
                            )),
                        Row(
                          children: [
                            Padding(
                              padding: const EdgeInsets.all(8.0),
                              child: ClipOval(
                                child: CircleAvatar(
                                  radius: 24,
                                  child: Image.asset('assets/prof2.jpg'),
                                ),
                              ),
                            ),
                            const Text('User1'),
                          ],
                        ),
                        InteractiveViewer(
                            child: Image.asset(
                          image,
                          fit: BoxFit.fitWidth,
                        )),
                        Row(
                          children: const [
                            Padding(
                              padding: EdgeInsets.all(8.0),
                              child: Icon(Icons.favorite),
                            ),
                            Padding(
                              padding: EdgeInsets.all(8.0),
                              child: Icon(Icons.comment),
                            ),
                          ],
                        )
                      ]
                    ],
                  ),
                ),
              ),
            ),
          ),
        );
      }
    }
    

    【讨论】:

      【解决方案2】:

      感谢@samad-karimi 的回答,我终于用 Listener Widget 解决了这个问题。 这是来自@samad-karimi 代码的优化代码:

      class MyApp2 extends StatefulWidget {
        MyApp2({Key? key}) : super(key: key);
      
        @override
        State<MyApp2> createState() => _MyApp2State();
      }
      
      class _MyApp2State extends State<MyApp2> {
        final List<String> images = [Images.IMG1, Images.IMG2, Images.IMG3];
        int _pointersCount = 0;
      
        @override
        Widget build(BuildContext context) {
          return MaterialApp(
            debugShowCheckedModeBanner: false,
            home: Scaffold(
              body: Listener(
                onPointerDown: (_) => setState(() => _pointersCount++),
                onPointerUp: (_) => setState(() => _pointersCount--),
                child: ListView(
                  physics: _pointersCount == 2 ? const NeverScrollableScrollPhysics() : null,
                  children: [
                    for (var image in images) ...[
                      const SizedBox(width: double.infinity, child: Divider(thickness: 5)),
                      Row(
                        children: [
                          Padding(
                            padding: const EdgeInsets.all(8.0),
                            child: ClipOval(
                              child: CircleAvatar(
                                radius: 24,
                                child: Image.asset(Images.PROFILE_IMAGE),
                              ),
                            ),
                          ),
                          const Text('User1'),
                        ],
                      ),
                      InteractiveViewer(child: Image.asset(image, fit: BoxFit.fitWidth)),
                      Row(
                        children: const [
                          Padding(padding: EdgeInsets.all(8.0), child: Icon(Icons.favorite)),
                          Padding(padding: EdgeInsets.all(8.0), child: Icon(Icons.comment)),
                        ],
                      )
                    ]
                  ],
                ),
              ),
            ),
          );
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-22
        • 2016-05-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多