Flutter - #27. AnimatedBuilder

Pearl Lee·2021년 6월 30일
1

Flutter Widget

목록 보기
26/50

내가 보려고 쓰는 Flutter 일기
참고1 : https://api.flutter.dev/flutter/widgets/AnimatedBuilder-class.html
참고2 : Do it! 플러터 앱 프로그래밍, 조준수 [이지스퍼블리싱]










AnimatedBuilder

저번 시간에 이어 오늘 배워볼 것은 AnimatedBuild.
AnimatedContainer에 비해, 위젯이 많은 복잡한 화면에서 세밀하게 애니메이션을 구현할 수 있다.
builder 속성에 구현할 애니메이션을 작성하고, child 에 설정된 위젯이 builder에 전해져 애니메이션이 적용된다.
다만 위치나 회전을 조정하는 수학을 혼자 작성하기 어려울뿐ㅠㅠ









코드 예시로 알아보자

공식페이지의 코드를 가져다가 조금만 수정해서 돌려보았다.

/// Flutter code sample for AnimatedBuilder
import 'dart:math' as math;
import 'package:flutter/material.dart';

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

/// This is the main application widget.
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  static const String _title = 'Flutter Code Sample';

  
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: _title,
      home: MyStatefulWidget(),
    );
  }
}

/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
  const MyStatefulWidget({Key? key}) : super(key: key);

  
  State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}

/// This is the private State class that goes with MyStatefulWidget.
/// AnimationControllers can be created with `vsync: this` because of TickerProviderStateMixin.
class _MyStatefulWidgetState extends State<MyStatefulWidget>
    with TickerProviderStateMixin {

  late final AnimationController _controller = AnimationController(
    duration: const Duration(seconds: 10),
    vsync: this,
  )..repeat();

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

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Test AnimatedBuilder'),
      ),
      body: Container(
        child: Center(
          child: AnimatedBuilder(
            animation: _controller,
            child: Container(
              width: 200.0,
              height: 200.0,
              color: Colors.green,
              child: const Center(
                child: Text('Whee!', style: TextStyle(fontSize: 50),),
              ),
            ),
            builder: (BuildContext context, Widget? child) {
              return Transform.rotate(
                angle: _controller.value * 2.0 * math.pi,
                child: child,
              );
            },
          ),
        ),
      ),
    );
  }
}

우선 실행화면은 아래와 같다.

-2.0 * math.pi2.0 * math.pi

코드에 온통 처음보는 것들 투성이인데, 하나하나 알아보자








TickerProviderStateMixin

Ticker 에서부터 막혔다... 구글에 검색해보니
계속 변하는 걸 알려주는 건가보다.

사방으로 설명을 찾아다녔는데, 정확히 이해할 만한 설명을 못찾았다ㅠㅠ

Ticker 는 매 프레임마다 함수를 호출하는 객체인데, 프레임이 변화되어야 할 때 알려주는 거라고 한다. 내가 적는데 뭔 말인지
직접 사용하는 경우는 없고, TickerProvider를 통해 다른 곳에서 간접적으로 사용하는 경우가 대부분이다. 대표적인 경우가 AnimationController이고, TickerProviderStateMixin 이나 SingleTickerProviderStateMixin 을 주로 사용한다.

class _MyStatefulWidgetState extends State<MyStatefulWidget>
    with TickerProviderStateMixin

위 코드에서는 TickerProviderStateMixin을 사용했는데, 클래스 내부에서 AnimationControler를 하나만 사용한다면 SingleTickerProviderStateMixin을 사용해도 된다. 현재 코드는 하나 뿐이므로 Single 써도 된다는 뜻이다.






AnimationController

애니메이션을 설정할 Controller이다. 애니메이션을 실행, 중지할 수 있고, 기본값은 설정한 시간 동안(duration) 0에서 1까지 선형적으로(linear) 변하는 것이다.

AnimationController({
  double? value,
  this.duration,
  this.reverseDuration,
  this.debugLabel,
  this.lowerBound = 0.0,
  this.upperBound = 1.0,
  this.animationBehavior = AnimationBehavior.normal,
  required TickerProvider vsync,
})

여기 lowerBound와 upperBound에 설정된 값을 보면 0과 1이다.
위의 코드에서 회전을 이렇게 작성했었는데, 0~1까지의 범위에 2Pi를 곱해준것과 같다. 만약 x2.0 x math.pi 가 아니라 +math.pi로 작성하면 초록 네모는 뒤집힌 상태에서 조금 회전하다 원래대로 돌아온다.

return Transform.rotate(
     angle: _controller.value * 2.0 * math.pi,
     child: child,
);

그리고 vsync 속성에는 TickerProvider를 받는데, 현재 클래스가 상속받은 TikcerProviderStateMixin을 전달하면 된다. 그래서 vsync:this 로 설정.







AnimatedBuilder

child: AnimatedBuilder(
          animation: _controller,
          child: Container(
            width: 200.0,
            height: 200.0,
            color: Colors.green,
            child: const Center(
              child: Text('Whee!', style: TextStyle(fontSize: 50),),
            ),
          ),
          builder: (BuildContext context, Widget? child) {
            return Transform.rotate(
              angle: _controller.value * 2.0 * math.pi,
              child: child,
            );
          },
        ),

animation에는 클래스 내에 만든 AnimationController를 지정한다. child에는 애니메이션을 지정할 위젯을 만들면 되고, builder에는 구현할 애니메이션을 설정한다. 여기서는 Transform.rotate를 사용했는데, 이외에도 scale, translate가 더 있다.

하는 김에 이것저것 두드려보자

builder: (BuildContext context, Widget? child) {
   return Transform.translate(
      offset: Offset(0, _controller.value*600),
      child: child,
  );
}

builder: (BuildContext context, Widget? child) {
   return Transform.scale(
       scale: _controller.value * 3,
       child: Transform.rotate(
       angle: _controller.value *2 * math.pi,
       child: child,
      ),
   );
},

요렇게 builder를 두가지로 해서 돌려보았다.

translatescale, rotate

범위를 내 마음대로 지정하긴 했다;;






오늘 ticker 때문에 한참 헤맸네
오늘의 일기는 여기까지!

profile
안 되면 되게 하라

0개의 댓글