상세 컨텐츠

본문 제목

제스처와 애니메이션 결합하기

공부/Flutter

by micalcomanie 2025. 1. 3. 15:56

본문

728x90
반응형
SMALL

Flutter는 제스처와 애니메이션을 결합하여 사용자 인터랙션을 풍부하게 만드는 강력한 도구를 제공합니다.
이 글에서는 Flutter에서 제스처와 애니메이션을 결합하는 방법과 이를 활용한 사례를 소개합니다.


1. Flutter의 제스처와 애니메이션

Flutter는 다양한 제스처(탭, 드래그, 스와이프 등)와 애니메이션을 쉽게 구현할 수 있는 위젯과 도구를 제공합니다.

1.1 주요 제스처 위젯

  • GestureDetector: 다양한 제스처를 감지.
  • InkWell: 클릭 효과를 추가한 탭 감지.

1.2 주요 애니메이션 도구

  • AnimationController: 애니메이션을 제어.
  • Tween: 애니메이션의 시작과 끝 값을 정의.
  • AnimatedBuilder: 애니메이션과 UI를 결합.

2. 기본 예제: 탭 애니메이션

버튼을 탭하면 크기가 커졌다가 작아지는 애니메이션을 구현합니다.

예제 코드

import 'package:flutter/material.dart';

class TapAnimationExample extends StatefulWidget {
  @override
  _TapAnimationExampleState createState() => _TapAnimationExampleState();
}

class _TapAnimationExampleState extends State<TapAnimationExample> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _scaleAnimation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 200),
    );

    _scaleAnimation = Tween<double>(begin: 1.0, end: 1.2).animate(
      CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
    );
  }

  void _onTapDown(TapDownDetails details) {
    _controller.forward();
  }

  void _onTapUp(TapUpDetails details) {
    _controller.reverse();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Tap Animation')),
      body: Center(
        child: GestureDetector(
          onTapDown: _onTapDown,
          onTapUp: _onTapUp,
          child: AnimatedBuilder(
            animation: _scaleAnimation,
            builder: (context, child) {
              return Transform.scale(
                scale: _scaleAnimation.value,
                child: Container(
                  width: 100,
                  height: 100,
                  color: Colors.blue,
                ),
              );
            },
          ),
        ),
      ),
    );
  }
}

3. 고급 예제: 드래그와 애니메이션 결합

카드를 드래그하면 위치가 변경되며, 드래그를 멈추면 애니메이션으로 원래 위치로 돌아옵니다.

예제 코드

class DragAnimationExample extends StatefulWidget {
  @override
  _DragAnimationExampleState createState() => _DragAnimationExampleState();
}

class _DragAnimationExampleState extends State<DragAnimationExample> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<Offset> _positionAnimation;
  Offset _currentPosition = Offset.zero;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 300),
    );

    _positionAnimation = Tween<Offset>(
      begin: Offset.zero,
      end: Offset.zero,
    ).animate(
      CurvedAnimation(parent: _controller, curve: Curves.easeOut),
    );

    _controller.addListener(() {
      setState(() {
        _currentPosition = _positionAnimation.value;
      });
    });
  }

  void _onDragUpdate(DragUpdateDetails details) {
    setState(() {
      _currentPosition += details.delta;
    });
  }

  void _onDragEnd(DragEndDetails details) {
    _positionAnimation = Tween<Offset>(
      begin: _currentPosition,
      end: Offset.zero,
    ).animate(CurvedAnimation(parent: _controller, curve: Curves.easeOut));
    _controller.forward(from: 0.0);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Drag Animation')),
      body: Center(
        child: GestureDetector(
          onPanUpdate: _onDragUpdate,
          onPanEnd: _onDragEnd,
          child: Transform.translate(
            offset: _currentPosition,
            child: Container(
              width: 100,
              height: 100,
              color: Colors.red,
            ),
          ),
        ),
      ),
    );
  }
}

4. 결합 패턴: 스와이프 애니메이션

스와이프 제스처를 사용하여 카드를 좌우로 이동시키고, 끝까지 이동하면 삭제 애니메이션을 추가합니다.

추가 개선 사항

  • 제스처와 애니메이션을 결합하여 삭제, 즐겨찾기 등의 작업을 수행.
  • 물리적 효과 추가: Flutter의 physics 속성을 활용해 자연스러운 동작 구현.

5. 결론

Flutter에서 제스처와 애니메이션을 결합하면 UX를 더욱 풍부하게 만들 수 있습니다. 위 예제를 바탕으로 창의적인 사용자 인터랙션을 구현해 보세요. 다음 글에서는 제스처와 고급 물리 효과를 결합하는 방법을 다룰 예정입니다.


참고 자료

728x90
반응형
LIST

관련글 더보기