skip to Main Content

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

4

Answers


  1. you will need to use SliverAppBar search for it and you will find what your request

    Login or Signup to reply.
  2. You can try CustomScrollView with SliverList and SliverToBoxAdapter like the below code or use shrinkWrap: true to ListView at UserPost:

    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: CustomScrollView(
            slivers: <Widget>[
              SliverToBoxAdapter(child: UserStory()),
              SliverToBoxAdapter(child: SizedBox(height: 10)), // Spacer between story and posts
              SliverList(delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return UserPost();
                },
                childCount: 10, // Replace this with the actual number of posts
              )),
            ],
          ),
        );
      }
    }
    
    Login or Signup to reply.
  3. 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,
      ...,
    );
    
    Login or Signup to reply.
  4. You can make below changes and it will work:

    Removing the Expanded from UserPost and making, making true the shrinkWrap Property of ListView.builder

     ListView.builder(
            physics: const BouncingScrollPhysics(),
            shrinkWrap: true,
            itemCount: 10,
            itemBuilder: (context, index) {
              /// Your UserPost Code.
            }
     )
    

    And Replace the Column widget with ListView widget in the home screen.

      body: ListView(
        children: const [
          UserStory(),
          UserPost()
        ],
      )
    

    More on you can also remove the Column widget from the UserStory as i don’t i see any use of it.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search