Flutter 프로그래밍 미세먼지 날씨 앱 만들기 - 3 (Loading Animation)
안녕하세요 아라요 IT입니다.
데이터 처리량이 많거나 network 작업이 길어질 경우 화면이 멈추거나 데이터가 없는 화면을 그대로 노출하면 안됩니다. 반드시 사용자에게 데이터가 처리되고 있다는 것을 알려줄 필요가 있습니다. 로딩시간에 따른 앱만족도 조사에 따르면 로딩 대기 시간이 1.6초일때 70% 앱만족도가 유지되며, 2.7초가 넘어가면 50%이하로 크게 떨어지게 됩니다. 하지만 로딩 애니메이션이 구현된 화면을 노출할 경우 만족도가 크게 높아지는 알 수 있습니다. 또한 사용자 오동작 유발을 방지 할 수도 있기 때문에 결과적으로 앱 재사용률과 앱 만족도를 높이기 위한 필수사항이라고 할 수 있습니다.
그래서 오늘은 Loading Animation UI를 만들어 보는 시간을 가지겠습니다.
enum LoadingType { CIRCLE, BAR, THREE_BALL }
circle type과 bar type은 flutter에서 기본적을 지원하는 ProgressIndicator widget을 사용하면 간단히 구현 할 수있습니다.
- CircularProgressIndicator : 원형 진행 표시
- LinearProgressIndicator : 선형 진행 표시
- THREE_BALL : 구현대상
class LoadingAnimation
- StatefulWidet을 상속 받아 위젯내 상태관리를 할 수 있도록 정의
- 생성자 기본 변수인 type, size는 required로 정의
- color변수는 class 생성시 정의되지 않으면 기본 Colors.white로 정의
class LoadingAnimation extends StatefulWidget {
const LoadingAnimation({
Key? key,
required this.type,
required this.size,
this.color = Colors.white,
}) : super(key: key);
final LoadingType type;
final Size size;
final Color color;
@override
_LoadingAnimationState createState() => _LoadingAnimationState();
}
class _LoadingAnimationState
late final AnimationController _controller = AnimationController(vsync: this,
duration: Duration(milliseconds: 500))
..repeat(reverse: true);
late final List<Animation<Offset>> _animation = [
Tween<Offset>(begin: Offset.zero, end: const Offset(0, 1)).animate(
CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
),
Tween<Offset>(begin: const Offset(0, 1), end: Offset.zero).animate(
CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
),
Tween<Offset>(begin: Offset.zero, end: const Offset(0, 1)).animate(
CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
),
];
static List<Color> _colorList = [
Color(0XFFffcdd2),
Color(0XFFb2dfdb),
Color(0XFFfff59d),
];
- AnimationController : 애니메이션 구동을 위한 컨트롤러
- Animation : 3개의 구형 위젯 애니메이션을 Tween type으로정의
- Tween 객체는 Offset type으로 begin과 end 값 설정
- _colorList : 3개의 구형의 색상 정의
Widget _buildLoading() {
switch (LoadingType.values[widget.type.index]) {
case LoadingType.THREE_BALL:
return _threeBall();
case LoadingType.BAR:
return _bar();
case LoadingType.CIRCLE:
default:
return _circle();
}
}
- 생성자 변수의 type에 따라 switch로 분기하여 widget 리턴
Widget _threeBall() {
return Container(
margin: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(
3,
(i) => SlideTransition(
position: _animation[i],
child: Container(
margin: EdgeInsets.symmetric(horizontal: widget.size.width / 2),
width: widget.size.width,
height: widget.size.height,
decoration: BoxDecoration(
color: _colorList[i],
shape: BoxShape.circle,
),
),
),
),
),
);
}
- SlideTransition을 이용하여 animation변수에 선언된 offset에 따라 위젯위치 변경

댓글
댓글 쓰기