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,
)),
],
),
);
}