SliverList stacked below SliverAppBar in flutter - Stack Overflow

admin2025-04-19  0

I am using slivers to display various kind of content. In some cases I have an empty title in AppBar and would like to push the content up to remove the blank space.

How would I do that?

This is my example:

class SliverPinnedExample extends StatelessWidget {
  final List<String> items = List.generate(30, (i) => 'Item #$i');

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      // Not using extendBodyBehindAppBar here, so the entire Scaffold won't shift up.
      body: CustomScrollView(
        slivers: [
          SliverAppBar(
            pinned: true,
            // This ensures no geometry mismatch with pinned minHeight.
            primary: true, // Tells Flutter to account for the status bar automatically.
            backgroundColor: Colors.transparent,
            elevation: 0,

            leading: IconButton(
              icon: Icon(Icons.arrow_back),
              onPressed: () {
                // back nav
              },
            ),
            actions: [
              IconButton(
                icon: Icon(Icons.search),
                onPressed: () {
                  // search
                },
              ),
            ],
            flexibleSpace: FlexibleSpaceBar(
              background: Container(color: Colors.transparent),
            ),
          ),

          SliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) {
                return Container(
                  height: 60,
                  alignment: Alignment.centerLeft,
                  margin: EdgeInsets.symmetric(horizontal: 16),
                  decoration: BoxDecoration(
                    border: Border(
                      bottom: BorderSide(color: Colors.grey.shade300),
                    ),
                  ),
                  child: Text(
                    items[index],
                    style: TextStyle(fontSize: 18),
                  ),
                );
              },
              childCount: items.length,
            ),
          ),
        ],
      ),
    );
  }
}

As you can see here the empty title with a blank space. I want to get the sliver list exactly above the AppBar. The list/content should begin at some point after below the statusbar.

In iOS you can adjust the paddings with contentInsets, but there is no option for that in flutter.

I am using slivers to display various kind of content. In some cases I have an empty title in AppBar and would like to push the content up to remove the blank space.

How would I do that?

This is my example:

class SliverPinnedExample extends StatelessWidget {
  final List<String> items = List.generate(30, (i) => 'Item #$i');

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      // Not using extendBodyBehindAppBar here, so the entire Scaffold won't shift up.
      body: CustomScrollView(
        slivers: [
          SliverAppBar(
            pinned: true,
            // This ensures no geometry mismatch with pinned minHeight.
            primary: true, // Tells Flutter to account for the status bar automatically.
            backgroundColor: Colors.transparent,
            elevation: 0,

            leading: IconButton(
              icon: Icon(Icons.arrow_back),
              onPressed: () {
                // back nav
              },
            ),
            actions: [
              IconButton(
                icon: Icon(Icons.search),
                onPressed: () {
                  // search
                },
              ),
            ],
            flexibleSpace: FlexibleSpaceBar(
              background: Container(color: Colors.transparent),
            ),
          ),

          SliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) {
                return Container(
                  height: 60,
                  alignment: Alignment.centerLeft,
                  margin: EdgeInsets.symmetric(horizontal: 16),
                  decoration: BoxDecoration(
                    border: Border(
                      bottom: BorderSide(color: Colors.grey.shade300),
                    ),
                  ),
                  child: Text(
                    items[index],
                    style: TextStyle(fontSize: 18),
                  ),
                );
              },
              childCount: items.length,
            ),
          ),
        ],
      ),
    );
  }
}

As you can see here the empty title with a blank space. I want to get the sliver list exactly above the AppBar. The list/content should begin at some point after below the statusbar.

In iOS you can adjust the paddings with contentInsets, but there is no option for that in flutter.

Share Improve this question edited Mar 6 at 15:27 Arny asked Mar 5 at 23:14 ArnyArny 4625 silver badges19 bronze badges 1
  • As you want Item #0 go under the AppBar..... 1. do you want the AppBar to be visible or just the item be under it ? ....2. what is the conditions is required to achieve this scroll ? , just when the title is empty or what ? .....3. do you want this as the initial state of the scrolling or it is persistence ? – Mahmoud Al-shehyby Commented Mar 10 at 21:50
Add a comment  | 

2 Answers 2

Reset to default 0

I already tried your code, and everything appears fine; there's no extra space between the SliverAppBar and SliverList. I'm not sure if this issue is device-specific.

However, you could try defining toolbarHeight in the SliverAppBar.

As I understand from you question:

  1. You have a widget consisting of a List of items and a SliverAppBar.

  2. If the title of this widget is empty the initial position of the List is under the AppBar

  3. And if the title is not empty the initial position of the scrolling is normal position

In Flutter, you can easily handle this behavior using the initialScrollOffset property of a ScrollController.

Demo video of the provided solution: initial_scroll_position

Step 1: Define the ScrollController and Helper Method

Define the controller and initialize it in the initState and define the itemHeight property , also create a helper method to check if the title is empty of not

 late final ScrollController _controller;
  
  double itemHeight = 60.0;

  bool get isTitleEmpty => widget.title.isEmpty;

  @override
  void initState() {
    _controller = ScrollController(
      initialScrollOffset: isTitleEmpty ? itemHeight : 0.0,
    );
    super.initState();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  final List<String> items = List.generate(30, (i) => 'Item #$i');
  • If the title is empty, the initialScrollOffset is set to the height of one list item (itemHeight). This ensures the list starts under the AppBar.

  • If the title is not empty, the initialScrollOffset is set to 0.0, which is the default starting position.

Step 2: Build the Widget and pass the controller


class SliverPinnedExample extends StatefulWidget {
  const SliverPinnedExample({
    super.key,
    required this.title,
  });

  final String title;

  @override
  State<SliverPinnedExample> createState() => _SliverPinnedExampleState();
}

class _SliverPinnedExampleState extends State<SliverPinnedExample> {
  late final ScrollController _controller;
  
  double itemHeight = 60.0;

  bool get isTitleEmpty => widget.title.isEmpty;

  @override
  void initState() {
    _controller = ScrollController(
      initialScrollOffset: isTitleEmpty ? itemHeight : 0.0,
    );
    super.initState();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  final List<String> items = List.generate(30, (i) => 'Item #$i');

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        controller: _controller,
        slivers: <Widget>[
          SliverAppBar(
            pinned: true,
            primary: true,
            backgroundColor: Colors.transparent,
            elevation: 0,
            title: isTitleEmpty ? null : Text(widget.title),
            actions: [
              IconButton(
                icon: const Icon(Icons.search),
                onPressed: () {
                  // search
                },
              ),
            ],
            flexibleSpace: FlexibleSpaceBar(
              background: Container(color: Colors.transparent),
            ),
          ),
          SliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) {
                return Container(
                  height: itemHeight,
                  alignment: Alignment.centerLeft,
                  margin: const EdgeInsets.symmetric(horizontal: 16),
                  decoration: BoxDecoration(
                    border: Border(
                      bottom: BorderSide(color: Colors.grey.shade300),
                    ),
                  ),
                  child: Text(
                    items[index],
                    style: const TextStyle(fontSize: 18),
                  ),
                );
              },
              childCount: items.length,
            ),
          ),
        ],
      ),
    );
  }
}

Hope that was helpful !

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1745003044a279346.html

最新回复(0)