0

I learned the use of sliver widget in flutter two days ago, and I was playing with it to grow my skills. I was building one kind of imaginary project and I faced a problem there.

let's think, there is 15 container in my body's container under x widget which allow them to scroll vertically.Now, My objective here, when I am scrolling, I want when the container number 5 reached the top,the container number 5 will stuck there like a appbar or like sliver appbar and others will scroll under it.

Here I am using sliver and SliverFixedExtentList under CustomScrollView widget to give an idea of my objective, if there is any other option without slivers please feel free to share with me. Thanks in advance :)

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: CustomScrollView(
          slivers: <Widget>[
            SliverAppBar(
                actions: <Widget>[
                  Icon(
                    Icons.camera_front,
                    size: 40,
                  )
                ],
                title: Text("Sliver Example"),
                leading: Icon(Icons.menu),
                backgroundColor: Colors.green,
                expandedHeight: 100.0,
                floating: true,
                pinned: true),
            SliverFixedExtentList(
              itemExtent: 75,
              delegate: SliverChildListDelegate([
                Container(
                  color: Colors.blue,
                  child: Text("1"),
                ),
                Container(
                  color: Colors.pink,
                  child: Text("2"),
                ),
                Container(
                  color: Colors.yellow,
                  child: Text("3"),
                ),
                Container(
                  color: Colors.red,
                  child: Text("4"),
                ),
                Container(
                  color: Colors.black,
                  child: Text(
                    "Desired Appbar Conainer  number 5, which will stuck\n there instead of the sliverappbar sliver example when it reached to the top ",
                    style: TextStyle(color: Colors.white),
                  ),
                ),
                Container(
                  color: Colors.amber,
                  child: Text("6"),
                ),
                Container(
                  color: Colors.blue,
                  child: Text("7"),
                ),
                Container(
                  color: Colors.yellow,
                  child: Text("8"),
                ),
                Container(
                  color: Colors.blue,
                  child: Text("9"),
                ),
                Container(
                  color: Colors.pink,
                  child: Text("10"),
                ),
                Container(
                  color: Colors.blue,
                  child: Text("11"),
                ),
                Container(
                  color: Colors.yellow,
                  child: Text("12"),
                ),
                Container(
                  color: Colors.blue,
                  child: Text("13"),
                ),
                Container(
                  color: Colors.purpleAccent,
                  child: Text("14"),
                ),
                Container(
                  color: Colors.white,
                  child: Text("15"),
                ),
              ]),
            ),
          ],
        ),
      ),
    );
  }
}
xahid_rocks
  • 632
  • 8
  • 24

2 Answers2

2

Seems I found a working solution of this problem.The answer is Based on => this post

Here is the code of mine to resolve the issue -

import 'package:flutter/material.dart';
import 'dart:math' as math;

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  SliverPersistentHeader makeHeader(String headerText) {
    return SliverPersistentHeader(
      pinned: true,
      delegate: _SliverAppBarDelegate(
        minHeight: 75.0,
        maxHeight: 75.0,
        child: Container(
          color: Colors.black,
          child: Center(
            child: Text(
              headerText,
              style: TextStyle(color: Colors.white),
            ),
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: CustomScrollView(
          slivers: <Widget>[
            SliverFixedExtentList(
              itemExtent: 75,
              delegate: SliverChildListDelegate([
                Container(
                  color: Colors.blue,
                  child: Text("1"),
                ),
                Container(
                  color: Colors.pink,
                  child: Text("2"),
                ),
                Container(
                  color: Colors.yellow,
                  child: Text("3"),
                ),
                Container(
                  color: Colors.red,
                  child: Text("4"),
                ),
              ]),
            ),
            makeHeader("Container Number 5"),
            SliverFixedExtentList(
              itemExtent: 75,
              delegate: SliverChildListDelegate([
                Container(
                  color: Colors.amber,
                  child: Text("6"),
                ),
                Container(
                  color: Colors.blue,
                  child: Text("7"),
                ),
                Container(
                  color: Colors.yellow,
                  child: Text("8"),
                ),
                Container(
                  color: Colors.blue,
                  child: Text("9"),
                ),
                Container(
                  color: Colors.pink,
                  child: Text("10"),
                ),
                Container(
                  color: Colors.blue,
                  child: Text("11"),
                ),
                Container(
                  color: Colors.yellow,
                  child: Text("12"),
                ),
                Container(
                  color: Colors.blue,
                  child: Text("13"),
                ),
                Container(
                  color: Colors.purpleAccent,
                  child: Text("14"),
                ),
                Container(
                  color: Colors.white,
                  child: Text("15"),
                ),
                Container(
                  color: Colors.yellow,
                  child: Text("12"),
                ),
                Container(
                  color: Colors.blue,
                  child: Text("13"),
                ),
                Container(
                  color: Colors.purpleAccent,
                  child: Text("14"),
                ),
                Container(
                  color: Colors.white,
                  child: Text("15"),
                ),
                Container(
                  color: Colors.yellow,
                  child: Text("12"),
                ),
                Container(
                  color: Colors.blue,
                  child: Text("13"),
                ),
                Container(
                  color: Colors.purpleAccent,
                  child: Text("14"),
                ),
                Container(
                  color: Colors.white,
                  child: Text("15"),
                ),
                Container(
                  color: Colors.yellow,
                  child: Text("12"),
                ),
                Container(
                  color: Colors.blue,
                  child: Text("13"),
                ),
                Container(
                  color: Colors.purpleAccent,
                  child: Text("14"),
                ),
                Container(
                  color: Colors.white,
                  child: Text("15"),
                ),
              ]),
            ),
          ],
        ),
      ),
    );
  }
}

class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  _SliverAppBarDelegate({
    @required this.minHeight,
    @required this.maxHeight,
    @required this.child,
  });

  final double minHeight;
  final double maxHeight;
  final Widget child;

  @override
  double get minExtent => minHeight;

  @override
  double get maxExtent => math.max(maxHeight, minHeight);

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return new SizedBox.expand(child: child);
  }

  @override
  bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
    return maxHeight != oldDelegate.maxHeight ||
        minHeight != oldDelegate.minHeight ||
        child != oldDelegate.child;
  }
}

Hope this will help someone like me :)

xahid_rocks
  • 632
  • 8
  • 24
1

your idea is still working, just need a little tweak, instead of using SliverFixedExtentList, you can use this, flutter_sticky_header, it provides sticky sliver list header, for your case, you can just set one header:

import 'package:flutter/material.dart';
import 'package:flutter_sticky_header/flutter_sticky_header.dart';

import '../common.dart';

class ListExample extends StatelessWidget {
  const ListExample({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      slivers: [
        //SliverAppBar(),
        //SliverList(),
        _StickyHeaderList(index: 2),
        //SliverList(),
      ],
    );
  }
}

class _StickyHeaderList extends StatelessWidget {
  const _StickyHeaderList({
    Key key,
    this.index,
  }) : super(key: key);

  final int index;

  @override
  Widget build(BuildContext context) {
    return SliverStickyHeader(
      header: Header(index: index),
      sliver: SliverList(
        delegate: SliverChildBuilderDelegate(
          (context, i) => ListTile(
            leading: CircleAvatar(
              child: Text('$index'),
            ),
            title: Text('List tile #$i'),
          ),
          childCount: 6,
        ),
      ),
    );
  }
}
Jim
  • 6,928
  • 1
  • 7
  • 18