I'm cloning a social media app design where there are two ListView: an horizontal one for the user stories, and a vertical one for user posts. I've already built them and they work, but I would like to wrap them in a unique ListView with stories at the top, and posts under the stories. If I scroll, the stories should disappear after a while and I should see only posts. How can I do?
UserStory widget:
class UserStory extends StatelessWidget {
const UserStory({super.key});
@override
Widget build(BuildContext context) {
return Column(
children: [
SizedBox(
height: 100,
child: ListView.builder(
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.symmetric(horizontal: 10.0),
scrollDirection: Axis.horizontal,
itemCount: 10,
itemBuilder: (context, i) {
return Container(
width: 60,
height: 60,
margin: const EdgeInsets.symmetric(horizontal: 5.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.grey.shade200,
),
);
},
),
)
],
);
}
}
UserPost widget:
class UserPost extends StatelessWidget {
const UserPost({super.key});
@override
Widget build(BuildContext context) {
return Expanded(
child: ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: 10,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
child: Column(
children: [
ListTile(
leading: Container(
width: 40,
height: 40,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.grey.shade200
),
),
title: const Text("Ava Sadie"),
subtitle: Text("Sylhet, Bangladesh", style: Theme.of(context).textTheme.labelSmall,),
trailing: IconButton(splashRadius: 20.0, onPressed: () {}, icon: const Icon(Icons.more_horiz_outlined),),
),
Container(
width: double.infinity,
height: 250,
margin: const EdgeInsets.only(top: 5.0),
decoration: BoxDecoration(
color: Colors.grey.shade200,
borderRadius: BorderRadius.circular(25.0),
),
),
const SizedBox(height: 5),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
children: [
IconButton(splashRadius: 20.0, onPressed: () {}, icon: const Icon(Icons.favorite_outline,),),
Text("6.2k", style: Theme.of(context).textTheme.displaySmall,),
],
),
const SizedBox(width: 20,),
Row(
children: [
IconButton(splashRadius: 20.0, onPressed: () {}, icon: const Icon(Icons.messenger_outline,),),
Text("2.1k", style: Theme.of(context).textTheme.displaySmall,),
],
),
const SizedBox(width: 20,),
Row(
children: [
IconButton(splashRadius: 20.0, onPressed: () {}, icon: const Icon(Icons.bookmark_border_outlined),),
Text("3.5k", style: Theme.of(context).textTheme.displaySmall,),
],
),
],
)
],
),
);
}
),
);
}
}
HomePage:
import 'package:atlas/pages/widgets/user_post.dart';
import 'package:atlas/pages/widgets/user_story.dart';
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
forceMaterialTransparency: true,
leading: IconButton(
padding: const EdgeInsets.symmetric(horizontal: 30.0),
onPressed: () {},
icon: const Icon(Icons.camera_alt_outlined),
),
actions: [
IconButton(
padding: const EdgeInsets.symmetric(horizontal: 30.0),
onPressed: () {},
icon: const Icon(Icons.email_outlined),
),
],
),
body: const Column(
children: <Widget>[
UserStory(),
UserPost(),
],
),
);
}
}
I tried to wrap the body in a ListView, but it spams some errors and I see neither Stories nor posts
You find two photos of the actual screen, When opening homepage:
here it's all ok, but when I want to scroll stories should disappear and I should see only posts. Instead, as you can see in the second photo, stories stay at the top.
Second photo while scrolling:
You could replace Column
to ListView
at HomePage.
body: ListView(
children: <Widget>[
UserStory(),
UserPost(),
],
),
And add shrinkWrap: true
to ListView
at UserPost widget.
return ListView.builder(
shrinkWrap: true,
...,
);