返回顶部
首页 > 资讯 > 移动开发 >flutter实现一个列表下拉抽屉的示例代码
  • 611
分享到

flutter实现一个列表下拉抽屉的示例代码

2024-04-02 19:04:59 611人浏览 安东尼
摘要

目录使用源码使用 通过监听滚动事件实现DraGopenDrawer 组件,可以给滚动组件添加一个下拉抽屉。其使用方式如下: DragOpenDrawer(   openDuratio

使用

通过监听滚动事件实现DraGopenDrawer 组件,可以给滚动组件添加一个下拉抽屉。其使用方式如下:

DragOpenDrawer(
  openDuration: Duration(microseconds: 900),
  closeDuration: Duration(milliseconds: 300),
  onOpen: (){
    print("onOpen");
  },
 child: Column(
      children: [
        Expanded(
          child: ListView.builder(
              itemCount: 40,
              itemBuilder: (context,index){
            return ListTile(title: Text("$index"),);
          }),
        ),
      ]
    ),
  backgroundBuilder: (context){
    return Container(child: FlutterLogo(style: FlutterLogoStyle.stacked,),color: Colors.blue[200],);
  },
),

组件参数说明

  • openDuration:抽屉打开动画持续的时间
  • closeDuration: 抽屉关闭动画持续的时间
  • onOpen: 抽屉打开事件回调
  • child: DragOpenDrawer 组件监听的滚动组件
  • backgroundBuilder:抽屉打开后展示的组件

运行效果

源码

import 'package:flutter/material.dart';

enum _DragOpenDrawerMode{
  // 正在拖动
  dragging,
  // 抽同打开事件已经触发
  done,
  // 抽屉处于关闭状态
  canceled,
  // 抽屉已经打开了
  opened,
}

class DragOpenDrawer extends StatefulWidget {
  const DragOpenDrawer({
    required this.child,
    required this.backgroundBuilder,
    this.onOpen,
    this.openDuration =  const Duration(seconds: 1),
    this.closeDuration = const Duration(seconds: 1),
    Key? key}) : super(key: key);

  final Widget Function(BuildContext context) backgroundBuilder;
  final Widget  child;

  /// 抽屉打开时的回调函数
  final void Function()? onOpen;

  final Duration openDuration;
  final Duration closeDuration;

  @override
  _DragOpenDrawerState createState() => _DragOpenDrawerState();
}

class _DragOpenDrawerState extends State<DragOpenDrawer> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late double _maxHeight;
  double _dragOffset = .0;
  bool _openTriggered = false;
  _DragOpenDrawerMode _dragOpenDrawerMode = _DragOpenDrawerMode.canceled;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this);
  }

  @override
  void dispose() {
    _changeDragOpenDrawerMode(_DragOpenDrawerMode.canceled);
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {

    return LayoutBuilder(
      builder: (BuildContext context, BoxConstraints constraints) {
        _maxHeight = constraints.maxHeight;
        return  WillPopScope(
          onWillPop: () async{
            if(_dragOpenDrawerMode == _DragOpenDrawerMode.opened){
              _changeDragOpenDrawerMode(_DragOpenDrawerMode.canceled);
              return false;
            }
            return true;
          },
          child: Stack(
            alignment: Alignment.topCenter,
            children: [
              SizedBox(
                width: double.infinity,
                height: double.infinity,
                child: ScaleTransition(
                    alignment: Alignment.topCenter,
                    scale: _controller,
                    child: widget.backgroundBuilder(context)),
              ),
              AnimatedBuilder(
                animation: _controller,
                builder: (BuildContext context, Widget? child) {
                  return  Positioned(
                    top: Tween(begin: .0, end: _maxHeight).evaluate(_controller),
                    height: _maxHeight,
                    width: constraints.maxWidth,
                    child: NotificationListener(
                        onNotification: (notification){
                          if(notification is OverscrollNotification){
                            if(notification.overscroll >= 0){
                              return true;
                            }else{
                              _dragOffset -= notification.overscroll;

                              _changeDragOpenDrawerMode(_DragOpenDrawerMode.dragging);

                              if(_dragOffset >_maxHeight/4){
                                _changeDragOpenDrawerMode(_DragOpenDrawerMode.done);
                              }
                            }
                          }else if(notification is ScrollEndNotification && _dragOpenDrawerMode != _DragOpenDrawerMode.done){
                            _controller
                              ..duration = widget.closeDuration
                              ..reverse().then((value) => _dragOffset = .0);
                          }else if(notification is ScrollEndNotification && _dragOpenDrawerMode == _DragOpenDrawerMode.done){
                            _changeDragOpenDrawerMode(_DragOpenDrawerMode.opened);
                          }
                          return true;
                        },
                        child: child ?? SizedBox()),
                  );
                },
                child:Container(
                  color: Colors.white,
                  height: _maxHeight,
                  child: widget.child
                ),
              ),
            ],
          ),
        );
      },
    );
  }

  _changeDragOpenDrawerMode(_DragOpenDrawerMode newMode)async{
    _dragOpenDrawerMode = newMode;

    switch (newMode){
      case _DragOpenDrawerMode.canceled : {
        _controller.duration = widget.closeDuration;
        await _controller.reverse();
        _openTriggered = false;
        _dragOffset = .0;
        break;
      }

      case _DragOpenDrawerMode.dragging:
        _controller.duration = Duration(seconds: 0);
        await  _controller.animateTo(_dragOffset/_maxHeight);
        break;

      case _DragOpenDrawerMode.opened:
        _controller.duration = widget.openDuration;
        await _controller.forward();
        break;

      case _DragOpenDrawerMode.done:
        if(!_openTriggered){
          widget.onOpen!.call();
        }
        _openTriggered = true;
        break;
      default:
        //executeUnknown();
    }
  }
}

到此这篇关于flutter实现一个列表下拉抽屉的示例代码的文章就介绍到这了,更多相关flutter 列表下拉抽屉内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: flutter实现一个列表下拉抽屉的示例代码

本文链接: https://lsjlt.com/news/139432.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作