달달한 스토리

728x90
반응형

오늘은 애니메이션 처리에 대해 글을 쓰려고 한다.

 

여러 유용한 패키지가 있었지만,

 

기존 flutter가 가지고 있는 AnimatedContainer를 한번 사용해 보려고 한다.

 

우선 flutter ui가 나는 아직 미숙하므로,

 

조잡한 예시를 보여주겠다.

 

 

 

 

정말 조잡하다.

 

하지만 실전에서는 아래와 같이 사용했다.

 

위에 방법은 기본적인 코드만을 짰기 때문에 나온 것이다...

 

 

아래 영상처럼 사용할 수도 있겠다.

 

헤헤 내가 만들었다.

 

물론 Gif를 사용하는 패키지를 포함시킨 거라

 

중간중간 Duration을 삽입하는 애를 많이 먹었다.

 

그렇다면 코드를 보자

 


사용법

우선 dart파일 두 가지를 준비한다.

 

main.dart이다.

 

import 'package:flutter/material.dart';

import 'animated_dialog.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'animated_dialog',
      home: GoAnimation(),
    );
  }
}

class GoAnimation extends StatefulWidget {
  @override
  _GoAnimationState createState() => _GoAnimationState();
}

class _GoAnimationState extends State<GoAnimation> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('animateDialog')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            titleBar(context),
            SizedBox(height: 80),
            startButton(context)
          ],
        ),
      ),
    );
  }

  InkWell startButton(BuildContext context) {
    return InkWell(
        onTap: () =>
            showDialog(context: context, builder: (_) => AnimatedDialog()),
        child: Container(
            width: 50,
            height: 50,
            decoration: BoxDecoration(
                color: Colors.red,
                shape: BoxShape.circle,
                boxShadow: [
                  BoxShadow(
                      color: Colors.grey.withOpacity(.5),
                      spreadRadius: 5,
                      blurRadius: 7)
                ]),
            child: Center(
                child: Text('시작',
                    style: TextStyle(
                        color: Colors.black38, fontWeight: FontWeight.bold)))));
  }

  Padding titleBar(BuildContext context) {
    return Padding(
        padding: const EdgeInsets.only(top: 100),
        child: Container(
            width: MediaQuery.of(context).size.width - 30,
            height: 60,
            decoration: BoxDecoration(
                color: Colors.blue.withOpacity(.4),
                borderRadius: BorderRadius.all(Radius.circular(20)),
                boxShadow: [
                  BoxShadow(
                      color: Colors.grey.withOpacity(.5),
                      spreadRadius: 5,
                      blurRadius: 7,
                      offset: Offset(0, 3))
                ]),
            child: Center(
                child: Text('애니메이션 다이얼로그',
                    style: TextStyle(fontSize: 18, color: Colors.black38)))));
  }
}

 

우선 나의 조잡한 Ui 실력으로 기본적인  이미지만 그려보았다.

 

그리고, 빨간 시작 버튼을 누르면 미리 만들어 놓은 AnimatedDialog를 호출해준다.

 

 

animated_dialog.dart

 

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class AnimatedDialog extends StatefulWidget {

  @override
  _AnimatedDialogState createState() => _AnimatedDialogState();
}

class _AnimatedDialogState extends State<AnimatedDialog> {

  bool isCircle;

  @override
  void initState() {
    isCircle = false;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      backgroundColor: Colors.transparent,
      elevation: 0,
      contentPadding: EdgeInsets.only(top: 20),
      content: AnimatedContainer(
        width: isCircle ? 64 : 300,
        height: isCircle ? 64 : 220,
        curve: Curves.fastOutSlowIn,
        duration: Duration(milliseconds: 500),
        child: isCircle ? circleContainer() : dialogContainer(context),
      ),
    );
  }

  Container dialogContainer(BuildContext context) {
    return Container(
      color: Colors.white,
      child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Container(
                child: RichText(
                    textAlign: TextAlign.center,
                    text: TextSpan(
                        children: [
                          TextSpan(
                              text: '안녕하세요\n',
                              style: TextStyle(
                                  fontSize: 20,
                                  color: Colors.black,
                                  height: 2,
                                  fontWeight: FontWeight.bold
                              )
                          ),
                          TextSpan(
                              text: '애니메이션 다이얼로그입니다.\n',
                              style: TextStyle(
                                  fontSize: 15,
                                  color: Colors.cyan,
                                  height: 2

                              )
                          ),
                          TextSpan(
                              text: 'UI 연습중입니다.',
                              style: TextStyle(
                                  fontSize: 20,
                                  color: Colors.deepPurple,
                                  height: 2
                              )
                          )
                        ]
                    )
                )
            ),
            SizedBox(
              height: 30,
            ),
            Container(
                height: 1,
                color: Colors.black
            ),
            Row(
                children: [
                  Expanded(
                      child: InkWell(
                          splashColor: Colors.transparent,
                          onTap: () => Navigator.of(context).pop(),
                          child: Container(
                              width: 80,
                              height: 70,
                              child: Center(
                                  child: Text(
                                      '취소', style: TextStyle(
                                      fontSize: 20,
                                      color: Colors.black,
                                      height: 2
                                  )
                                  )
                              )
                          )
                      )
                  ),
                  Container(
                    width: 1,
                    height: 76,
                    color: Colors.black,
                  ),
                  Expanded(child:
                  InkWell(
                      splashColor: Colors.transparent,
                      onTap: () {
                        setState(() {
                          isCircle = true;
                        });
                      },
                      child: Container(
                          child: Center(
                              child: Text(
                                  '애니메이션', style: TextStyle(
                                  fontSize: 20,
                                  color: Colors.black,
                                  height: 2
                              )
                              )
                          )
                      )
                  ))
                ]
            )
          ]
      ),
    );
  }

  Widget circleContainer(){
    return Container(
      decoration: BoxDecoration(
        shape: BoxShape.circle,
        color: Colors.white,
        boxShadow: [BoxShadow(
            color: Colors.grey.withOpacity(.5),
            spreadRadius: 5,
            blurRadius: 7
        )]
      ),
      child: Center(child: Text('성공')),
    );
  }
}

AlertDialog 위젯으로 전체를 감싸준다.

 

그리고 content 파라미터에 AnimatedContainer를 넣어준다.

 

여기서 AnmatedContainer를 사용할 때, 주의할 점은

 

width값과 height값이 null이 되면 안 된다.

 

Curve는 애니메이션의 종류를 선택하는 것인데,

 

종류가 많아 다 써보고 괜찮을 것을 찾았으면 좋을 듯하다.

 

애니메이션의 전환의 구분은 isCircle 불리언 값으로 구분한다.

 

initState에다가 false값으로 둔 다음,

 

다이얼로그에서 애니메이션 버튼을 누를 때,

 

동작한다.

 

circleContainer와 dialogContainer처럼 두 개로 보기 좋게 나누어,

 

위에 코드처럼 사용하면 된다.

 

이 밖에도 AnimatedOpacity 등등 여러 애니메이션 위젯들이 있으니,

 

같이 활용해보는 것도 좋을 듯하다.

 

728x90
반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band
loading