Search code examples
flutterflutter-layoutcustomscrollview

Flutter NestedScrollView header bounce with TabBar and TabbarView


enter image description here

  1. Header pull to refresh can be pulled up when I want to drag it up.
  2. Tabbar sticky.
  3. ListView can swipe to another page.

Solution

  • 100% Custom Widget. It supports to change the header value and also support swipe opeartions.

    It is not actually a TabBar Widget but it Works exactly like that

         import 'package:flutter/material.dart';
    
    import 'dart:math';
    
    
    class NestedScrolls extends StatefulWidget {
    static const   listHeader = ['Pakistan', 'China','Iran','Turkey'];
      @override
      _NestedScrollsState createState() => _NestedScrollsState();
    }
    
    class _NestedScrollsState extends State<NestedScrolls> {
     
    
    var position=0;
      var topHeader;
     Widget? applyWidget() {
    
       switch(position){
         case 0:
           setState(() {
             topHeader = NestedScrolls.listHeader[0];
           });
           // return widget if user click over pakistan in tab bar
           return grid();
         case 1:
           setState(() {
             topHeader = NestedScrolls.listHeader[1];
           });
           return   list();
         case 2:
           setState(() {
             topHeader = NestedScrolls.listHeader[2];
           });
           return Container(color: Colors.blue,
             child: Center(child: Text(topHeader),),);
         case 3:
           setState(() {
             topHeader = NestedScrolls.listHeader[3];
           });
           return Container(color: Colors.orange,
             child: Center(child: Text(topHeader),),);
    
    
       }
    
    
    
      }
    @override
      void initState() {
        // TODO: implement initState
        super.initState();
        //initial header name when activity start first time
         topHeader = NestedScrolls.listHeader[0];
      }
      @override
      Widget build(BuildContext context) {
        topHeader = topHeader;
        return Scaffold(
          // Persistent AppBar that never scrolls
          appBar: AppBar(
            title: Text('AppBar'),
            elevation: 0.0,
          ),
          body:
               Column(
                children: <Widget>[
                  ///header
                  Container(
                    alignment: Alignment.center,
                    color: Colors.blueGrey,
                    height: 90,
                    child: Text(NestedScrolls.listHeader[position]),
                  ),
                  /// tabBar
                  Container(
                    height: 60,
                    width: MediaQuery.of(context).size.width,
                    child: ListView.builder(
                        scrollDirection: Axis.horizontal,
                        itemCount: NestedScrolls.listHeader.length,
                        itemBuilder: (con, index) {
                          return GestureDetector(
                            onTap: () => setState(() {
                              position=index;
                              topHeader = NestedScrolls.listHeader[index];
    
                            }),
                            child: Padding(
                              padding: const EdgeInsets.symmetric(
                                  vertical: 2.0, horizontal: 10),
                              child: Container(alignment: Alignment.center,
                                  width: 100,
                                  color: topHeader==NestedScrolls.listHeader[index]?Colors.black26:Colors.transparent,
                                  child: Text(NestedScrolls.listHeader[index])),
                            ),
                          );
                        }),
                  ),
    
                ///Widget
                Expanded(
                      child: GestureDetector(
    
                          // onHorizontalDragStart: (left){
                          //    print('left : ${left.localPosition.direction}');
                          // // left.globalPosition.dx
                          //
                          // },
                          onHorizontalDragEnd: (start){
                            print('start : ${start.velocity.pixelsPerSecond.dx}');
                            if((start.velocity.pixelsPerSecond.dx)<-700){
                              if(position<NestedScrolls.listHeader.length-1 && position>=0)
                                setState(() {
                                  position=position+1;
                                });
    
    
                            }else{}
    
                          if((start.velocity.pixelsPerSecond.dx)>900){
                            if(position<=NestedScrolls.listHeader.length-1 && position>0)
                              setState(() {
                                position=position-1;
                              });
    
                            }
                            print(position);
                          },
                          child: applyWidget()),
                    ),
    
                ],
              ),
        );
      }
    
      list() {
        return SingleChildScrollView(scrollDirection: Axis.vertical,
          child: Container(
    
    
    
                  child: Column(children: [
                    for(var color in Colors.primaries)
                    Container(color: color, height: 100.0)
    
                  ],),
    
    
    
    
    
    
          ),
        );
      }
    
      grid() {
        return  GridView.count(
            padding: EdgeInsets.zero,
            crossAxisCount: 3,
            children: Colors.primaries.map((color) {
              return Container(color: color, height: 100.0);
            }).toList(),
          );
      }
    }
    

    enter image description here