Flutter List UI
A Flutter package that provides a collection of list-related widgets with consistent styling and behavior.

Features
InfoList
: A flexible list widget that supports:
- Generic type support for any data model
- Empty state handling with customizable UI
- Skeleton loading UI with shimmer effect
- AsyncValue integration with Riverpod
- Custom item builders
- Custom separators
- Custom styling options
InfoCard
: A card widget that wraps content with consistent styling
InfoHeader
: A header widget for cards with title and optional actions
InfoItemBase
: A base model for list items with common properties
Getting Started
Add the package to your pubspec.yaml
:
dependencies:
flutter_list_ui: ^1.4.2
shimmer: ^3.0.0 # Optional: for skeleton loading effect
Usage
Basic List
InfoList.info(
items: items,
buildItem: (item) => ListTile(
title: Text(item.title),
subtitle: Text(item.subtitle),
),
);
With Empty State
InfoList.info(
items: items,
buildEmptyItem: (context, items) => Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.inbox_outlined,
size: 48,
color: Colors.grey[400],
),
const SizedBox(height: 16),
Text(
'데이터가 없습니다',
style: TextStyle(
color: Colors.grey[600],
fontSize: 16,
),
),
],
),
),
buildItem: (item) => ListTile(
title: Text(item.title),
subtitle: Text(item.subtitle),
),
);
With Skeleton Loading
InfoList.info(
items: items,
isLoading: true,
skeletonCount: 3,
skeletonBuilder: (context, index) => Container(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: Colors.grey[300],
shape: BoxShape.circle,
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: double.infinity,
height: 20,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(4),
),
),
const SizedBox(height: 8),
Container(
width: 150,
height: 16,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(4),
),
),
],
),
),
],
),
),
);
With Riverpod AsyncValue
InfoList.when(
value: itemsAsyncValue,
buildItem: (item) => ListTile(
title: Text(item.title),
subtitle: Text(item.subtitle),
),
buildEmptyItem: (context, items) => Container(
padding: const EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.search_off,
size: 48,
color: Colors.grey[400],
),
const SizedBox(height: 16),
Text(
'검색 결과가 없습니다',
style: TextStyle(
color: Colors.grey[600],
fontSize: 16,
),
),
const SizedBox(height: 8),
Text(
'다른 검색어를 시도해보세요',
style: TextStyle(
color: Colors.grey[500],
fontSize: 14,
),
),
],
),
),
);
With Shimmer Effect
import 'package:shimmer/shimmer.dart';
InfoList.info(
items: items,
isLoading: true,
skeletonBuilder: (context, index) => Shimmer.fromColors(
baseColor: Colors.grey[300]!,
highlightColor: Colors.grey[100]!,
child: Container(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: double.infinity,
height: 20,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(4),
),
),
const SizedBox(height: 8),
Container(
width: 150,
height: 16,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(4),
),
),
],
),
),
],
),
),
),
);
With InfoCard
Info(
card: InfoCard(
header: InfoHeader(
title: 'List Title',
titleStyle: Theme.of(context).textTheme.titleLarge,
),
body: InfoList.info(
items: items,
buildItem: (item) => ListTile(
title: Text(item.title),
subtitle: Text(item.subtitle),
),
),
backgroundColor: Colors.white,
isRound: true,
showBorder: false,
),
);
Property |
Type |
Description |
card |
InfoCard |
The InfoCard widget to display |
paddingOption |
String |
Padding option ('all' or 'symmetric', default: 'all') |
paddingVertical |
double |
Vertical padding value (default: 8.0) |
paddingHorizontal |
double |
Horizontal padding value (default: 8.0) |
Property |
Type |
Description |
header |
InfoHeaderBase |
Header widget |
body |
InfoList |
Main content widget |
isRound |
bool |
Whether to show rounded corners (default: false) |
backgroundColor |
Color? |
Background color |
margin |
EdgeInsetsGeometry? |
Margin around the card |
padding |
EdgeInsetsGeometry? |
Padding around the content |
showBorder |
bool |
Whether to show border (default: true) |
borderColor |
Color? |
Border color |
useSliver |
bool |
Whether to use SliverList (default: false) |
Property |
Type |
Description |
title |
String |
Title text |
subtitle |
String? |
Optional subtitle text |
trailing |
Widget? |
Optional trailing widget |
titleStyle |
TextStyle? |
Style for the title text |
subtitleStyle |
TextStyle? |
Style for the subtitle text |
backgroundColor |
Color? |
Background color |
padding |
EdgeInsetsGeometry? |
Padding around the content |
Property |
Type |
Description |
items |
List |
List of items to display |
buildItem |
Widget Function(T) |
Function to build each item |
backgroundColor |
Color? |
Background color |
contentPadding |
EdgeInsetsGeometry? |
Padding around the list content |
shrinkWrap |
bool |
Whether the list should shrink-wrap its content (default: true) |
separatorBuilder |
Widget Function(BuildContext, int)? |
Function to build separator widgets |
physics |
ScrollPhysics? |
Scroll physics for the list |
itemPadding |
EdgeInsetsGeometry? |
Padding for each item |
itemDecoration |
BoxDecoration? |
Decoration for each item container |
removeTopPadding |
bool |
Whether to remove top padding (default: false) |
emptyWidget |
Widget? |
Widget to show when items is empty |
isLoading |
bool |
Whether to show skeleton loading UI (default: false) |
skeletonCount |
int |
Number of skeleton items to show (default: 3) |
skeletonBuilder |
Widget Function(BuildContext, int)? |
Function to build skeleton items |
buildEmptyItem |
Widget Function(BuildContext, List |
Function to build empty state UI |
useSliver |
bool |
Whether to use SliverList (default: false) |
Property |
Type |
Description |
header |
InfoHeaderBase |
Header widget |
body |
InfoList |
Main content widget |
isRound |
bool |
Whether to show rounded corners (default: false) |
backgroundColor |
Color? |
Background color |
margin |
EdgeInsetsGeometry? |
Margin around the card |
padding |
EdgeInsetsGeometry? |
Padding around the content |
builder |
Widget Function(BuildContext, WidgetRef)? |
Custom builder function |
showBorder |
bool |
Whether to show border (default: true) |
borderColor |
Color? |
Border color |
useSliver |
bool |
Whether to use SliverList (default: false) |
Property |
Type |
Description |
items |
List |
List of items to display |
buildItem |
Widget Function(T) |
Function to build each item |
backgroundColor |
Color? |
Background color |
contentPadding |
EdgeInsetsGeometry? |
Padding around the list content |
shrinkWrap |
bool |
Whether the list should shrink-wrap its content (default: true) |
separatorBuilder |
Widget Function(BuildContext, int)? |
Function to build separator widgets |
physics |
ScrollPhysics? |
Scroll physics for the list |
itemPadding |
EdgeInsetsGeometry? |
Padding for each item |
itemDecoration |
BoxDecoration? |
Decoration for each item container |
removeTopPadding |
bool |
Whether to remove top padding (default: false) |
emptyWidget |
Widget? |
Widget to show when items is empty |
isLoading |
bool |
Whether to show skeleton loading UI (default: false) |
skeletonCount |
int |
Number of skeleton items to show (default: 3) |
skeletonBuilder |
Widget Function(BuildContext, int)? |
Function to build skeleton items |
buildEmptyItem |
Widget Function(BuildContext, List |
Function to build empty state UI |
useSliver |
bool |
Whether to use SliverList (default: false) |
Property |
Type |
Description |
items |
List |
List of items to display |
buildItem |
Widget Function(T) |
Function to build each item |
backgroundColor |
Color? |
Background color |
contentPadding |
EdgeInsetsGeometry? |
Padding around the list content |
shrinkWrap |
bool |
Whether the list should shrink-wrap its content (default: true) |
separatorBuilder |
Widget Function(BuildContext, int)? |
Function to build separator widgets |
physics |
ScrollPhysics? |
Scroll physics for the list |
itemPadding |
EdgeInsetsGeometry? |
Padding for each item |
itemDecoration |
BoxDecoration? |
Decoration for each item container |
removeTopPadding |
bool |
Whether to remove top padding (default: false) |
emptyWidget |
Widget? |
Widget to show when items is empty |
isLoading |
bool |
Whether to show skeleton loading UI (default: false) |
skeletonCount |
int |
Number of skeleton items to show (default: 3) |
skeletonBuilder |
Widget Function(BuildContext, int)? |
Function to build skeleton items |
buildEmptyItem |
Widget Function(BuildContext, List |
Function to build empty state UI |
useSliver |
bool |
Whether to use SliverList (default: false) |
Property |
Type |
Description |
items |
List |
List of items to display |
buildItem |
Widget Function(T) |
Function to build each item |
backgroundColor |
Color? |
Background color |
contentPadding |
EdgeInsetsGeometry? |
Padding around the list content |
shrinkWrap |
bool |
Whether the list should shrink-wrap its content (default: true) |
separatorBuilder |
Widget Function(BuildContext, int)? |
Function to build separator widgets |
physics |
ScrollPhysics? |
Scroll physics for the list |
itemPadding |
EdgeInsetsGeometry? |
Padding for each item |
itemDecoration |
BoxDecoration? |
Decoration for each item container |
removeTopPadding |
bool |
Whether to remove top padding (default: false) |
emptyWidget |
Widget? |
Widget to show when items is empty |
isLoading |
bool |
Whether to show skeleton loading UI (default: false) |
skeletonCount |
int |
Number of skeleton items to show (default: 3) |
skeletonBuilder |
Widget Function(BuildContext, int)? |
Function to build skeleton items |
buildEmptyItem |
Widget Function(BuildContext, List |
Function to build empty state UI |
useSliver |
bool |
Whether to use SliverList (default: false) |
Dependencies
- flutter_riverpod: ^2.5.1 (Required for AsyncValue support)
- flutter_screenutil: ^5.9.0
- google_fonts: ^6.1.0
- cached_network_image: ^3.3.1
- shimmer: ^3.0.0 (Optional: for skeleton loading effect)
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
About
A reusable Flutter UI components package