모바일 애플리케이션에서 데이터를 로딩하는 동안 사용자가 아무런 피드백 없이 기다리게 하는 것은 좋은 사용자 경험을 제공하는 데 있어 큰 걸림돌이 될 수 있습니다. 이때 로딩 상태를 시각적으로 표현해주는 flutter_shimmer 패키지를 사용하면 로딩 중임을 직관적으로 알릴 수 있습니다.
많이들 사용하는 인스타, 페이스북, 스레드 등 앱을 실행시키면 첫 화면으로 볼 수 있는 화면들이다.
기존의 CircularProgressIndicator는 단순한 로딩 상태를 나타내지만, 앱화면을 미리 직관적으로 볼 수 있는 장점이 있습니다.
https://pub.dev/packages/shimmer/versions
$ flutter pub add shimmer
import 'package:shimmer/shimmer.dart';
child: Shimmer.fromColors(
baseColor: Colors.grey[300]!,
highlightColor: Colors.grey[100]!,
child: ListView.builder(
itemCount: 6,
itemBuilder: (_, __) => Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 80.0,
height: 80.0,
color: Colors.white,
),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 8.0),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: double.infinity,
height: 8.0,
color: Colors.white,
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 2.0),
),
Container(
width: double.infinity,
height: 8.0,
color: Colors.white,
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 2.0),
),
Container(
width: 40.0,
height: 8.0,
color: Colors.white,
),
],
),
)
],
),
),
),
),
- Shimmer.fromColors: 이 위젯은 flutter_shimmer 패키지에서 제공하는 기본적인 기능입니다. baseColor와 highlightColor를 설정하여 애니메이션의 색상 변화를 지정할 수 있습니다. 이 예제에서는 회색 계열의 색상을 사용하여 부드러운 반짝임 효과를 적용하였습니다.
- Container: 반짝이는 애니메이션을 보여주기 위해, 데이터가 로딩될 영역에 빈 컨테이너를 사용합니다. 로딩이 완료되면 실제 데이터로 이 컨테이너를 대체하게 됩니다.
flutter_shimmer 패키지는 Flutter 애플리케이션에서 로딩 상태를 시각적으로 개선할 수 있는 강력한 도구입니다. 사용자는 데이터가 로드되고 있음을 직관적으로 알 수 있으며, 로딩 애니메이션을 통해 보다 매끄러운 사용자 경험을 제공할 수 있습니다. 위의 예제와 같이 간단한 코드로 손쉽게 애니메이션을 추가해보세요. 앱의 완성도가 한층 더 높아질 것입니다.
이제 flutter_shimmer 패키지를 활용하여 로딩 상태에서도 사용자에게 즐거운 경험을 선사해보세요!!
/// 전체 소스 코드
import 'package:flutter/material.dart';
import 'package:shimmer/shimmer.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Shimmer Example')),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Shimmer.fromColors(
baseColor: Colors.grey[300]!,
highlightColor: Colors.grey[100]!,
child: ListView.builder(
itemCount: 6,
itemBuilder: (_, __) => Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 80.0,
height: 80.0,
color: Colors.white,
),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 8.0),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: double.infinity,
height: 8.0,
color: Colors.white,
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 2.0),
),
Container(
width: double.infinity,
height: 8.0,
color: Colors.white,
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 2.0),
),
Container(
width: 40.0,
height: 8.0,
color: Colors.white,
),
],
),
)
],
),
),
),
),
),
),
),
);
}
}