0

I am trying to design/develop a long page in flutter. It's a long scrollable page. If the page is scrolled a little bit then 4 tabs are visible and user can go to that section either by scrolling or by clicking the tab.

left side image is without scrolling.

image 1 image 2

Right side image is after scrolling a little bit, where 4 tabs are showing. How can I design/develop this page in flutter?

Thanks in advance.

James Z
  • 12,209
  • 10
  • 24
  • 44
Humayun Kabir
  • 561
  • 2
  • 13
  • 27

1 Answers1

0

I have done this using CustomScrollView and scroll_to_index plugin . here is code

class ScrollSample extends StatefulWidget {
  const ScrollSample({Key? key}) : super(key: key);
  @override
  _ScrollSampleState createState() => _ScrollSampleState();
}

class _ScrollSampleState extends State<ScrollSample> {
  late AutoScrollController _autoScrollController;
  final scrollDirection = Axis.vertical;

  bool isExpaned = true;
  bool get _isAppBarExpanded {
    return _autoScrollController.hasClients &&
        _autoScrollController.offset > (160 - kToolbarHeight);
  }

  @override
  void initState() {
    _autoScrollController = AutoScrollController(
      viewportBoundaryGetter: () =>
          Rect.fromLTRB(0, 0, 0, MediaQuery.of(context).padding.bottom),
      axis: scrollDirection,
    )..addListener(
        () => _isAppBarExpanded
            ? isExpaned != false
                ? setState(
                    () {
                      isExpaned = false;
                      print('setState is called');
                    },
                  )
                : {}
            : isExpaned != true
                ? setState(() {
                    print('setState is called');
                    isExpaned = true;
                  })
                : {},
      );
    super.initState();
  }

  Future _scrollToIndex(int index) async {
    await _autoScrollController.scrollToIndex(index,
        preferPosition: AutoScrollPosition.begin);
    _autoScrollController.highlight(index);
  }

  Widget _wrapScrollTag({required int index, required Widget child}) {
    return AutoScrollTag(
      key: ValueKey(index),
      controller: _autoScrollController,
      index: index,
      child: child,
      highlightColor: Colors.black.withOpacity(0.1),
    );
  }

  _buildSliverAppbar() {
    return SliverAppBar(
      brightness: Brightness.light,
      pinned: true,
      expandedHeight: 300.0,
      backgroundColor: Colors.white,
      flexibleSpace: FlexibleSpaceBar(
        collapseMode: CollapseMode.parallax,
        background: BackgroundSliverAppBar(),
      ),
      bottom: PreferredSize(
        preferredSize: Size.fromHeight(40),
        child: AnimatedOpacity(
          duration: Duration(milliseconds: 500),
          opacity: isExpaned ? 0.0 : 1,
          child: DefaultTabController(
            length: 4,
            child: TabBar(
                onTap: (index) async {
                  _scrollToIndex(index);
                },
                tabs: [
                  Tab(
                    text: 'Amber',
                  ),
                  Tab(
                    text: 'Green',
                  ),
                  Tab(
                    text: 'Yellow',
                  ),
                  Tab(
                    text: 'Red',
                  ),
                ]),
          ),
        ),
      ),
    );
  }

  Widget BackgroundSliverAppBar() {
    return Stack(
      children: <Widget>[
        Positioned.fill(
            child: Image.network(
          "https://images.wallpapersden.com/image/download/colorful-neon-bubbles_a2dtaWmUmZqaraWkpJRmbmdlrWZlbWU.jpg",
          fit: BoxFit.cover,
        )),
        Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Text(
                'Join as our member now,\nget discount upto 70%',
                style: TextStyle(color: Colors.white),
              ),
              SizedBox(height: 8.0),
              RaisedButton(
                child: Text(
                  'Subscribe now',
                  style: TextStyle(color: Colors.red),
                ),
                onPressed: () {},
              )
            ],
          ),
        )
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Expanded(
            child: CustomScrollView(
              controller: _autoScrollController,
              slivers: <Widget>[
                _buildSliverAppbar(),
                SliverList(
                    delegate: SliverChildListDelegate([
                  _wrapScrollTag(
                      index: 0,
                      child: Container(
                        height: 300,
                        color: Colors.amber,
                      )),
                  _wrapScrollTag(
                      index: 1,
                      child: Container(
                        height: 700,
                        color: Colors.green,
                      )),
                  _wrapScrollTag(
                      index: 2,
                      child: Container(
                        height: 500,
                        color: Colors.yellow,
                      )),
                  _wrapScrollTag(
                      index: 3,
                      child: Container(
                        height: 500,
                        color: Colors.grey,
                      )),
                ])),
              ],
            ),
          ),
          Container(
            height: 40.0,
            color: Colors.white,
          )
        ],
      ),
    );
  }
}

all credit goes to Nhật Trần . take help from here

Humayun Kabir
  • 561
  • 2
  • 13
  • 27