내가 보려고 쓰는 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.pi | 2.0 * math.pi |
---|---|
코드에 온통 처음보는 것들 투성이인데, 하나하나 알아보자
Ticker 에서부터 막혔다... 구글에 검색해보니
계속 변하는 걸 알려주는 건가보다.
사방으로 설명을 찾아다녔는데, 정확히 이해할 만한 설명을 못찾았다ㅠㅠ
Ticker 는 매 프레임마다 함수를 호출하는 객체인데, 프레임이 변화되어야 할 때 알려주는 거라고 한다. 내가 적는데 뭔 말인지
직접 사용하는 경우는 없고, TickerProvider를 통해 다른 곳에서 간접적으로 사용하는 경우가 대부분이다. 대표적인 경우가 AnimationController이고, TickerProviderStateMixin 이나 SingleTickerProviderStateMixin 을 주로 사용한다.
class _MyStatefulWidgetState extends State<MyStatefulWidget>
with TickerProviderStateMixin
위 코드에서는 TickerProviderStateMixin을 사용했는데, 클래스 내부에서 AnimationControler를 하나만 사용한다면 SingleTickerProviderStateMixin을 사용해도 된다. 현재 코드는 하나 뿐이므로 Single 써도 된다는 뜻이다.
애니메이션을 설정할 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 로 설정.
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를 두가지로 해서 돌려보았다.
translate | scale, rotate |
---|---|
범위를 내 마음대로 지정하긴 했다;;
오늘 ticker 때문에 한참 헤맸네
오늘의 일기는 여기까지!