Efficient Navigator Management in Flutter gives better app performance
Tabs or Bottom Navigator Bar
You can use the TabBar widget along with TabBarView to implement tabs. Each tab represents a different section or view within the same screen. Users can switch between tabs to access different content.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
title: Text('Tabs Example'),
bottom: TabBar(
tabs: [
Tab(text: 'Tab 1'),
Tab(text: 'Tab 2'),
Tab(text: 'Tab 3'),
],
),
),
body: TabBarView(
children: [
// Widget content for Tab 1
Container(
child: Text('Tab 1 Content'),
),
// Widget content for Tab 2
Container(
child: Text('Tab 2 Content'),
),
// Widget content for Tab 3
Container(
child: Text('Tab 3 Content'),
),
],
),
),
),
);
}
}
Modal Bottom Sheets or Dialogs
Instead of navigating to a separate screen, you can use the showModalBottomSheet function to display a modal bottom sheet. It provides quick access to additional information or options without interrupting the current context.
void _showModalBottomSheet(BuildContext context) {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return Container(
child: Text('Modal Bottom Sheet Content'),
);
},
);
}
For more details view Flutter Bottomsheet
Page Reveal or Slide Reveal
You can use animations or gestures to reveal additional content within the current screen. For example, swiping left or right can slide-reveal a sidebar menu, providing navigator options without navigating to a separate screen.
class SlideRevealExample extends StatefulWidget {
@override
_SlideRevealExampleState createState() => _SlideRevealExampleState();
}
class _SlideRevealExampleState extends State<SlideRevealExample> {
bool isSidebarOpen = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Slide Reveal Example'),
),
body: Stack(
children: [
// Main Content
Container(
child: Text('Main Content'),
),
// Sidebar
AnimatedPositioned(
duration: Duration(milliseconds: 300),
top: 0,
left: isSidebarOpen ? 0 : -200,
right: isSidebarOpen ? 0 : 200,
bottom: 0,
child: Container(
color: Colors.grey,
child: Text('Sidebar'),
),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
isSidebarOpen = !isSidebarOpen;
});
},
child: Icon(isSidebarOpen ? Icons.close : Icons.menu),
),
);
}
}
Expandable Widgets
Use the ExpansionPanel or ExpansionTile widgets to create expandable sections within a single screen. This allows users to view detailed information or nested options without navigating to separate screens.
class ExpandableExample extends StatefulWidget {
@override
_ExpandableExampleState createState() => _ExpandableExampleState();
}
class _ExpandableExampleState extends State<ExpandableExample> {
bool isExpanded = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Expandable Example'),
),
body: ListView(
children: [
ExpansionPanelList(
expandedHeaderPadding: EdgeInsets.zero,
elevation: 1,
children: [
ExpansionPanel(
headerBuilder: (BuildContext context, bool isExpanded) {
return ListTile(
title: Text('Expandable Item'),
);
},
body: ListTile(
title: Text('Expanded Content'),
),
isExpanded: isExpanded,
),
],
expansionCallback: (int index, bool isExpanded) {
setState(() {
this.isExpanded = !isExpanded;
});
},
),
],
),
);
}
}
Scrolling Content
Implement a ListView, GridView, or SliverAppBar to display large sets of information within a single screen. Users can scroll through the content without the need for separate navigator.
class ScrollingContentExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Scrolling Content Example'),
),
body: ListView.builder(
itemCount: 100,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text('Item $index'),
);
},
),
);
}
}
State Management
Use the provider package for state management. You can share data between different parts of your app without navigating between screens. For example, update the shared state when a user performs an action in one part of the app, and the changes are reflected in another part of the app.
class CounterModel extends ChangeNotifier {
int _counter = 0;
int get counter => _counter;
void incrementCounter() {
_counter++;
notifyListeners();
}
}
class CounterWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final counter = Provider.of<CounterModel>(context).counter;
return Text('Counter: $counter');
}
}
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => CounterModel(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('State Management Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CounterWidget(),
RaisedButton(
onPressed: () {
Provider.of<CounterModel>(context, listen: false)
.incrementCounter();
},
child: Text('Increment'),
),
],
),
),
),
);
}
}
Conditional Rendering
Conditionally render UI components based on user interactions or application state. For instance, show different views or widgets within the same screen based on user choices or conditions, reducing the need for separate navigator.
class ConditionalRenderingExample extends StatefulWidget {
@override
_ConditionalRenderingExampleState createState() =>
_ConditionalRenderingExampleState();
}
class _ConditionalRenderingExampleState
extends State<ConditionalRenderingExample> {
bool showContent = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Conditional Rendering Example'),
),
body: Column(
children: [
RaisedButton(
onPressed: () {
setState(() {
showContent = !showContent;
});
},
child: Text(showContent ? 'Hide Content' : 'Show Content'),
),
if (showContent) ...[
Text('Content 1'),
Text('Content 2'),
],
],
),
);
}
}