Vintage appMaker의 Tech Blog

[Flutter] InteractiveViewer를 listView안에 넣기 본문

Source code or Tip/Flutter & Dart

[Flutter] InteractiveViewer를 listView안에 넣기

VintageappMaker 2022. 8. 11. 21:43

 

InteractiveView는 핀치인아웃(두손가락 확대축소)으로 위젯을 확대/축소할 수 있는 위젯이다. 그런데 Listview 안에서 사용할 경우, Scroll 이벤트와 핀치인아웃 행위가 충돌되므로 매끄럽게 확대축소가 되지 못하거나 아예 안되는 경우가 발생한다. 그런 문제를 해결하기 위해서

 

(1) 상위위젯에 Listener 위젯으로 덮어씌워서

(2) 2 포인트 터치가 있을 경우

(3) ListView의 스크롤 기능을 비활성화


시키는 로직을 구현한다. onPointerDown과 onPoinerUp에서 down과 up의 포인터를 저장하여 down시 up과의 편차가 1이상이 나왔을 경우, 두손가락을 터치했다고 판단한다. 그 때에는 ListView의 physics 파라메터를 변경하여 스크롤을 하지 못하게( NeverScrollableScrollPhysics() ) 설정한다. 

 

[전체소스]

import 'dart:ui';

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final title = 'InteractiveViewer 예제';

  int nDown = 0;
  int nUp = 0;

  bool isEnableScroll = true;

  @override
  Widget build(BuildContext context) {
    Widget testItem(int n) {
      return Padding(
        padding: const EdgeInsets.all(8.0),
        child: InteractiveViewer(
          boundaryMargin: const EdgeInsets.all(5.0),
          minScale: 0.1,
          maxScale: 3.6,
          child: Image.network((n % 2 == 0)
              ? "https://i.discogs.com/SmIONVwpLyWK2PwD-46ujP9935T9heE70B2KzLU0eBs/rs:fit/g:sm/q:90/h:404/w:600/czM6Ly9kaXNjb2dz/LWRhdGFiYXNlLWlt/YWdlcy9BLTg0NzUy/LTE0NDc3NjY2NDEt/NjM0My5qcGVn.jpeg"
              : "https://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Logo_ACDC.svg/746px-Logo_ACDC.svg.png?20140903231808"),
        ),
      );
    }

    var onDownEVT = (PointerDownEvent e) {
      nDown = e.pointer;
      print("down: ${e.pointer}, ndown : ${nDown}");
      print("nDown - nUp: ${nDown - nUp}");

      if (nDown - nUp > 1) {
        setState(() {
          print("isEnableScroll = false");

          isEnableScroll = false;
        });
      }
    };
    var onUpEVT = (PointerUpEvent e) {
      nUp = e.pointer;
      print("up: ${e.pointer}, ndown : ${nUp}");

      if (nDown - nUp < 1) {
        setState(() {
          print("isEnableScroll = true");

          isEnableScroll = true;
        });
      }
    };

    return MaterialApp(
      title: title,
      home: Scaffold(
        body: Listener(
          onPointerDown: onDownEVT,
          onPointerUp: onUpEVT,
          child: ListView(
            physics: (isEnableScroll)
                ? const AlwaysScrollableScrollPhysics()
                : const NeverScrollableScrollPhysics(),
            children: <Widget>[
              for (var i = 0; i < 100; i++) ...{testItem(i)}
            ],
          ),
        ),
      ),
    );
  }
}

 

Comments