flutter_bottom_sheet_pickers 0.1.0 copy "flutter_bottom_sheet_pickers: ^0.1.0" to clipboard
flutter_bottom_sheet_pickers: ^0.1.0 copied to clipboard

Customizable Flutter bottom sheet pickers for single, multiple, searchable, lazy loaded, and cascade selection.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_bottom_sheet_pickers/flutter_bottom_sheet_pickers.dart';

void main() {
  runApp(const PickerExampleApp());
}

class PickerExampleApp extends StatefulWidget {
  const PickerExampleApp({super.key});

  @override
  State<PickerExampleApp> createState() => _PickerExampleAppState();
}

class _PickerExampleAppState extends State<PickerExampleApp> {
  Locale _locale = const Locale("en");

  @override
  void initState() {
    super.initState();
    _applyPickerLocalizations(_locale);
  }

  @override
  void dispose() {
    BottomSheetPickers.clearLocalizations();
    super.dispose();
  }

  void _applyPickerLocalizations(Locale locale) {
    BottomSheetPickers.setLocalizations(localizations: BottomPickerLocalizations.byLocale(locale));
  }

  void _toggleLocale() {
    final nextLocale = _locale.languageCode == "en" ? const Locale("zh") : const Locale("en");
    _applyPickerLocalizations(nextLocale);
    setState(() => _locale = nextLocale);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter Bottom Pickers",
      debugShowCheckedModeBanner: false,
      locale: _locale,
      supportedLocales: const [
        Locale("en"),
        Locale("zh"),
      ],
      localizationsDelegates: const [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF1677FF)),
        useMaterial3: true,
      ),
      home: PickerExampleHome(
        locale: _locale,
        onToggleLocale: _toggleLocale,
      ),
    );
  }
}

class PickerExampleHome extends StatefulWidget {
  final Locale locale;
  final VoidCallback onToggleLocale;

  const PickerExampleHome({
    super.key,
    required this.locale,
    required this.onToggleLocale,
  });

  @override
  State<PickerExampleHome> createState() => _PickerExampleHomeState();
}

class _PickerExampleHomeState extends State<PickerExampleHome> {
  String _result = "No selection";
  static const BottomPickerTheme _theme = BottomPickerTheme(
    primaryColor: Color(0xFF1677FF),
    buttonBorderRadius: BorderRadius.all(Radius.circular(16)),
  );

  final List<CascadeOption> _locations = const [
    CascadeOption(
      id: "province_a",
      label: "Province A",
      children: [
        CascadeOption(
          id: "city_a",
          label: "City A",
          children: [
            CascadeOption(id: "town_a", label: "Town A"),
            CascadeOption(id: "town_b", label: "Town B"),
          ],
        ),
        CascadeOption(id: "city_b", label: "City B"),
      ],
    ),
    CascadeOption(
      id: "province_b",
      label: "Province B",
      children: [
        CascadeOption(id: "city_c", label: "City C"),
      ],
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Flutter Bottom Pickers"),
        actions: [
          TextButton(
            onPressed: widget.onToggleLocale,
            child: Text(widget.locale.languageCode == "en" ? "中文" : "EN"),
          ),
        ],
      ),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          Text(_result, style: Theme.of(context).textTheme.titleMedium),
          const SizedBox(height: 24),
          FilledButton(
            onPressed: _showSinglePicker,
            child: const Text("Show single picker"),
          ),
          const SizedBox(height: 12),
          FilledButton(
            onPressed: _showMultiplePicker,
            child: const Text("Show multiple picker"),
          ),
          const SizedBox(height: 12),
          FilledButton(
            onPressed: _showCascadePicker,
            child: const Text("Show cascade picker"),
          ),
          const SizedBox(height: 12),
          FilledButton(
            onPressed: _showMultipleCascadePicker,
            child: const Text("Show multiple cascade picker"),
          ),
          const SizedBox(height: 12),
          FilledButton(
            onPressed: _showLazyPicker,
            child: const Text("Show lazy picker"),
          ),
        ],
      ),
    );
  }

  Future<void> _showSinglePicker() async {
    final selected = await BottomSheetPickers.single<String>(
      context,
      title: "Choose a fruit",
      themeData: _theme,
    ).options(["Apple", "Orange", "Banana"], initialValue: "Apple").show();
    _updateResult(selected);
  }

  Future<void> _showMultiplePicker() async {
    final selected = await BottomSheetPickers.multiple<String>(
      context,
      title: "Choose tags",
      themeData: _theme,
    ).options(["New", "Popular", "Recommended", "Archived"], initialValue: ["New"]).show();
    _updateResult(selected);
  }

  Future<void> _showCascadePicker() async {
    final selected = await BottomSheetPickers.cascade(
      context,
      title: "Choose location",
      themeData: _theme,
    ).options(_locations)
        .initialValue(CascadeSelection.byIds("province_a", "city_a", "town_a"))
        .cascadeAllItemSupported()
        .show();
    if(selected is CascadeSelection) {
      _updateResult(selected.path.map((item) => item.label).join(" / "));
    }
  }

  Future<void> _showMultipleCascadePicker() async {
    final selected = await BottomSheetPickers.cascade(
      context,
      title: "Choose locations",
      themeData: _theme,
    ).options(_locations)
        .multiple()
        .initialValues([CascadeSelection.byIds("province_a", "city_a", "town_a")])
        .show();
    _updateResult(selected?.map((item) => item.path.map((option) => option.label).join(" / ")).join(", "));
  }

  Future<void> _showLazyPicker() async {
    final selected = await BottomSheetPickers.single<String>(
      context,
      title: "Choose remote item",
      themeData: _theme,
    ).lazyLoad(
      lazyRequestFuture: (params) async {
        await Future<void>.delayed(const Duration(milliseconds: 300));
        final int pageIndex = params["page_index"] as int? ?? 1;
        return List<String>.generate(10, (index) => "Item ${(pageIndex - 1) * 10 + index + 1}");
      },
    ).show();
    _updateResult(selected);
  }

  void _updateResult(Object? value) {
    if(!mounted) { return ; }
    setState(() => _result = value?.toString() ?? "Cancelled");
  }
}
1
likes
0
points
229
downloads

Publisher

unverified uploader

Weekly Downloads

Customizable Flutter bottom sheet pickers for single, multiple, searchable, lazy loaded, and cascade selection.

Repository (GitHub)
View/report issues

Topics

#picker #bottom-sheet #cascade-picker #flutter-picker #selection

License

unknown (license)

Dependencies

flutter

More

Packages that depend on flutter_bottom_sheet_pickers