fluttersliverappbar

Add a buttons carousler to a SliverAppBar - flutter


My goal, if possible, is to add a carousel of buttons and a search bar to a SliverAppBar, that way the search bar is persistent and the carousel just shrinks when scrolling down.
This is the current state without the SliverAppBar:

enter image description here

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import 'dart:io';

bool get isIOS => !kIsWeb && Platform.isIOS;

class MainStore extends StatefulWidget {
  MainStore({Key? key}) : super(key: key);

  @override
  State<MainStore> createState() => _MainStoreState();
}

class _MainStoreState extends State<MainStore> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: pageBody(context),
    );
  }
}

Widget pageBody(BuildContext context) {
  return Scaffold(
    body: ListView(
      padding: EdgeInsets.symmetric(vertical: 15.0, horizontal: 15.0),
      scrollDirection: Axis.vertical,
      children: <Widget>[
        //SEARCH BAR
        Container(
          width: MediaQuery.of(context).size.width * 15,
          padding: EdgeInsets.symmetric(vertical: 15.0, horizontal: 15.0),
          child: Material(
            borderRadius: BorderRadius.circular(15.0),
            elevation: 5.0,
            child: TextField(),
          ),
        ),
        SizedBox(
          height: 15.0,
        ),
        Container(
          height: 80.0,
          child: ListView(
              scrollDirection: Axis.horizontal,
              children: new List.generate(10, (int index) {
                return new Card(
                  color: Colors.blue[index * 100],
                  child: new Container(
                    width: 100.0,
                    height: 100.0,
                    child: new Text("$index"),
                  ),
                );
              })),
        ),
        SizedBox(
          height: 15.0,
        ),
        Column(
          children: [
            RichText(
              textAlign: TextAlign.start,
              text: TextSpan(text: 'Premium '),
            ),
            SizedBox(
              height: 15.0,
              child: Divider(color: Colors.black),
            ),
            GridView.count(
              primary: false,
              padding: const EdgeInsets.all(20),
              crossAxisSpacing: 10,
              mainAxisSpacing: 10,
              crossAxisCount: 4,
              physics:
                  NeverScrollableScrollPhysics(), // to disable GridView's scrolling
              shrinkWrap: true,
              children: <Widget>[
                Container(
                  padding: const EdgeInsets.all(8),
                  child: const Text("He'd have you all unravel at the"),
                  color: Colors.teal[100],
                ),
                Container(
                  padding: const EdgeInsets.all(8),
                  child: const Text('Heed not the rabble'),
                  color: Colors.teal[200],
                ),
                Container(
                  padding: const EdgeInsets.all(8),
                  child: const Text('Sound of screams but the'),
                  color: Colors.teal[300],
                ),
                Container(
                  padding: const EdgeInsets.all(8),
                  child: const Text('Who scream'),
                  color: Colors.teal[400],
                ),
                Container(
                  padding: const EdgeInsets.all(8),
                  child: const Text('Revolution is coming...'),
                  color: Colors.teal[500],
                ),
                Container(
                  padding: const EdgeInsets.all(8),
                  child: const Text('Revolution, they...'),
                  color: Colors.teal[600],
                ),
              ],
            ),
          ],
        ),
        Column(
          children: [
            RichText(
              textAlign: TextAlign.start,
              text: TextSpan(text: 'Rones '),
            ),
            SizedBox(
              height: 15.0,
              child: Divider(color: Colors.black),
            ),
            GridView.count(
              primary: false,
              padding: const EdgeInsets.all(20),
              crossAxisSpacing: 10,
              mainAxisSpacing: 10,
              crossAxisCount: 4,
              physics:
                  NeverScrollableScrollPhysics(), // to disable GridView's scrolling
              shrinkWrap: true,
              children: <Widget>[
                Container(
                  padding: const EdgeInsets.all(8),
                  child: const Text("He'd have you all unravel at the"),
                  color: Colors.teal[100],
                ),
                Container(
                  padding: const EdgeInsets.all(8),
                  child: const Text('Heed not the rabble'),
                  color: Colors.teal[200],
                ),
                Container(
                  padding: const EdgeInsets.all(8),
                  child: const Text('Sound of screams but the'),
                  color: Colors.teal[300],
                ),
                Container(
                  padding: const EdgeInsets.all(8),
                  child: const Text('Who scream'),
                  color: Colors.teal[400],
                ),
                Container(
                  padding: const EdgeInsets.all(8),
                  child: const Text('Revolution is coming...'),
                  color: Colors.teal[500],
                ),
                Container(
                  padding: const EdgeInsets.all(8),
                  child: const Text('Revolution, they...'),
                  color: Colors.teal[600],
                ),
              ],
            ),
          ],
        ),
        Column(
          children: [
            RichText(
              textAlign: TextAlign.left,
              text: TextSpan(text: 'Rones '),
            ),
            SizedBox(
              height: 15.0,
              child: Divider(color: Colors.black),
            ),
            GridView.count(
              primary: false,
              padding: const EdgeInsets.all(20),
              crossAxisSpacing: 10,
              mainAxisSpacing: 10,
              crossAxisCount: 4,
              physics:
                  NeverScrollableScrollPhysics(), // to disable GridView's scrolling
              shrinkWrap: true,
              children: <Widget>[
                Container(
                  padding: const EdgeInsets.all(8),
                  child: const Text("He'd have you all unravel at the"),
                  color: Colors.teal[100],
                ),
                Container(
                  padding: const EdgeInsets.all(8),
                  child: const Text('Heed not the rabble'),
                  color: Colors.teal[200],
                ),
                Container(
                  padding: const EdgeInsets.all(8),
                  child: const Text('Sound of screams but the'),
                  color: Colors.teal[300],
                ),
                Container(
                  padding: const EdgeInsets.all(8),
                  child: const Text('Who scream'),
                  color: Colors.teal[400],
                ),
                Container(
                  padding: const EdgeInsets.all(8),
                  child: const Text('Revolution is coming...'),
                  color: Colors.teal[500],
                ),
                Container(
                  padding: const EdgeInsets.all(8),
                  child: const Text('Revolution, they...'),
                  color: Colors.teal[600],
                ),
              ],
            ),
          ],
        )
      ],
    ),
    resizeToAvoidBottomInset: true,
  );
}


This happens when I try to add the carousel to the SliverAppBar, and I can find a way to add the rest of the widgets of the previous image.

enter image description here

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import 'dart:io';

bool get isIOS => !kIsWeb && Platform.isIOS;

class MainStore extends StatefulWidget {
  MainStore({Key? key}) : super(key: key);

  @override
  State<MainStore> createState() => _MainStoreState();
}

class _MainStoreState extends State<MainStore> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: pageBody(context),
    );
  }
}

Widget pageBody(BuildContext context) {
  bool _pinned = true;
  bool _snap = false;
  bool _floating = false;
  return Scaffold(
    body: CustomScrollView(
      slivers: <Widget>[
        SliverAppBar(
          pinned: _pinned,
          snap: _snap,
          floating: _floating,
          expandedHeight: 200.0,
          flexibleSpace: const FlexibleSpaceBar(
            // title: Text('SliverAppBar'),
            background: FlutterLogo(),
          ),
          actions: <Widget>[
            Container(
              width: MediaQuery.of(context).size.width,
              padding: EdgeInsets.symmetric(vertical: 15.0, horizontal: 15.0),
              child: Material(
                borderRadius: BorderRadius.circular(15.0),
                elevation: 5.0,
                child: TextField(),
              ),
            ),
            new Container(
                height: 80.0,
                child: new ListView(
                    scrollDirection: Axis.horizontal,
                    children: new List.generate(10, (int index) {
                      return new Card(
                          color: Colors.blue[index * 100],
                          child: new Container(
                            width: 50.0,
                            height: 50.0,
                            child: new Text("$index"),
                          ));
                    })))
          ],
        ),
        SliverToBoxAdapter(
            child: Container(
          height: 100.0,
          child: ListView.builder(
            scrollDirection: Axis.horizontal,
            itemCount: 10,
            itemBuilder: (context, index) {
              return Container(
                width: 100.0,
                child: Card(
                  child: Text('data'),
                ),
              );
            },
          ),
        )),
      ],
    ),
    
  );
}


Solution

  • You can use FlexibleSpaceBar's title to place the horizontal list.

    SliverAppBar(
      pinned: _pinned,
      snap: _snap,
      floating: _floating,
      expandedHeight: 200.0,
      flexibleSpace: FlexibleSpaceBar(
        background: FlutterLogo(),
        title: Container(
          height: 80.0,
          alignment: Alignment.bottomCenter,
          child: SingleChildScrollView(
            primary: false,
            scrollDirection: Axis.horizontal,
            child: Row(
              children: List.generate(
                10,
                (int index) {
                  return Card(
                      color: Colors.blue[index * 100],
                      child: Container(
                        width: 50.0,
                        height: 50.0,
                        child: Text("$index"),
                      ));
                },
              ),
            ),
          ),
        ),
      ),
      actions: <Widget>[
        Container(
          width: MediaQuery.of(context).size.width,
          padding: EdgeInsets.symmetric(vertical: 15.0, horizontal: 15.0),
          child: Material(
            borderRadius: BorderRadius.circular(15.0),
            elevation: 5.0,
            child: TextField(),
          ),
        ),
      ],
    )
    

    enter image description here

    Also, you can check bottom on SliverAppBar.