【问题标题】:SilverApp hide not working when scrolling滚动时 SilverApp 隐藏不起作用
【发布时间】:2021-05-07 16:07:35
【问题描述】:

当我们向下滚动时,我们想隐藏appBar,只显示tabBar,这和Flutter: hide and display app bar in scrolling detected 一模一样。

但是,它在我们的案例中不起作用。只有当我们点击并滚动appBar时它才会隐藏。

ma​​in.dart

 @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: NestedScrollView(
      body: TabBarView(
        controller: _tabController,
        children: <Widget>[TabA(), TabA()],
      ),
      floatHeaderSlivers: true,
      headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
        return <Widget>[
          SliverAppBar(
            title: Text("Silver App"),
            pinned: true,
            floating: true,
            forceElevated: innerBoxIsScrolled,
            bottom: TabBar(
              unselectedLabelColor: Colors.white,
              labelColor: Colors.white,
              tabs: <Widget>[
                Tab(
                  text: "Tab A",
                ),
                Tab(
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      Text("Tab B"),
                      Padding(
                        padding: EdgeInsets.only(left: 15),
                      ),
                    ],
                  ),
                ),
              ],
              controller: _tabController,
              indicatorColor: Colors.white,
              indicatorSize: TabBarIndicatorSize.tab,
            ),
          ),
        ];
      },
    ));
  } 

TabA.dart

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

class TabA extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _TabAState();
}

class _TabAState extends State<TabA> with SingleTickerProviderStateMixin {
  final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
      new GlobalKey<RefreshIndicatorState>();

  bool isLoading = false;
  ScrollController _controller;
  int page = 1;
  AnimationController controller;
  Animation<Offset> offset;

  @override
  void initState() {
    super.initState();
    _controller = ScrollController()..addListener(_scrollListener);
    controller =
        AnimationController(vsync: this, duration: Duration(milliseconds: 500));

    offset = Tween<Offset>(begin: Offset.zero, end: Offset(0.0, 2.0))
        .animate(controller);
  }

  final data = [
    'T 0',
    'T 1',
    'T 2',
      ...
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        floatingActionButton: SlideTransition(
            position: offset,
            child: FloatingActionButton(
                elevation: 0.0,
                child: Icon(Icons.add, color: Colors.white),
                onPressed: () {})),
        body: RefreshIndicator(
            key: _refreshIndicatorKey,
            onRefresh: _refresh,
            child: _showData()));
  }

  void _scrollListener() async {
    if (_controller.position.pixels == _controller.position.maxScrollExtent) {
      // display loading on bottom of listView
    }
    if (_controller.position.userScrollDirection == ScrollDirection.reverse) {
      setState(() {
        controller.forward();
      });
    }
    if (_controller.position.userScrollDirection == ScrollDirection.forward) {
      setState(() {
        controller.reverse();
      });
    }
  }

  Widget _showData() {
    return Stack(
      children: <Widget>[
        _showListView(),
        // Align(
        //   child: Row(
        //       mainAxisAlignment: MainAxisAlignment.center,
        //       children: <Widget>[
        //         Padding(
        //             padding: EdgeInsets.only(bottom: 15),
        //             child: Text("loading .....",
        //                 style: TextStyle(
        //                   color: const Color(0xff000066),
        //                   fontSize: 15,
        //                 ))),
        //         SizedBox(
        //           width: 12,
        //         ),
        //       ]),
        //   alignment: FractionalOffset.bottomCenter,
        // )
      ],
    );
  }

  Widget _showListView() {
    return ListView.builder(
        controller: _controller,
        itemCount: data.length,
        itemBuilder: (context, index) {
          return Text(data[index]);
        });
  }

  Future<void> _refresh() {
    // return data;
  }
}

输出:

如您所见,appBarlistView 滚动时不会隐藏。只有当我们按下appBar 并滚动时它才会隐藏。

【问题讨论】:

    标签: flutter dart appbar


    【解决方案1】:

    这是基于您的代码的工作代码。

    关键是 'ScrollController' 实例是由 'NestedScrollView' 上下文创建的
    并将该 'ScrollController' 实例传递到 TabBarView 子项中的 'ListView' 内部。

    import 'package:flutter/material.dart';
    import 'package:flutter/rendering.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage>
        with SingleTickerProviderStateMixin {
      TabController _tabController;
    
      @override
      void initState() {
        super.initState();
        _tabController = TabController(initialIndex: 0, length: 2, vsync: this);
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            body: NestedScrollView(
          body: Builder(
            builder: (context) {
              final _scr = PrimaryScrollController.of(context);
              return TabBarView(
                controller: _tabController,
                children: <Widget>[TabA(_scr), TabA(_scr)],
              );
            },
          ),
          floatHeaderSlivers: true,
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            return <Widget>[
              SliverAppBar(
                title: Text("Silver App"),
                pinned: true,
                floating: true,
                forceElevated: innerBoxIsScrolled,
                bottom: TabBar(
                  unselectedLabelColor: Colors.white,
                  labelColor: Colors.white,
                  tabs: <Widget>[
                    Tab(
                      text: "Tab A",
                    ),
                    Tab(
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: <Widget>[
                          Text("Tab B"),
                          Padding(
                            padding: EdgeInsets.only(left: 15),
                          ),
                        ],
                      ),
                    ),
                  ],
                  controller: _tabController,
                  indicatorColor: Colors.white,
                  indicatorSize: TabBarIndicatorSize.tab,
                ),
              ),
            ];
          },
        ));
      }
    }
    
    class TabA extends StatefulWidget {
      final ScrollController scrollController;
    
      TabA(this.scrollController);
    
      @override
      State<StatefulWidget> createState() => _TabAState();
    }
    
    class _TabAState extends State<TabA> with SingleTickerProviderStateMixin {
      final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
          new GlobalKey<RefreshIndicatorState>();
    
      bool isLoading = false;
      int page = 1;
      AnimationController controller;
      Animation<Offset> offset;
    
      @override
      void initState() {
        super.initState();
    
        widget.scrollController.addListener(_scrollListener);
        controller =
            AnimationController(vsync: this, duration: Duration(milliseconds: 500));
    
        offset = Tween<Offset>(begin: Offset.zero, end: Offset(0.0, 2.0))
            .animate(controller);
      }
    
      final data = [
        'T 0',
        'T 1',
        'T 2',
        'T 0',
        'T 1',
        'T 0',
        'T 1',
        'T 2',
        'T 0',
        'T 1',
        'T 2',
        'T 0',
        'T 1',
        'T 2',
        'T 0',
        'T 1',
        'T 2',
        'T 0',
        'T 1',
        'T 2',
        'T 2',
        'T 0',
        'T 1',
        'T 2',
        'T 0',
        'T 1',
        'T 2',
        'T 0',
        'T 1',
        'T 2',
        'T 0',
        'T 1',
        'T 2',
        'T 0',
        'T 1',
        'T 2',
        'T 0',
        'T 1',
        'T 2',
        'T 0',
        'T 1',
        'T 2',
        'T 0',
        'T 1',
        'T 2',
        'T 0',
        'T 1',
        'T 2',
        'T 0',
        'T 1',
        'T 2',
        'T 0',
        'T 1',
        'T 2',
        'T 0',
        'T 1',
        'T 2',
        'T 0',
        'T 1',
        'T 2',
      ];
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            floatingActionButton: SlideTransition(
                position: offset,
                child: FloatingActionButton(
                    elevation: 0.0,
                    child: Icon(Icons.add, color: Colors.white),
                    onPressed: () {})),
            body: RefreshIndicator(
                key: _refreshIndicatorKey,
                onRefresh: _refresh,
                child: _showData()));
      }
    
      void _scrollListener() async {
        if (widget.scrollController.position.pixels ==
            widget.scrollController.position.maxScrollExtent) {
          // display loading on bottom of listView
        }
        if (widget.scrollController.position.userScrollDirection ==
            ScrollDirection.reverse) {
          setState(() {
            controller.forward();
          });
        }
        if (widget.scrollController.position.userScrollDirection ==
            ScrollDirection.forward) {
          setState(() {
            controller.reverse();
          });
        }
      }
    
      Widget _showData() {
        return Stack(
          children: <Widget>[
            _showListView(),
            // Align(
            //   child: Row(
            //       mainAxisAlignment: MainAxisAlignment.center,
            //       children: <Widget>[
            //         Padding(
            //             padding: EdgeInsets.only(bottom: 15),
            //             child: Text("loading .....",
            //                 style: TextStyle(
            //                   color: const Color(0xff000066),
            //                   fontSize: 15,
            //                 ))),
            //         SizedBox(
            //           width: 12,
            //         ),
            //       ]),
            //   alignment: FractionalOffset.bottomCenter,
            // )
          ],
        );
      }
    
      Widget _showListView() {
        return ListView.builder(
            controller: widget.scrollController,
            itemCount: data.length,
            itemBuilder: (context, index) {
              return Text(data[index]);
            });
      }
    
      Future<void> _refresh() {
        // return data;
      }
    }
    

    【讨论】:

      【解决方案2】:

      尝试对 NestedScrollView 和 ListView 使用相同的 ScrollController:

      NestedScrollView(
        controller: _controller,
      
      ListView(
        controller: _controller,
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-21
        • 2016-06-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多