Skip to content

Instantly share code, notes, and snippets.

@CharlVS
Last active August 21, 2024 08:27
Show Gist options
  • Save CharlVS/97720a3b17ce849fb6c040e4ad2faa74 to your computer and use it in GitHub Desktop.
Save CharlVS/97720a3b17ce849fb6c040e4ad2faa74 to your computer and use it in GitHub Desktop.
Nested scrollable Flutter example
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