[Flutter] Draggable 위젯

GH lee·2023년 6월 12일
0

Dart/Flutter

목록 보기
3/12

Draggable

위젯을 다른 위젯 위로 드래그 시킬 수 있는 위젯
Draggable 위젯과 DragTarget 위젯으로 드래그 할 위젯과 드래그해서 갖다 놓을 위젯을 만들 수 있다
플러터 공식 유튜브 채널을 보다가 재밌어보여서
고양이에게 츄르를 먹이는 앱을 만들어 보았다

동작화면

Draggable 위젯

data
위젯이 가지는 데이터를 설정

feedback
위젯을 클릭하여 드래그하는 동안에 보여지는 위젯

childWhenDragging
위젯을 드래그 하는 동안 원래 위젯이 있던 자리에 그려지는 위젯

child
드래그하기 전 생성되어있는 위젯

axis
드래그 방향 지정, Axis.horizontal과 Axis.vertical

이 외의 속성은 공식문서를 참조하자
https://api.flutter.dev/flutter/widgets/Draggable-class.html

example

Draggable(
  data: '츄르',
  feedback: RotatedBox(
    quarterTurns: 1,
    child: Image.network(
      'https://cdnimg.catpang.com/catpang/data/goods/2/1715_web_original_1491832849664054.jpg',
      width: 100,
      height: 100,
    ),
  ),
  childWhenDragging: const SizedBox(
    width: 100,
    height: 100,
  ),
  child: RotatedBox(
    quarterTurns: 1,
    child: Image.network(
      'https://cdnimg.catpang.com/catpang/data/goods/2/1715_web_original_1491832849664054.jpg',
      width: 100,
      height: 100,
    ),
  ),
),

DragTarget 위젯

onAccept
Draggable 위젯이 드래그되어 target에 놓여졌을 때 동작
onAccept: (data) {}
data는 draggable 위젯이 가진 data

onLeave
Draggable 위젯이 target위에 있다가 밖으로 나갔을 때 동작
onLeave: (data) {}

onMove
Draggable 위젯이 target위에서 움직이는 동안 동작
onMove: (details) {}
details는 data와 offset을 가진다

onAcceptWithDetails
onAccept시 details로 offset을 가져올 수 있다
onAcceptWithDetails: (details) {}

onWillAccept
target이 Accept를 할지 말지를 결정
onWillAccept: (data) {return true;}

example

DragTarget(
  builder: (context, candidateData, rejectedData) {
    return !isEat
        ? Image.asset(
            'asset/image/draggable/cat.png',
            height: 250,
          )
        : Image.asset(
            'asset/image/draggable/cat_heart.gif',
            height: 250,
          );
  },
  onAccept: (data) {
    if (data == '츄르') {
      setState(() {
        isEat = !isEat;
      });
    }
  },
  onLeave: (data) {
    debugPrint('onLeave $data');
  },
  onMove: (details) {
    debugPrint('onMove ${details.data}');
    debugPrint('onMove ${details.offset}');
  },
  onAcceptWithDetails: (details) {
    debugPrint('onAcceptWithDetails ${details.offset}');
  },
  onWillAccept: (data) {
    return true;
  },
),

전체코드

import 'package:flutter/material.dart';

class DraggablePage extends StatefulWidget {
  const DraggablePage({super.key});

  
  State<DraggablePage> createState() => _DraggablePageState();
}

class _DraggablePageState extends State<DraggablePage> {
  bool isEat = false;

  
  Widget build(BuildContext context) {
    if (isEat) {
      Future.delayed(const Duration(milliseconds: 2500)).then((_) {
        setState(() {
          isEat = !isEat;
        });
      });
    }
    return DefaultLayout(
      title: 'Draggable 테스트',
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            DragTarget(
              builder: (context, candidateData, rejectedData) {
                return !isEat
                    ? Image.asset(
                        'asset/image/draggable/cat.png',
                        height: 250,
                      )
                    : Image.asset(
                        'asset/image/draggable/cat_heart.gif',
                        height: 250,
                      );
              },
              onAccept: (data) {
                if (data == '츄르') {
                  setState(() {
                    isEat = !isEat;
                  });
                }
              },
              onLeave: (data) {
                debugPrint('onLeave $data');
              },
              onMove: (details) {
                debugPrint('onMove ${details.data}');
                debugPrint('onMove ${details.offset}');
              },
              onAcceptWithDetails: (details) {
                debugPrint('onAcceptWithDetails ${details.offset}');
              },
              onWillAccept: (data) {
                return true;
              },
            ),
            const SizedBox(
              height: 100,
            ),
            Draggable(
              data: '츄르',
              feedback: RotatedBox(
                quarterTurns: 1,
                child: Image.network(
                  'https://cdnimg.catpang.com/catpang/data/goods/2/1715_web_original_1491832849664054.jpg',
                  width: 100,
                  height: 100,
                ),
              ),
              childWhenDragging: const SizedBox(
                width: 100,
                height: 100,
              ),
              child: RotatedBox(
                quarterTurns: 1,
                child: Image.network(
                  'https://cdnimg.catpang.com/catpang/data/goods/2/1715_web_original_1491832849664054.jpg',
                  width: 100,
                  height: 100,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

고양이 짤은 픽사베이에서 가져왔다
https://pixabay.com/ko/gifs/%EA%B3%A0%EC%96%91%EC%9D%B4-%EC%82%AC%EB%9E%91-%ED%82%A4%EC%8A%A4-%EB%A7%88%EC%9D%8C-133/

profile
Flutter Junior

0개의 댓글