I’m making a flutter web application and want to restrict screen’s width but at the same time keep the whole screen scrollable like it’s done in twitter website.
I use primary Scaffold to determine whether to show bottomAppBar or navigation rail. Inside body of that Scaffold I put inner Scaffolds wrapped iniside ContrainedBox(maxWidth: 650) so I restrict the width of the content. The problem is that scroll bar is attached to inner Scaffolds but not to the screen. Below is the minimum representation code.
class MinimalHomeScreen extends StatelessWidget {
const MinimalHomeScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
final bool isMobile = constraints.maxWidth <= 600;
return Scaffold(
// show bottom bar if width is small
bottomNavigationBar: isMobile
? BottomNavigationBar(
items: [
BottomNavigationBarItem(icon: Icon(Icons.home)),
BottomNavigationBarItem(icon: Icon(Icons.search)),
],
)
: null,
// The content is centered and its maxWidth is 650
body: Center(
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: 650),
child: Row(
children: [
// show navigation rail if width is not small
if (!isMobile)
NavigationRail(
destinations: [
NavigationRailDestination(icon: Icon(Icons.home), label: Text('Home')),
NavigationRailDestination(icon: Icon(Icons.search), label: Text('Search')),
],
selectedIndex: 0,
),
// show content
Expanded(
child: Scaffold(
appBar: AppBar(title: Text('Title')),
body: ListView.separated(
itemCount: 100,
itemBuilder: (_, __) {
return Container(
height: 50,
width: double.infinity,
color: Colors.green,
);
},
separatorBuilder: (_, __) {
return Divider();
},
),
),
),
],
),
),
),
);
}
);
}
}
I need to scroll my content from any part of screen but I don’t really know how to do that. I also need to use inner scaffolds to have logic inside them like back button on AppBar.
I think I have to use NestedScrollView or CustomScrollView but I didn’t come up with solution after hours of attemps. I also looked into ‘responsive framework’ package but it also remains scrolling for only scrollable part of content but not the whole screen. If someone knows how to solve this typical issue, please, help!
2
Answers
It's possible to listen the whole screen scrolling in web like this:
So we can get scroll offset, put it in some stream, get it from widget which contains ListView/GridView etc, calculate offset inside ScrollController and use jumpTo() method of ScrollController. But the problem is that the given trackpad offset from onMouseWheel is little. So after hours of trying different ways like Listener widget and some libraries I decided to stop slaming my head against the wall and redisign my application. I hope there'll come a day when such a task is solved easily
To achieve a scrollable screen (no matter where the user scrolls) with a restricted width, you can use a combination of
SingleChildScrollView
,Row
andExpanded
.In the example below,
SingleChildScrollView
is used as the main container, ensuring the entire screen is scrollable. TheConstrainedBox
is used to restrict the minimum width of the content to 650 pixels. The content is wrapped in aColumn
, which includes theAppBar
at the top and theRow
below it. TheNavigationRail
is placed on the left side, and the main content is placed in anExpanded
widget to take up the remaining width.Note: Formatting of close brackets for easier viewing. 🙂
EDIT 1
Given your comment, you can use a combination of
NestedScrollView
andSilverList
.NestedScrollView
is used as the main container, with aSliverAppBar
as the header (remaining pinned at the top and can float when scrolling). Inside theNestedScrollView
, theSingleChildScrollView
is used to wrap the restricted content. TheColumn
contains theNavigationRail
on the left side and theListView.builder
as the main content. TheListView.builder
hasshrinkWrap
set totrue
andphysics
set toNeverScrollableScrollPhysics()
to ensure that it only takes up the necessary space and doesn’t scroll independently.