Flutter 底部抽屉,三阶滑动;

Flutter 底部抽屉,三阶滑动,但不跟随手指滑动、效果一般;Head布局可以触发抽屉滑动, 内部的Sliver布局单独滑动;

推荐看这篇文章,支持列表Sliver滑动;Flutter 底部列表抽屉,三阶滑动 , 支持列表Sliver布局_Choi晨的博客-CSDN博客

  

import 'package:flutter/material.dart';


class SlidingPanel3Controller {
  _SlidingPanel3ViewState? onState;

  _addState(_SlidingPanel3ViewState? onState){
    this.onState = onState;
  }

  void setPanel3State(Panel3State state){
    onState?.setPanel3state(state);
  }

  Panel3State getPanel3State(){
    return onState?._panel3state.value ?? Panel3State.CENTER;
  }

}

enum Panel3State { OPEN, CENTER, CLOSE, EXIT }

class SlidingPanel3View extends StatefulWidget {
  final double heightOpen; //展开高度
  final double heightCenter; //中间高度
  final double heightClose; //闭合高度
  final Widget headWidget; //标题布局(内含滑动操作)
  final Widget bodyWidget; //内容布局
  final Panel3State initPanel3state; //初始状态
  final Color backColor; //背景色
  final SlidingPanel3Controller? slidingPanel3Controller; //控制器

  const SlidingPanel3View(
      {Key? key,
      this.heightOpen = 600,
      this.heightCenter = 360,
      this.heightClose = 100,
      required this.headWidget,
      required this.bodyWidget,
        this.slidingPanel3Controller,
      this.initPanel3state = Panel3State.CENTER,
      this.backColor = Colors.transparent})
      : super(key: key);

  @override
  State<SlidingPanel3View> createState() => _SlidingPanel3ViewState();
}


class _SlidingPanel3ViewState extends State<SlidingPanel3View> {
  double heightClose = 100;
  double heightCenter = 360;
  double heightOpen = 600;
  final ValueNotifier<Panel3State> _panel3state = ValueNotifier(Panel3State.CENTER);
  SlidingPanel3Controller? slidingPanel3Controller;

  @override
  void initState() {
    super.initState();
    heightClose = widget.heightClose;
    heightCenter = widget.heightCenter;
    heightOpen = widget.heightOpen;
    _panel3state.value = widget.initPanel3state;
    slidingPanel3Controller = widget.slidingPanel3Controller;
    slidingPanel3Controller?._addState(this);

  }

  void setPanel3state(Panel3State s){
    _panel3state.value = s;
  }

  double panelHeight() {
    if (_panel3state.value == Panel3State.OPEN) {
      return heightOpen;
    } else if (_panel3state.value == Panel3State.CENTER) {
      return heightCenter;
    } else if (_panel3state.value == Panel3State.CLOSE) {
      return heightClose;
    } else {
      return 0;
    }
  }

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder(
      valueListenable: _panel3state,
      builder: (context, state, child) {
        return AnimatedContainer(
          color: widget.backColor,
          duration: const Duration(milliseconds: 220),
          width: double.infinity,
          height: panelHeight(),
          child: Column(
            children: [HeadView(),  Expanded(child: widget.bodyWidget)],
          ),
        );
      },
    );
  }

  double pointerMove = 0;
  bool isCan = true;

  Widget HeadView() {
    return Listener(
      onPointerDown: (e) {
        pointerMove = e.position.dy;
        isCan = true;
      },
      onPointerMove: (e) {
        if (e.position.dy - pointerMove > 20 && isCan) {
          // print("手指下滑触发 -- ");
          isCan = false;
          if (_panel3state.value == Panel3State.OPEN) {
            _panel3state.value = Panel3State.CENTER;
          } else if (_panel3state.value == Panel3State.CENTER) {
            _panel3state.value = Panel3State.CLOSE;
          }
        } else if (e.position.dy - pointerMove < -20 && isCan) {
          // print("手指上滑触发 -- ");
          isCan = false;
          if (_panel3state.value == Panel3State.CLOSE) {
            _panel3state.value = Panel3State.CENTER;
          } else if (_panel3state.value == Panel3State.CENTER) {
            _panel3state.value = Panel3State.OPEN;
          }
        }
      },
      onPointerUp: (e) {
        isCan = true;
      },
      child: widget.headWidget,
    );
  }
}

使用:

  SlidingPanel3Controller slidingPanel3Controller = SlidingPanel3Controller();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          InkWell(
            onTap: (){
              slidingPanel3Controller.setPanel3State(Panel3State.CLOSE);
            },
            child: Container(
              width: double.infinity,
              height: double.infinity,
              color: Colors.blue.withAlpha(88),
            ),
          ),
          Align(
              alignment: AlignmentDirectional.bottomCenter,
              child: SlidingPanel3View(
                heightClose: ScreenUtils.getDip(116),
                heightCenter: ScreenUtils.getDip(330),
                heightOpen: ScreenUtils.getDip(680),
                headWidget: headView(),
                bodyWidget: BodyView(),
                slidingPanel3Controller: slidingPanel3Controller,
                initPanel3state: Panel3State.CENTER,

              )),
        ],
      ),
    );
  }