Complex Flutter Widgets: Building Advanced UI Components

This complex flutter widgets is posted by seven.srikanth at 5/2/2025 11:40:55 PM



<h1 id="complex-flutter-widgets-building-advanced-ui-components">Complex Flutter Widgets: Building Advanced UI Components</h1> <p>Complex widgets combine multiple basic widgets and implement sophisticated behaviors. Let's explore how to build and implement these advanced UI components.</p> <h2 id="custom-form-widgets">1. Custom Form Widgets</h2> <h3 id="custom-form-field">Custom Form Field</h3> <pre>class CustomFormField extends StatefulWidget { final String label; final String? Function(String?)? validator; final void Function(String?)? onSaved;

const CustomFormField({ Key? key, required this.label, this.validator, this.onSaved, }) : super(key: key);

@override _CustomFormFieldState createState() =&gt; _CustomFormFieldState(); }

class _CustomFormFieldState extends State&lt;CustomFormField&gt; { final _controller = TextEditingController(); bool _isPasswordVisible = false;

@override Widget build(BuildContext context) { return TextFormField( controller: _controller, obscureText: !_isPasswordVisible, decoration: InputDecoration( labelText: widget.label, suffixIcon: IconButton( icon: Icon( _isPasswordVisible ? Icons.visibility_off : Icons.visibility, ), onPressed: () { setState(() ); }, ), ), validator: widget.validator, onSaved: widget.onSaved, ); }

@override void dispose() { _controller.dispose(); super.dispose(); } } </pre> <h3 id="custom-date-picker">Custom Date Picker</h3> <pre>class CustomDatePicker extends StatefulWidget { final DateTime? initialDate; final void Function(DateTime)? onDateSelected;

const CustomDatePicker({ Key? key, this.initialDate, this.onDateSelected, }) : super(key: key);

@override _CustomDatePickerState createState() =&gt; _CustomDatePickerState(); }

class _CustomDatePickerState extends State&lt;CustomDatePicker&gt; { late DateTime _selectedDate;

@override void initState() { super.initState(); _selectedDate = widget.initialDate ?? DateTime.now(); }

Future&lt;void&gt; _selectDate(BuildContext context) async { final DateTime? picked = await showDatePicker( context: context, initialDate: _selectedDate, firstDate: DateTime(2000), lastDate: DateTime(2100), ); if (picked != null &amp;&amp; picked != _selectedDate) { setState(() ); widget.onDateSelected?.call(picked); } }

@override Widget build(BuildContext context) { return InkWell( onTap: () =&gt; _selectDate(context), child: InputDecorator( decoration: InputDecoration( labelText: &#39;Select Date&#39;, suffixIcon: Icon(Icons.calendar_today), ), child: Text( &#39;\({_selectedDate.day}/\)/$&#39;, ), ), ); } } </pre> <h2 id="custom-list-widgets">2. Custom List Widgets</h2> <h3 id="custom-expandable-list">Custom Expandable List</h3> <pre>class ExpandableList extends StatefulWidget { final List&lt;ExpandableItem&gt; items;

const ExpandableList({ Key? key, required this.items, }) : super(key: key);

@override _ExpandableListState createState() =&gt; _ExpandableListState(); }

class _ExpandableListState extends State&lt;ExpandableList&gt; { final Map&lt;int, bool&gt; _expandedItems = ;

@override Widget build(BuildContext context) { return ListView.builder( itemCount: widget.items.length, itemBuilder: (context, index) { final isExpanded = _expandedItems[index] ?? false; return Column( children: [ ListTile( title: Text(widget.items[index].title), trailing: Icon( isExpanded ? Icons.expand_less : Icons.expand_more, ), onTap: () { setState(() { _expandedItems[index] = !isExpanded; }); }, ), if (isExpanded) Padding( padding: EdgeInsets.symmetric(horizontal: 16), child: widget.items[index].content, ), ], ); }, ); } } </pre> <h3 id="custom-draggable-list">Custom Draggable List</h3> <pre>class DraggableList extends StatefulWidget { final List&lt;String&gt; items;

const DraggableList({ Key? key, required this.items, }) : super(key: key);

@override _DraggableListState createState() =&gt; _DraggableListState(); }

class _DraggableListState extends State&lt;DraggableList&gt; { late List&lt;String&gt; _items;

@override void initState() { super.initState(); _items = List.from(widget.items); }

void _onReorder(int oldIndex, int newIndex) { setState(() { if (oldIndex &lt; newIndex) { newIndex -= 1; } final item = _items.removeAt(oldIndex); _items.insert(newIndex, item); }); }

@override Widget build(BuildContext context) { return ReorderableListView( onReorder: _onReorder, children: _items.map((item) { return ListTile( key: ValueKey(item), title: Text(item), ); }).toList(), ); } } </pre> <h2 id="custom-navigation-widgets">3. Custom Navigation Widgets</h2> <h3 id="custom-bottom-navigation">Custom Bottom Navigation</h3> <pre>class CustomBottomNavigation extends StatefulWidget { final List&lt;BottomNavItem&gt; items; final int initialIndex; final void Function(int)? onIndexChanged;

const CustomBottomNavigation({ Key? key, required this.items, this.initialIndex = 0, this.onIndexChanged, }) : super(key: key);

@override _CustomBottomNavigationState createState() =&gt; _CustomBottomNavigationState(); }

class _CustomBottomNavigationState extends State&lt;CustomBottomNavigation&gt; { late int _currentIndex;

@override void initState() { super.initState(); _currentIndex = widget.initialIndex; }

@override Widget build(BuildContext context) { return BottomNavigationBar( currentIndex: _currentIndex, onTap: (index) { setState(() ); widget.onIndexChanged?.call(index); }, items: widget.items.map((item) { return BottomNavigationBarItem( icon: Icon(item.icon), label: item.label, ); }).toList(), ); } } </pre> <h3 id="custom-tab-navigation">Custom Tab Navigation</h3> <pre>class CustomTabNavigation extends StatefulWidget { final List&lt;TabItem&gt; tabs; final int initialIndex; final void Function(int)? onIndexChanged;

const CustomTabNavigation({ Key? key, required this.tabs, this.initialIndex = 0, this.onIndexChanged, }) : super(key: key);

@override _CustomTabNavigationState createState() =&gt; _CustomTabNavigationState(); }

class _CustomTabNavigationState extends State&lt;CustomTabNavigation&gt; with SingleTickerProviderStateMixin { late TabController _tabController;

@override void initState() { super.initState(); _tabController = TabController( length: widget.tabs.length, vsync: this, initialIndex: widget.initialIndex, ); _tabController.addListener(() { widget.onIndexChanged?.call(_tabController.index); }); }

@override Widget build(BuildContext context) { return Column( children: [ TabBar( controller: _tabController, tabs: widget.tabs.map((tab) { return Tab( icon: Icon(tab.icon), text: tab.label, ); }).toList(), ), Expanded( child: TabBarView( controller: _tabController, children: widget.tabs.map((tab) =&gt; tab.content).toList(), ), ), ], ); }

@override void dispose() { _tabController.dispose(); super.dispose(); } } </pre> <h2 id="best-practices">4. Best Practices</h2> <ol> <li><p><strong>Implement proper state management</strong></p> <ul> <li>Use appropriate state management solutions</li> <li>Handle state changes efficiently</li> <li>Clean up resources properly</li> </ul> </li> <li><p><strong>Optimize performance</strong></p> <ul> <li>Use const constructors</li> <li>Implement proper keys</li> <li>Minimize rebuilds</li> </ul> </li> <li><p><strong>Handle edge cases</strong></p> <ul> <li>Test thoroughly</li> <li>Handle errors gracefully</li> <li>Provide fallback UI</li> </ul> </li> </ol> <p>By mastering these complex widgets and following best practices, you can create Flutter applications that are:</p> <ul> <li>More sophisticated</li> <li>More maintainable</li> <li>More performant</li> <li>More user-friendly</li> </ul>


Tags: flutter,markdown,generated








0 Comments
Login to comment.
Recent Comments