Flutter:在 AppBar 中实现具有滚动和隐藏功能的过滤器

问题描述 投票:0回答:1

我需要在屏幕顶部实现过滤器。这个想法是,当您向下滚动时,过滤器应该消失,但标题和前导小部件应该保持可见。此外,向上滚动时,过滤器应该重新出现。有人对如何实现这一目标有任何建议吗?此功能的最佳用途是什么?

flutter flutter-animation
1个回答
0
投票

您可以使用 ScrollController 来检测滚动方向并结合使用 SliverAppBarSliverPersistentHeader 来实现布局。

import 'package:flutter/material.dart';

class ScrollableFiltersPage extends StatefulWidget {
  @override
  _ScrollableFiltersPageState createState() => _ScrollableFiltersPageState();
}

class _ScrollableFiltersPageState extends State<ScrollableFiltersPage> {
  final ScrollController _scrollController = ScrollController();
  bool _showFilters = true;
  double _lastOffset = 0;

  @override
  void initState() {
    super.initState();
    _scrollController.addListener(() {
      if (_scrollController.offset > _lastOffset && _showFilters) {
        setState(() => _showFilters = false); // Scrolling down
      } else if (_scrollController.offset < _lastOffset && !_showFilters) {
        setState(() => _showFilters = true); // Scrolling up
      }
      _lastOffset = _scrollController.offset;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        controller: _scrollController,
        slivers: [
          SliverAppBar(
            pinned: true,
            title: Text('Title'),
            leading: Icon(Icons.menu),
          ),
          SliverPersistentHeader(
            pinned: true,
            delegate: _FiltersDelegate(
              showFilters: _showFilters,
              child: Container(
                color: Colors.blueGrey,
                height: 50,
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: [
                    TextButton(onPressed: () {}, child: Text("Filter 1")),
                    TextButton(onPressed: () {}, child: Text("Filter 2")),
                    TextButton(onPressed: () {}, child: Text("Filter 3")),
                  ],
                ),
              ),
            ),
          ),
          SliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) => ListTile(title: Text('Item $index')),
              childCount: 50,
            ),
          ),
        ],
      ),
    );
  }
}


class _FiltersDelegate extends SliverPersistentHeaderDelegate {
  final bool showFilters;
  final Widget child;

  _FiltersDelegate({required this.showFilters, required this.child});

  @override
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
    return AnimatedOpacity(
      duration: Duration(milliseconds: 200),
      opacity: showFilters ? 1.0 : 0.0,
      child: child,
    );
  }

  @override
  double get maxExtent => 50.0;
  @override
  double get minExtent => 50.0;
  @override
  bool shouldRebuild(covariant _FiltersDelegate oldDelegate) =>
      showFilters != oldDelegate.showFilters || child != oldDelegate.child;
}

我希望这对您有帮助。 谢谢你:)

© www.soinside.com 2019 - 2024. All rights reserved.