settings_item 2.0.0
settings_item: ^2.0.0 copied to clipboard
A beautiful, customizable expandable menu widget for Flutter settings pages with smooth animations and Material Design 3 styling. Supports switch, expandable, and button modes.
Settings Expandable Menu #
A beautiful, customizable expandable menu widget for Flutter settings pages with smooth animations and Material Design 3 styling.

Features #
✨ Three Operation Modes:
- Switch Mode: Toggle switch for on/off settings
- Expandable Mode: Expandable content with smooth animations and up arrow
- Button Mode: Left arrow rotation without content expansion
🎨 Highly Customizable:
- Custom prefix icons with themed containers
- Custom title text with Material Design typography
- Custom suffix widgets for advanced interactions
- Custom expanded content widgets
- Theme-aware colors and styling
⚡ Smooth Animations:
- Butter-smooth expansion/collapse animations
- Rotating arrow indicators with easing curves
- Interactive bounce feedback with
s_bounceable - Elegant toggle switches with
s_toggle
🎯 Developer Friendly:
- Simple, intuitive API
- Two state management modes: Internal (automatic) or external (controlled)
- Comprehensive documentation
- Type-safe parameter configuration
- Callback support for state changes and expansion events
Installation #
Add this to your package's pubspec.yaml file:
dependencies:
settings_item: ^2.0.0
Then run:
flutter pub get
Usage #
State Management (External State) #
Example using external state management:
SettingsItem supports two state management modes:
- Internal State (Uncontrolled) - Widget manages its own state automatically
- External State (Controlled) - Parent widget controls the state
Internal State Management (Recommended for Simple Cases)
No need to manage state in your parent widget! Just set an optional initialState:
// Simple switch with internal state - no state variable needed!
SettingsItem(
parameters: ExpandableParameters(
prefixIcon: Icons.notifications_rounded,
title: 'Notifications',
isSwitch: true,
),
initialState: true, // Optional: defaults to false
onChange: (value) {
// Optional: listen to state changes
print('Notifications: $value');
},
)
External State Management (Controlled Mode)
Full control over state for complex scenarios:
class MySettingsPage extends StatefulWidget {
@override
State<MySettingsPage> createState() => _MySettingsPageState();
}
class _MySettingsPageState extends State<MySettingsPage> {
bool notificationsEnabled = true;
@override
Widget build(BuildContext context) {
return SettingsItem(
parameters: ExpandableParameters(
prefixIcon: Icons.notifications_rounded,
title: 'Notifications',
isSwitch: true,
),
isActive: notificationsEnabled, // Provide external state
onChange: (value) {
setState(() {
notificationsEnabled = value;
});
},
);
}
}
Basic Example - Switch Mode #
import 'package:flutter/material.dart';
import 'package:settings_item/settings_item.dart';
class MySettingsPage extends StatefulWidget {
@override
State<MySettingsPage> createState() => _MySettingsPageState();
}
class _MySettingsPageState extends State<MySettingsPage> {
bool notificationsEnabled = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Settings')),
body: ListView(
padding: EdgeInsets.all(16),
children: [
SettingsExpendableMenu(
parameters: ExpandableParameters(
prefixIcon: Icons.notifications_rounded,
title: 'Notifications',
isSwitch: true,
),
isActive: notificationsEnabled,
onChange: (value) {
setState(() {
notificationsEnabled = value;
});
},
),
],
),
);
}
}
```Internal State
Simplest expandable menu - no state management needed:
```dart
SettingsItem(
parameters: ExpandableParameters(
prefixIcon: Icons.settings_rounded,
title: 'Display Settings',
isExpandeable: true,
expandedWidget: Column(
children: [
ListTile(
leading: Icon(Icons.brightness_6),
title: Text('Brightness'),
onTap: () {
// Handle brightness
},
),
ListTile(
leading: Icon(Icons.text_fields),
title: Text('Font Size'),
onTap: () {
// Handle font size
},
),
],
),
),
// No isActive needed - widget manages its own state!
)
Expandable Mode with Content (External State) #
Expandable Mode with Content #
bool accountExpanded = false;
SettingsExpendableMenu(
parameters: ExpandableParameters(
prefixIcon: Icons.account_circle_rounded,
title: 'Account Settings',
isExpandeable: true,
expandedWidget: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ListTile(
leading: Icon(Icons.person),
title: Text('Edit Profile'),
onTap: () {
// Handle profile edit
},
),
ListTile(
leading: Icon(Icons.lock),
title: Text('Change Password'),
onTap: () {
// Handle password change
},
),
ListTile(
leading: Icon(Icons.logout),
title: Text('Sign Out'),
onTap: () {
// Handle sign out
},
),
],
),
),
isActive: accountExpanded,
onChange: (value) {
setState(() {
accountExpanded = value;
});
},
)
Button Mode (No Expansion) #
bool themeButtonActive = false;
SettingsExpendableMenu(
parameters: ExpandableParameters(
prefixIcon: Icons.palette_rounded,
title: 'Theme Settings',
isExpandeable: false, // Only rotates arrow, doesn't expand
),
isActive: themeButtonActive,
onChange: (value) {
setState(() {
themeButtonActive = value;
});
// Navigate to theme settings page
Navigator.push(context, MaterialPageRoute(
builder: (_) => ThemeSettingsPage(),
));
},
)
Advanced Example - Custom Suffix Widget #
bool privacyExpanded = false;
int privacyLevel = 2;
SettingsExpendableMenu(
parameters: ExpandableParameters(
prefixIcon: Icons.security_rounded,
title: 'Privacy Level',
isExpandeable: true,
suffixWidget: Container(
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.primary.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(8),
),
child: Text(
['Low', 'Medium', 'High'][privacyLevel],
style: TextStyle(
color: Theme.of(context).colorScheme.primary,
fontWeight: FontWeight.w600,
),
),
),
expandedWidget: Column(
children: [
RadioListTile(
title: Text('Low'),
value: 0,
groupValue: privacyLevel,
onChanged: (value) {
setState(() {
privacyLevel = value!;
});
},
),
RadioListTile(
title: Text('Medium'),
value: 1,
groupValue: privacyLevel,
onChanged: (value) {
setState(() {
privacyLevel = value!;
});?` | Current active/expanded state (optional - if null, uses internal state) |
| `initialState` | `bool` | Initial state when using internal state management (defaults to `false`)
},
),
RadioListTile(
title: Text('High'),
value: 2,
groupValue: privacyLevel,
onChanged: (value) {
setState(() {
privacyLevel = value!;
});
},
),
],
),
onExpandedSectionToggle: () {
print('Privacy section toggled!');
},
),
isActive: privacyExpanded,
onChange: (value) {
setState(() {
privacyExpanded = value;
});
},
)
Parameters #
SettingsExpendableMenu #
| Parameter | Type | Description |
|---|---|---|
parameters |
ExpandableParameters |
Configuration for the menu item |
isActive |
bool |
Current active/expanded state |
onChange |
Function(bool)? |
Callback when state changes |
ExpandableParameters #
| Parameter | Type | Default | Description |
|---|---|---|---|
prefixIcon |
IconData? |
null |
Icon displayed on the left |
title |
String? |
"Settings Item" |
Title text of the menu item |
isSwitch |
bool |
false |
Shows toggle switch when true |
isExpandeable |
bool |
true |
Enables content expansion when true |
expandedWidget |
Widget? |
null |
Content shown when expanded |
suffixWidget |
Widget? |
null |
Custom widget on the right (overrides default arrow/switch) |
onExpandedSectionToggle |
VoidCallback? |
null |
Called when expansion state changes |
Dependencies #
This package uses the following dependencies:
- s_bounceable ^2.0.0 - For interactive bounce feedback
- s_toggle ^2.0.1 - For elegant toggle switches
Example App #
A complete example app demonstrating all features is available in the example folder. Run it with:
cd example
flutter run
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.
Author #
SoundSliced
- GitHub: @SoundSliced
Changelog #
See CHANGELOG.md for a list of changes.