How to make Column scrollable when overflowed but use expanded otherwise
Try implementing this solution I've just created without the animation you have. Is a scrollable area at the top and a persistent footer.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
home: SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text("My AppBar"),
),
body: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
// Your scrollable widgets here
Container(
height: 100,
color: Colors.green,
),
Container(
height: 100,
color: Colors.blue,
),
Container(
height: 100,
color: Colors.red,
),
],
),
),
),
Container(
child: Text(
'Your footer',
),
color: Colors.blueGrey,
height: 200,
width: double.infinity,
)
],
),
),
),
);
}
}
Kris
Developing apps using flutter and firebase to provide the next generation of digital tools to enhance productivity and communication
Updated on January 01, 2023Comments
-
Kris over 1 year
I am trying to achieve an effect where there is expandable content on the top end of a sidebar, and other links on the bottom of the sidebar. When the content on the top expands to the point it needs to scroll, the bottom links should scroll in the same view.
Here is an example of what I am trying to do, except that it does not scroll. If I wrap a scrollable view around the column, that won't work with the spacer or expanded that is needed to keep the bottom links on bottom:
import 'package:flutter/material.dart'; const Color darkBlue = Color.fromARGB(255, 18, 32, 47); void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData.dark().copyWith( scaffoldBackgroundColor: darkBlue, ), debugShowCheckedModeBanner: false, home: Scaffold( body: Center( child: MyWidget(), ), ), ); } } class MyWidget extends StatefulWidget { @override State<MyWidget> createState() { return MyWidgetState(); } } class MyWidgetState extends State<MyWidget> { List<int> items = [1]; @override Widget build(BuildContext context) { return Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ IconButton( icon: const Icon(Icons.add), onPressed: () { setState(() { items.add(items.last + 1); }); }, ), IconButton( icon: const Icon(Icons.delete), onPressed: () { setState(() { if (items.length != 1) items.removeLast(); }); }, ), ], ), for (final item in items) MyAnimatedWidget( child: SizedBox( height: 200, child: Center( child: Text('Top content item $item'), ), ), ), Spacer(), Container( alignment: Alignment.center, decoration: BoxDecoration(border: Border.all()), height: 200, child: Text('Bottom content'), ) ], ); } } class MyAnimatedWidget extends StatefulWidget { final Widget? child; const MyAnimatedWidget({this.child, Key? key}) : super(key: key); @override State<MyAnimatedWidget> createState() { return MyAnimatedWidgetState(); } } class MyAnimatedWidgetState extends State<MyAnimatedWidget> with SingleTickerProviderStateMixin { late AnimationController controller; @override initState() { controller = AnimationController( value: 0, duration: const Duration(seconds: 1), vsync: this); controller.animateTo(1, curve: Curves.linear); super.initState(); } @override Widget build(BuildContext context) { return AnimatedBuilder( animation: controller, builder: (context, child) { return SizedBox(height: 200 * controller.value, child: widget.child); }); } }
I have tried using a global key to get the size of the spacer and detect after rebuilds whether the spacer has been sized to 0, and if so, re-build the entire widget as a list view (without the spacer) instead of a column. You also need to listen in that case for if the size shrinks and it needs to become a column again, it seemed to make the performance noticeably worse, it was tricky to save the state when switching between column/listview, and it seemed not the best way to solve the problem.
Any ideas?
-
p2kr over 2 yearsYou might want to take look at SliverAppBar
-
Kris over 2 yearsSliverAppBar is interesting, thank you for the tip - however I was unable to find a combination of Slivers to add to a CustomScrollView that will achieve a similar effect for a widget on the bottom of the view.
-
-
Kris over 2 yearsHey thanks for the answer, unfortunately I am specifically looking for a way to avoid this scenario because the footer will take up a significant portion of the screen on a mobile device and will look better to scroll with the rest if it needs to.