Reputation: 351
I'm working on a Flutter app where I want a screen layout with the following structure:
My goal is to achieve the following scrolling behavior:
When scrolling, the row should stay fixed, allowing the list and grid to scroll independently.
When the list and grid reach their topmost elements, the carousel and list above should start to appear as the user scrolls down.
Currently, I'm facing two issues:
The top elements (carousel and list) hide slowly instead of instantly.
The list and grid scroll together, and when scrolling down, the top elements appear first before the list and grid start scrolling.
Below are the images:
Below is a simplified version of my code:
Scaffold(
appBar: AppBar(
title: Text('Sample'),
centerTitle: true,
),
body: SafeArea(
child: NestedScrollView(
floatHeaderSlivers: true,
headerSliverBuilder: (context, innerBoxIsScrolled) {
return [
SliverOverlapAbsorber(
handle:
NestedScrollView.sliverOverlapAbsorberHandleFor(context),
sliver: SliverAppBar(
automaticallyImplyLeading: false,
flexibleSpace: FlexibleSpaceBar(
background: sampleTopCard(),
),
expandedHeight: 360,
floating: true,
snap: true,
forceElevated: innerBoxIsScrolled,
),
),
];
},
body: sampleBody(),
),
),
);
}
Widget sampleBody() {
return Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: ListView.builder(
padding: const EdgeInsets.symmetric(vertical: 10),
shrinkWrap: true,
itemCount: controller.list.length,
itemBuilder: (context, index) {
return SizedBox(
height: 150,
width: 80,
child: Card(
color: Colors.purpleAccent.withOpacity(0.5),
child: Center(
child: Text(
'Left List Card',
textAlign: TextAlign.center,
),
),
),
);
},
),
),
Expanded(
flex: 3,
child: GridView.builder(
padding: const EdgeInsets.all(5),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: Get.width * 0.02,
mainAxisSpacing: 10,
childAspectRatio: 0.60,
),
itemCount: 10,
itemBuilder: (context, index) {
return Card(
color: Colors.greenAccent.withOpacity(0.5),
child: Center(
child: Text(
'Right Grid Card',
textAlign: TextAlign.center,
),
),
);
},
),
),
],
);
}
Widget sampleTopCard() {
return Container(
color: Colors.white,
height: 420,
width: Get.width,
child: Column(
children: [
SizedBox(
width: Get.width - 20,
height: 100,
child: CarouselWidget(
controller: controller,
carouselWidget: Card(
color: Colors.pink.withOpacity(0.5),
child: Center(child: Text('Carousel Card')),
),
),
),
SizedBox(height: 10),
DotIndicatorWidget(controller: controller),
SizedBox(height: 20),
Container(
height: 220,
padding: const EdgeInsets.only(left: 10),
color: Colors.grey[200],
width: Get.width,
child: ListView.separated(
separatorBuilder: (ctx, idx) => const SizedBox(width: 10),
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.symmetric(vertical: 10),
shrinkWrap: true,
itemCount: controller.list.length,
itemBuilder: (context, index) {
return SizedBox(
height: 100,
width: 150,
child: Card(
color: Colors.blueAccent.withOpacity(0.5),
child: Center(child: Text('List Card')),
),
);
},
),
),
],
),
);
Upvotes: 3
Views: 72