quick_list_builder 0.0.2 copy "quick_list_builder: ^0.0.2" to clipboard
quick_list_builder: ^0.0.2 copied to clipboard

A lightweight and developer-friendly customizable listview widget for Flutter.

quick_list_builder #

A lightweight and developer-friendly list widget for Flutter. QuickListBuilder replaces boilerplate ListView.builder code with a single, feature-rich widget that handles selection, async data, pagination, grid layout, section headers, skeleton loading, and more — with zero extra dependencies.


Features #

  • 4 selection modes — none, radio, checkbox, switch toggle
  • Trailing or leading selection placement
  • Async fetcherFuture-based data source with built-in loading / error / empty states
  • Infinite scroll pagination — auto-loads the next page near the scroll end
  • Pull-to-refreshRefreshIndicator wired automatically
  • Grid layout — drop-in GridView with layout: QuickListLayout.grid
  • Section headers — inline grouped headers via sectionHeaderBuilder
  • Skeleton loading — custom per-item placeholders during initial load
  • Programmatic controllerQuickListController for refresh, loadMore, insert, remove, replaceWhere
  • Custom buildersitemBuilder, titleBuilder, subtitleBuilder, leadingBuilder, trailingBuilder, radioBuilder, checkboxBuilder, switchBuilder
  • Dividers & separatorsdivider toggle, static separator, or per-index separatorBuilder
  • Animated item transitions — configurable animationDuration
  • Item enable/disable — per-item enabled state with 50 % opacity
  • Horizontal listsscrollDirection: Axis.horizontal
  • List extensionmyList.quickList(...) builds from any List<T> instantly
  • Zero extra dependencies

Installation #

dependencies:
  quick_list_builder: ^0.0.3
import 'package:quick_list_builder/quick_list_builder.dart';

Quick start #

Static list #

final items = ['Apple', 'Banana', 'Cherry'];

QuickListBuilder<String>(
  items: items,
  divider: true,
  onItemTap: (item) => print('Tapped $item'),
)

Or use the List extension:

items.quickList(
  divider: true,
  onItemTap: (item) => print('Tapped $item'),
)

Selection modes #

Radio #

String? selected = 'Apple';

QuickListBuilder<String>(
  items: items,
  selectionMode: QuickListSelectionMode.radio,
  selectedItem: selected,
  onChanged: (val) => setState(() => selected = val as String),
)

Checkbox #

List<String> selected = [];

QuickListBuilder<String>(
  items: items,
  selectionMode: QuickListSelectionMode.checkbox,
  trailingSelection: true,        // place checkbox on the right
  selectedItems: selected,
  onChanged: (val) => setState(() => selected = List<String>.from(val as List)),
)

Switch toggle #

QuickListBuilder<String>(
  items: items,
  selectionMode: QuickListSelectionMode.switchToggle,
  trailingSelection: true,
  selectedItems: enabled,
  onChanged: (val) => setState(() => enabled = List<String>.from(val as List)),
)

Async data & pagination #

Provide a fetcher instead of items to load data from an API. The widget handles loading, error, empty, and infinite-scroll pagination states automatically.

Future<QuickListPage<User>> _fetchUsers(int page, int pageSize) async {
  final json = await api.getUsers(page: page, limit: pageSize);
  return QuickListPage(
    items: json.map(User.fromJson).toList(),
    hasMore: json.length == pageSize,
  );
}

QuickListBuilder<User>(
  fetcher: _fetchUsers,
  pageSize: 20,
  enablePagination: true,
  enablePullToRefresh: true,
  titleBuilder: (user) => Text(user.name),
  subtitleBuilder: (user) => Text(user.email),
  leadingBuilder: (user) => CircleAvatar(child: Text(user.name[0])),
  emptyWidget: const Center(child: Text('No users found')),
  errorBuilder: (context, error, retry) => Center(
    child: Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Text('$error'),
        FilledButton(onPressed: retry, child: const Text('Retry')),
      ],
    ),
  ),
  endOfListWidget: const Center(
    child: Padding(
      padding: EdgeInsets.all(16),
      child: Text('— no more results —'),
    ),
  ),
)

Grid layout #

Switch to a GridView with one parameter:

QuickListBuilder<Product>(
  fetcher: _fetchProducts,
  layout: QuickListLayout.grid,
  gridCrossAxisCount: 2,
  gridChildAspectRatio: 0.75,
  gridMainAxisSpacing: 8,
  gridCrossAxisSpacing: 8,
  itemBuilder: (context, product, index) => ProductCard(product),
)

Section headers #

Group items under inline headers automatically:

QuickListBuilder<Contact>(
  items: contacts,          // must be pre-sorted by group
  sectionHeaderBuilder: (contact, index) => contact.department,
  titleBuilder: (contact) => Text(contact.name),
  subtitleBuilder: (contact) => Text(contact.role),
  leadingBuilder: (contact) => CircleAvatar(child: Text(contact.name[0])),
)

Use sectionHeaderWidgetBuilder for a fully custom header widget.


Skeleton loading #

Show placeholder items while the first page loads:

QuickListBuilder<Post>(
  fetcher: _fetchPosts,
  skeletonCount: 6,
  skeletonBuilder: (context) => const ListTile(
    leading: _SkeletonCircle(),
    title: _SkeletonLine(width: double.infinity),
    subtitle: _SkeletonLine(width: 140),
  ),
  itemBuilder: (context, post, index) => PostTile(post),
)

Programmatic controller #

Use QuickListController to refresh, paginate, or mutate items from outside the widget:

final _controller = QuickListController<String>();

// Attach
QuickListBuilder<String>(
  fetcher: _fetch,
  controller: _controller,
  ...
)

// Elsewhere
_controller.refresh();                        // reload from page 1
_controller.insert('New item', at: 0);        // optimistic insert
_controller.remove('Old item');               // optimistic remove
_controller.replaceWhere((e) => e == 'x', 'y'); // swap item

Custom item builder #

Full control over each row:

QuickListBuilder<Order>(
  items: orders,
  itemBuilder: (context, order, index) => Card(
    margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
    child: ListTile(
      leading: Icon(
        order.isPaid ? Icons.check_circle : Icons.pending,
        color: order.isPaid ? Colors.green : Colors.orange,
      ),
      title: Text(order.title),
      subtitle: Text('\$${order.amount}'),
      trailing: Text(order.date),
    ),
  ),
)

Separators #

// Built-in divider
QuickListBuilder<String>(items: items, divider: true)

// Static separator widget
QuickListBuilder<String>(
  items: items,
  separator: const Padding(
    padding: EdgeInsets.symmetric(horizontal: 16),
    child: Divider(height: 1),
  ),
)

// Per-index separator builder
QuickListBuilder<String>(
  items: items,
  separatorBuilder: (context, index, before, after) =>
      index == 2 ? const SizedBox(height: 24) : const Divider(),
)

Horizontal list #

SizedBox(
  height: 120,
  child: QuickListBuilder<Category>(
    items: categories,
    scrollDirection: Axis.horizontal,
    separator: const SizedBox(width: 12),
    itemBuilder: (context, cat, index) => CategoryChip(cat),
  ),
)

Item enable / disable #

QuickListBuilder<Plan>(
  items: plans,
  isItemEnabled: (plan) => plan.isAvailable,  // disabled items shown at 50 % opacity
  selectionMode: QuickListSelectionMode.radio,
  selectedItem: _selectedPlan,
  onChanged: (val) => setState(() => _selectedPlan = val as Plan),
  titleBuilder: (plan) => Text(plan.name),
  subtitleBuilder: (plan) => Text(plan.price),
)

Full API reference #

Data source #

Param Type Default Description
items List<T>? Static list. Provide either items or fetcher
fetcher QuickListFetcher<T>? Async page fetcher. Provide either items or fetcher
pageSize int 20 Items per page requested from fetcher
enablePagination bool true Auto-load next page on scroll
enablePullToRefresh bool true Wrap with RefreshIndicator
controller QuickListController<T>? Programmatic controller

Item rendering #

Param Description
itemBuilder Full custom item widget — overrides all other builders
titleBuilder Title widget for each item
subtitleBuilder Subtitle widget for each item
leadingBuilder Leading widget (left side)
trailingBuilder Trailing widget (right side)
sectionHeaderBuilder Returns a group header string for each item
sectionHeaderWidgetBuilder Custom widget for section header

Selection #

Param Type Default Description
selectionMode QuickListSelectionMode none none, radio, checkbox, switchToggle
selectedItem T? Currently selected item (radio / switch)
selectedItems List<T>? Currently selected items (checkbox / switch)
trailingSelection bool false Place selection widget on the trailing side
isItemSelected bool Function(T)? Custom equality check for selection state
radioBuilder builder Fully custom radio widget
checkboxBuilder builder Fully custom checkbox widget
switchBuilder builder Fully custom switch widget
activeColor Color? Active color for radio / checkbox
checkColor Color? Check mark color for checkbox
checkboxShape OutlinedBorder? Custom checkbox shape (e.g. CircleBorder)

Interaction #

Param Type Description
onItemTap ValueChanged<T>? Called when an item is tapped
onItemLongPress ValueChanged<T>? Called on long press
onChanged ValueChanged<dynamic>? Selection change callback
isItemEnabled bool Function(T)? Per-item enabled state

Layout #

Param Type Default Description
layout QuickListLayout list list or grid
gridCrossAxisCount int 2 Grid columns
gridChildAspectRatio double 1.0 Grid cell aspect ratio
gridMainAxisSpacing double 8 Grid row spacing
gridCrossAxisSpacing double 8 Grid column spacing
scrollDirection Axis vertical Scroll axis
shrinkWrap bool false Shrink-wrap the scroll view
physics ScrollPhysics? Custom scroll physics
scrollController ScrollController? External scroll controller
reverse bool false Reverse scroll direction
padding EdgeInsetsGeometry? List padding

Separators #

Param Type Default Description
divider bool false Show Divider between items
dividerColor Color? Divider color
dividerThickness double? Divider thickness
dividerIndent / dividerEndIndent double? Divider indent
separator Widget? Static separator widget. Overrides divider
separatorBuilder builder Per-index separator. Highest priority

Item styling #

Param Type Description
itemPadding EdgeInsetsGeometry? Padding inside each item
itemMargin EdgeInsetsGeometry? Margin around each item
itemBackgroundColor Color? Default item background
selectedItemBackgroundColor Color? Background when selected
itemBorderRadius BorderRadiusGeometry? Item corner radius
itemBorder BoxBorder? Item border
itemShadow List<BoxShadow>? Item shadow
animationDuration Duration Selection animation duration (default 200 ms)

State widgets #

Param Description
loadingWidget Widget shown during initial load (overrides skeleton)
errorBuilder (context, error, retry) — custom error widget
emptyWidget Widget shown when list is empty
loadMoreWidget Widget shown at bottom while loading more pages
endOfListWidget Widget shown when no more pages remain
skeletonCount Number of skeleton items to show during initial load
skeletonBuilder Builder for each skeleton item

QuickListController #

final controller = QuickListController<T>();

controller.refresh();                           // reload from page 1
controller.loadMore();                          // load next page manually
controller.insert(item, at: 0);                 // insert at index
controller.remove(item);                        // remove by equality
controller.replaceWhere((e) => test(e), newItem); // conditional replace
controller.items;       // current item list (unmodifiable)
controller.isLoading;   // true during initial load
controller.isLoadingMore; // true while loading a page
controller.hasMore;     // whether more pages exist
controller.error;       // last initial-load error, if any

License #

MIT

2
likes
140
points
7
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A lightweight and developer-friendly customizable listview widget for Flutter.

Repository (GitHub)
View/report issues

Topics

#listview #radio #checkbox #flutter-ui #productivity

License

MIT (license)

Dependencies

flutter

More

Packages that depend on quick_list_builder