Last active
August 21, 2024 08:27
-
-
Save CharlVS/97720a3b17ce849fb6c040e4ad2faa74 to your computer and use it in GitHub Desktop.
Nested scrollable Flutter example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
void main() => runApp(MyApp()); | |
class MyApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
home: SliverDemo(), | |
); | |
} | |
} | |
class SliverDemo extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return AppPage( | |
appBar: AppBar( | |
title: Text('Sliver Demo with Fixed Sidebar'), | |
), | |
sidebar: Sidebar(), | |
footer: Container( | |
height: 60, | |
color: Colors.grey[300], | |
child: Center( | |
child: Text('Fixed Footer'), | |
), | |
), | |
content: CustomScrollView( | |
slivers: <Widget>[ | |
// Sliver for the top fixed-height container | |
SliverToBoxAdapter( | |
child: Container( | |
height: 300, // Fixed height container | |
color: Colors.blue, | |
child: Center( | |
child: Text( | |
'Fixed Height Container \n(Charts here)', | |
style: TextStyle( | |
fontSize: 24, | |
color: Colors.white, | |
), | |
textAlign: TextAlign.center, | |
), | |
), | |
), | |
), | |
// Sliver Persistent Header for the pinned search bar | |
SliverPersistentHeader( | |
pinned: true, | |
delegate: _SliverSearchBarDelegate(), | |
), | |
// SliverList for the coin list, nested in a separate widget | |
CoinList(), | |
], | |
), | |
); | |
} | |
} | |
// AppPage widget with appBar, sidebar, content, and footer | |
class AppPage extends StatelessWidget { | |
final PreferredSizeWidget appBar; | |
final Widget sidebar; | |
final Widget content; | |
final Widget footer; | |
AppPage({ | |
required this.appBar, | |
required this.sidebar, | |
required this.content, | |
required this.footer, | |
}); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: appBar, | |
body: Row( | |
children: <Widget>[ | |
// Fixed Sidebar | |
Container( | |
width: 250, | |
color: Colors.grey[200], | |
child: sidebar, | |
), | |
// Main content area | |
Expanded( | |
child: Column( | |
children: <Widget>[ | |
Expanded( | |
child: content, | |
), | |
footer, // Fixed Footer at the bottom of the content | |
], | |
), | |
), | |
], | |
), | |
); | |
} | |
} | |
// Sidebar Widget | |
class Sidebar extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return ListView( | |
padding: EdgeInsets.zero, | |
children: <Widget>[ | |
DrawerHeader( | |
decoration: BoxDecoration( | |
color: Colors.blueAccent, | |
), | |
child: Text( | |
'Sidebar Header', | |
style: TextStyle( | |
color: Colors.white, | |
fontSize: 24, | |
), | |
), | |
), | |
ListTile( | |
leading: Icon(Icons.home), | |
title: Text('Home'), | |
onTap: () {}, | |
), | |
ListTile( | |
leading: Icon(Icons.settings), | |
title: Text('Settings'), | |
onTap: () {}, | |
), | |
], | |
); | |
} | |
} | |
// CoinList widget for displaying a list of items | |
class CoinList extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return SliverList( | |
delegate: SliverChildBuilderDelegate( | |
(BuildContext context, int index) { | |
return ListTile( | |
title: Text('Coin #$index'), | |
); | |
}, | |
childCount: 200, // Number of items in the list | |
), | |
); | |
} | |
} | |
// Delegate for the search bar header | |
class _SliverSearchBarDelegate extends SliverPersistentHeaderDelegate { | |
@override | |
double get minExtent => 60; | |
@override | |
double get maxExtent => 60; | |
@override | |
Widget build( | |
BuildContext context, double shrinkOffset, bool overlapsContent) { | |
return Container( | |
color: Colors.white, | |
padding: EdgeInsets.all(8), | |
child: Row( | |
children: <Widget>[ | |
ElevatedButton( | |
onPressed: () { | |
// Logic to add coins | |
}, | |
child: Text('Add coins'), | |
), | |
Spacer(), | |
SizedBox( | |
width: 200, | |
child: TextField( | |
decoration: InputDecoration( | |
hintText: 'Search coins...', | |
prefixIcon: Icon(Icons.search), | |
border: OutlineInputBorder( | |
borderRadius: BorderRadius.circular(8), | |
), | |
), | |
), | |
), | |
], | |
), | |
); | |
} | |
@override | |
bool shouldRebuild(_SliverSearchBarDelegate oldDelegate) { | |
return false; // No need to rebuild if the content doesn't change | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment