voo_section_list 0.1.1 copy "voo_section_list: ^0.1.1" to clipboard
voo_section_list: ^0.1.1 copied to clipboard

A comprehensive Flutter package for creating settings-style section lists with multiple visual styles, custom builders, and full theming support.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:voo_section_list/voo_section_list.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) => MaterialApp(
        title: 'VooSectionList Example',
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
          useMaterial3: true,
        ),
        darkTheme: ThemeData(
          colorScheme: ColorScheme.fromSeed(
            seedColor: Colors.blue,
            brightness: Brightness.dark,
          ),
          useMaterial3: true,
        ),
        home: const StyleSelectorPage(),
      );
}

class StyleSelectorPage extends StatelessWidget {
  const StyleSelectorPage({super.key});

  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          title: const Text('VooSectionList Styles'),
        ),
        body: ListView(
          padding: const EdgeInsets.all(16),
          children: [
            _StyleCard(
              title: 'Card Style',
              description: 'Elevated cards with rounded corners',
              onTap: () => Navigator.push(
                context,
                MaterialPageRoute<void>(
                  builder: (_) => const SettingsPage(style: VooSectionStyle.card),
                ),
              ),
            ),
            const SizedBox(height: 12),
            _StyleCard(
              title: 'iOS Inset Grouped',
              description: 'iOS-style with inset and rounded containers',
              onTap: () => Navigator.push(
                context,
                MaterialPageRoute<void>(
                  builder: (_) => const SettingsPage(style: VooSectionStyle.insetGrouped),
                ),
              ),
            ),
            const SizedBox(height: 12),
            _StyleCard(
              title: 'Flat / Material',
              description: 'Android/Material flat style with headers',
              onTap: () => Navigator.push(
                context,
                MaterialPageRoute<void>(
                  builder: (_) => const SettingsPage(style: VooSectionStyle.flat),
                ),
              ),
            ),
            const SizedBox(height: 12),
            _StyleCard(
              title: 'Plain',
              description: 'Minimal plain list with dividers',
              onTap: () => Navigator.push(
                context,
                MaterialPageRoute<void>(
                  builder: (_) => const SettingsPage(style: VooSectionStyle.plain),
                ),
              ),
            ),
          ],
        ),
      );
}

class _StyleCard extends StatelessWidget {
  final String title;
  final String description;
  final VoidCallback onTap;

  const _StyleCard({
    required this.title,
    required this.description,
    required this.onTap,
  });

  @override
  Widget build(BuildContext context) => Card(
        child: ListTile(
          title: Text(title),
          subtitle: Text(description),
          trailing: const Icon(Icons.chevron_right),
          onTap: onTap,
        ),
      );
}

class SettingsPage extends StatefulWidget {
  final VooSectionStyle style;

  const SettingsPage({super.key, required this.style});

  @override
  State<SettingsPage> createState() => _SettingsPageState();
}

class _SettingsPageState extends State<SettingsPage> {
  bool _notificationsEnabled = true;
  bool _emailUpdates = false;
  bool _darkMode = false;
  bool _autoplay = true;
  bool _downloadWifiOnly = true;
  String _language = 'English';
  String _theme = 'System';

  VooSectionConfig get _config {
    switch (widget.style) {
      case VooSectionStyle.card:
        return VooSectionConfig.card;
      case VooSectionStyle.insetGrouped:
        return VooSectionConfig.ios;
      case VooSectionStyle.flat:
        return VooSectionConfig.material;
      case VooSectionStyle.plain:
        return VooSectionConfig.plain;
    }
  }

  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          title: Text('${widget.style.displayName} Style'),
        ),
        body: VooSectionList<void>(
          config: _config,
          padding: const EdgeInsets.symmetric(vertical: 8),
          sections: [
            VooSection(
              id: 'account',
              title: 'Account',
              items: [
                VooSectionItem(
                  id: 'profile',
                  title: 'Edit Profile',
                  leading: const Icon(Icons.person_outline),
                  onTap: () => _showSnackBar('Edit Profile tapped'),
                ),
                VooSectionItem(
                  id: 'password',
                  title: 'Change Password',
                  leading: const Icon(Icons.lock_outline),
                  onTap: () => _showSnackBar('Change Password tapped'),
                ),
              ],
            ),
            VooSection(
              id: 'notifications',
              title: 'Notifications',
              items: [
                VooSectionItem(
                  id: 'push',
                  title: 'Push Notifications',
                  leading: const Icon(Icons.notifications_outlined),
                  type: VooSectionItemType.toggle,
                  toggleValue: _notificationsEnabled,
                  onToggleChanged: (value) {
                    setState(() => _notificationsEnabled = value);
                  },
                ),
                VooSectionItem(
                  id: 'email',
                  title: 'Email Updates',
                  leading: const Icon(Icons.email_outlined),
                  type: VooSectionItemType.toggle,
                  toggleValue: _emailUpdates,
                  onToggleChanged: (value) {
                    setState(() => _emailUpdates = value);
                  },
                ),
              ],
            ),
            VooSection(
              id: 'preferences',
              title: 'Preferences',
              footerText: 'Choose your preferred display settings',
              items: [
                VooSectionItem(
                  id: 'language',
                  title: 'Language',
                  leading: const Icon(Icons.language),
                  type: VooSectionItemType.value,
                  displayValue: _language,
                  onTap: _showLanguagePicker,
                ),
                VooSectionItem(
                  id: 'theme',
                  title: 'Theme',
                  leading: const Icon(Icons.palette_outlined),
                  type: VooSectionItemType.value,
                  displayValue: _theme,
                  onTap: _showThemePicker,
                ),
                VooSectionItem(
                  id: 'darkMode',
                  title: 'Dark Mode',
                  leading: const Icon(Icons.dark_mode_outlined),
                  type: VooSectionItemType.toggle,
                  toggleValue: _darkMode,
                  onToggleChanged: (value) {
                    setState(() => _darkMode = value);
                  },
                ),
              ],
            ),
            VooSection(
              id: 'playback',
              title: 'Playback',
              items: [
                VooSectionItem(
                  id: 'autoplay',
                  title: 'Autoplay',
                  subtitle: 'Automatically play next video',
                  leading: const Icon(Icons.play_circle_outline),
                  type: VooSectionItemType.toggle,
                  toggleValue: _autoplay,
                  onToggleChanged: (value) {
                    setState(() => _autoplay = value);
                  },
                ),
                VooSectionItem(
                  id: 'wifiOnly',
                  title: 'Download via WiFi only',
                  leading: const Icon(Icons.wifi),
                  type: VooSectionItemType.toggle,
                  toggleValue: _downloadWifiOnly,
                  onToggleChanged: (value) {
                    setState(() => _downloadWifiOnly = value);
                  },
                ),
              ],
            ),
            VooSection(
              id: 'about',
              title: 'About',
              items: [
                VooSectionItem(
                  id: 'version',
                  title: 'Version',
                  leading: const Icon(Icons.info_outline),
                  type: VooSectionItemType.info,
                  trailing: Text(
                    '1.0.0',
                    style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant),
                  ),
                ),
                VooSectionItem(
                  id: 'terms',
                  title: 'Terms of Service',
                  leading: const Icon(Icons.description_outlined),
                  onTap: () => _showSnackBar('Terms of Service tapped'),
                ),
                VooSectionItem(
                  id: 'privacy',
                  title: 'Privacy Policy',
                  leading: const Icon(Icons.privacy_tip_outlined),
                  onTap: () => _showSnackBar('Privacy Policy tapped'),
                ),
              ],
            ),
            VooSection(
              id: 'danger',
              title: 'Danger Zone',
              items: [
                VooSectionItem(
                  id: 'logout',
                  title: 'Sign Out',
                  leading: const Icon(Icons.logout),
                  type: VooSectionItemType.destructive,
                  onTap: _showSignOutDialog,
                ),
                VooSectionItem(
                  id: 'delete',
                  title: 'Delete Account',
                  leading: const Icon(Icons.delete_forever),
                  type: VooSectionItemType.destructive,
                  onTap: _showDeleteDialog,
                ),
              ],
            ),
          ],
        ),
      );

  void _showSnackBar(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(message)),
    );
  }

  void _showLanguagePicker() {
    showModalBottomSheet(
      context: context,
      builder: (context) => Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          ListTile(
            title: const Text('English'),
            trailing: _language == 'English' ? const Icon(Icons.check) : null,
            onTap: () {
              setState(() => _language = 'English');
              Navigator.pop(context);
            },
          ),
          ListTile(
            title: const Text('Spanish'),
            trailing: _language == 'Spanish' ? const Icon(Icons.check) : null,
            onTap: () {
              setState(() => _language = 'Spanish');
              Navigator.pop(context);
            },
          ),
          ListTile(
            title: const Text('French'),
            trailing: _language == 'French' ? const Icon(Icons.check) : null,
            onTap: () {
              setState(() => _language = 'French');
              Navigator.pop(context);
            },
          ),
          const SizedBox(height: 16),
        ],
      ),
    );
  }

  void _showThemePicker() {
    showModalBottomSheet(
      context: context,
      builder: (context) => Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          ListTile(
            title: const Text('System'),
            trailing: _theme == 'System' ? const Icon(Icons.check) : null,
            onTap: () {
              setState(() => _theme = 'System');
              Navigator.pop(context);
            },
          ),
          ListTile(
            title: const Text('Light'),
            trailing: _theme == 'Light' ? const Icon(Icons.check) : null,
            onTap: () {
              setState(() => _theme = 'Light');
              Navigator.pop(context);
            },
          ),
          ListTile(
            title: const Text('Dark'),
            trailing: _theme == 'Dark' ? const Icon(Icons.check) : null,
            onTap: () {
              setState(() => _theme = 'Dark');
              Navigator.pop(context);
            },
          ),
          const SizedBox(height: 16),
        ],
      ),
    );
  }

  void _showSignOutDialog() {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Sign Out'),
        content: const Text('Are you sure you want to sign out?'),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('Cancel'),
          ),
          TextButton(
            onPressed: () {
              Navigator.pop(context);
              _showSnackBar('Signed out');
            },
            child: const Text('Sign Out'),
          ),
        ],
      ),
    );
  }

  void _showDeleteDialog() {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Delete Account'),
        content: const Text(
          'This action cannot be undone. All your data will be permanently deleted.',
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('Cancel'),
          ),
          TextButton(
            onPressed: () {
              Navigator.pop(context);
              _showSnackBar('Account deleted');
            },
            style: TextButton.styleFrom(foregroundColor: Colors.red),
            child: const Text('Delete'),
          ),
        ],
      ),
    );
  }
}
1
likes
160
points
9
downloads

Documentation

API reference

Publisher

verified publishervoostack.com

Weekly Downloads

A comprehensive Flutter package for creating settings-style section lists with multiple visual styles, custom builders, and full theming support.

Homepage
Repository (GitHub)
View/report issues

Topics

#flutter #settings #lists #user-interface #section-list

License

MIT (license)

Dependencies

equatable, flutter, voo_responsive, voo_tokens, voo_ui_core

More

Packages that depend on voo_section_list