Search
▪️

Adding Animations

Flutter는 1초에 60번 update를 한다. 즉 animation은 1회 rendering에 16milliseconds가 걸리는 것이다. 이를 처리하기 위해서 SingleTickerProviderStateMixin이 필요하다. 이를 이용하면, Widget에게 animation에 의해서 frame update가 일어남을 알리게 된다.
Animation 생성 방법
AnimationController와 Animation<T>가 필요하다. (initState()에서 처리한다.)
Controller는 vsync를 this로 해주고 duration을 설정한다.
Animation Class의 instance는 두 frame 사이에 어떻게 animate해야 하는지 가이드 하기 위해 Tween class로 초기화 되어야 한다. (Tween의 타입은 Animaton<T>로 준 타입과 동일하다.)
Tween<T>(begin:, end:,).animate()
애니메이션 효과를 내고 싶은 인자에 생성한 animate의 값을 입힌다.
이후 animation이 바뀌는 곳에 controller.forward() 혹은 controller.reverse()를 해준다.
그럼 지금까지 한 것이 controller를 생성하고, animation의 크기 값과 효과 선택, 그리고 animation 크기 값과 효과를 할당한 것이다.
마지막으로 animation에 Listener를 달아야 한다. (initState()부분) 만일 manual하게 listener작업하기 싫다면, AnimatedBuilder라는 Widget을 통해서 자동으로 생성할 수도 있다.
animation을 생성 후에는 controller를 소멸시키는 dispose()를 정의해야 한다. (생성이든 소멸이든 둘다 super.() 다음에 해줘야 한다.)
responsive UI를 쓴다면 constraints의 minHeight도 animation값을 줘야 한다.
위 방법처럼 이렇게 일일이 Animation을 주는 것 마저도 귀찮다면 AnimatedContainer() Widget을 이용하면 된다. (state관리 및 re-rendering여부를 manual하게 하는 것보다 훨씬 효율적이다.)
AnimatedContainer()은 많은 일을 줄여주는 Widget이며, 효율적으로 동작하고 자동으로 transition을 만들어 준다.
두 값이 주어지면 자동으로 이를 인식하여 두 값에 대해서 smooth하게 처리하는 모션을 보인다.
따라서 controller에 listener를 달아서 쓰는 방법과 AnimatedBuilder와 같이 animation 크기 값을 직접 지정하지 않고 원래 Container에 쓰는 것처럼 상수 값을 주면 알아서 인식하고 animation을 적용 해준다.
또한 변화하는 값에 따라 알아서 forward(), reverse()를 처리하기 때문에 수동으로 controller을 만들어서 쓸 필요도 없을 뿐더러 animation 크기 값을 선택할 필요 없이 인자로 duration과 curve만 주면 된다.
이외에도 멋지고 강력한 Widget들이 많다. 예를 들면, FadeTransition과 같은 if문을 없앨 수 있는 Widget들도 존재한다.
** animation간 nested로 이용하게 되면 굉장히 느려질 수 있다.
Hero의 tag는 새로운 창이 앞으로 나오면서 커지는 animation을 나타낼 때 어떤 어떤 Screen을 animating 할지 구분하기 위한 용도이다. 따라서 어떠한 값이든 unique한 값이면 된다. 또한 두 스크린 간 switching으로 이뤄지는 animation이기 때문에 Hero Widget은 Before Screen, After Screen 두 Screen에 모두 같은 tag로 걸어야 한다.
Scaffold내 body에 CustomScrollView로 줘서 AppBar와 Image간 이쁜 animation을 넣을 수 있다.
이 때 기존 AppBar는 지워야 한다.
slivers로 SliverList와 SliverAppBar로 넣는데 SliverList는 일종의 ListView이다.
SliverList의 인자로 쓰이는 delegate는 List안에 요소들을 어떻게 Render해야할지 알리는 역할을 한다.
SliverAppBar의 인자로 들어가는 expandedHeight는 AppBar을 제한 높이이며, pinned는 scroll시 AppBar을 보일지 말지에 대한 인자, flexibleSpace는 AppBar내의 Animating 시킬 공간의 인자이다.
Page Routing에 직접 animation을 주고 싶다면 CustomRoute<T> class를 만들어 주고, 이 때MaterialPageRoute<T>를 상속 받게 한다. (push or push replace, but not push named)
만든 class에서 인자로 가져야 하는 것은 Widget을 만드는 WidgetBuilder와 MaterialPageRoute가 갖는 settings인자 타입인 RouteSetting가 필요하다. (즉, MaterialPageRoute가 받는 것들을 기본적으로 모두 처리할 수 있어야 한다.) 이렇게 설정된 값들은 Parent Class로 보내야 해서 :을 이용하여 super class로 보낸다. (:의 의미는 initializer이다.)
또한 buildTransition이 필요하므로 super class의 것을 override 한다. 여기서 <RouterSettings>.isInitialRoute 처리는 첫 화면에는 animation을 넣지 않기 위한 것이다.
마지막으로 이런 CustomRoute를 적용하기 위해 theme에 pageTransitionsTheme을 지정해야 한다. 이 Theme에는 각 platform에 맞는 transitionBuilder가 필요하다. 따라서 PageTransitionsBuilder를 상속하는 새로운 class CustomPageTransitionsBuilder을 생성 해준다. 이전에 만든 CustomRoute를 Generic타입의 buildTransition()의 인자로 준다. platform에 해당하는 transition builder지정한다.