赞
踩
Flutter 底部是列表的抽屉,三阶滑动,支持列表Sliver布局,Head布局可以触发抽屉滑动, 内部的Sliver布局也可以触发抽屉滑动;
抽屉在最大高度时,Sliver布局可以滑动,其他高度会触发抽屉滑动;
、、
- import 'package:flutter/material.dart';
-
-
- class SliverPanel3Controller {
- _SliverPanel3ViewState? onState;
-
- _addState(_SliverPanel3ViewState? 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 SliverPanel3View extends StatefulWidget {
- final double heightOpen; //展开高度
- final double heightCenter; //中间高度
- final double heightClose; //闭合高度
- final Widget headWidget; //标题布局
- final Widget Function(ScrollController sc , ScrollPhysics? physics)? bodyWidget; //内容布局
- final Panel3State initPanel3state; //初始状态
- final Color backColor; //背景色
- final SliverPanel3Controller? sliverPanel3Controller; //控制器
-
- const SliverPanel3View(
- {Key? key,
- this.heightOpen = 600,
- this.heightCenter = 360,
- this.heightClose = 100,
- required this.headWidget,
- required this.bodyWidget,
- this.sliverPanel3Controller,
- this.initPanel3state = Panel3State.CENTER,
- this.backColor = Colors.transparent})
- : super(key: key);
-
- @override
- State<SliverPanel3View> createState() => _SliverPanel3ViewState();
- }
-
-
- class _SliverPanel3ViewState extends State<SliverPanel3View> {
- double heightClose = 100;
- double heightCenter = 360;
- double heightOpen = 600;
- final ValueNotifier<Panel3State> _panel3state = ValueNotifier(Panel3State.CENTER);
- SliverPanel3Controller? sliverPanel3Controller;
- ScrollController _sc = ScrollController();
- ScrollPhysics? _physics;
-
- @override
- void initState() {
- super.initState();
- heightClose = widget.heightClose;
- heightCenter = widget.heightCenter;
- heightOpen = widget.heightOpen;
- _panel3state.value = widget.initPanel3state;
- sliverPanel3Controller = widget.sliverPanel3Controller;
- sliverPanel3Controller?._addState(this);
-
- }
-
- void setPanel3state(Panel3State s){
- _panel3state.value = s;
- }
-
- double panelHeight() {
-
- if(_panel3state.value == Panel3State.OPEN){
- _physics = const AlwaysScrollableScrollPhysics();
- }else{
- _physics = const NeverScrollableScrollPhysics();
- }
-
- 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: BodyView())],
- ),
- );
- },
- );
- }
-
- double pointerMove = 0;
- bool isCan = true;
- double scOffset = 0;
-
- Widget HeadView() {
- return Listener(
- onPointerDown: (e) {
- pointerMove = e.position.dy;
- isCan = true;
- },
- onPointerMove: (e) {
- if (e.position.dy - pointerMove > 36 && 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 < -36 && 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,
- );
- }
-
-
- Widget BodyView() {
- return Listener(
- onPointerDown: (e) {
- pointerMove = e.position.dy;
- isCan = true;
- },
- onPointerMove: (e) {
- scOffset = _sc.hasClients ? _sc.offset : 0; //滑动控制器是否绑定
-
- if (e.position.dy - pointerMove > 36 && isCan) {
- // print("手指下滑触发 -- ");
- isCan = false;
- if (_panel3state.value == Panel3State.OPEN && scOffset <= 0) {
- _panel3state.value = Panel3State.CENTER;
- } else if (_panel3state.value == Panel3State.CENTER) {
- _panel3state.value = Panel3State.CLOSE;
- }
- } else if (e.position.dy - pointerMove < -36 && 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: Container(child: widget.bodyWidget!(_sc , _physics),),
- );
- }
- }
使用:
- import 'package:flutter/material.dart';
-
-
- openTestSlidingPanel3Page(BuildContext context) {
- Navigator.push(context, CupertinoPageRoute(builder: (BuildContext context) {
- return TestSlidingPanel3Page();
- }));
- }
-
- class TestSlidingPanel3Page extends StatefulWidget {
- const TestSlidingPanel3Page({Key? key}) : super(key: key);
-
- @override
- State<TestSlidingPanel3Page> createState() => _TestSlidingPanel3PageState();
- }
-
- class _TestSlidingPanel3PageState extends State<TestSlidingPanel3Page> {
-
- SliverPanel3Controller slidingPanel3Controller = SliverPanel3Controller();
-
- @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: SliverPanel3View(
- heightClose: ScreenUtils.getDip(108),
- heightCenter: ScreenUtils.getDip(330),
- heightOpen: ScreenUtils.getDip(680),
- headWidget: headView(),
- bodyWidget: (ScrollController sc , ScrollPhysics? physics){
- return BodyView(sc , physics);
- },
- sliverPanel3Controller: slidingPanel3Controller,
- initPanel3state: Panel3State.CENTER,
-
- )),
- ],
- ),
- );
- }
-
- Widget headView() {
- return Container(
- height: ScreenUtils.getDip(108),
- width: ScreenUtils.getScreenWidth(),
- padding: ScreenUtils.edge(20, 10, 20, 0),
- decoration: const BoxDecoration(
- color: Colors.white,
- borderRadius: BorderRadius.only(
- topLeft: Radius.circular(8),
- topRight: Radius.circular(8),
- )),
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- cuttingHorizontalSliver(),
- SizedBox(
- height: ScreenUtils.getDip(12),
- ),
- InkWell(
- onTap: (){
- slidingPanel3Controller.setPanel3State(Panel3State.EXIT);
- LocationPluginUtils.get().then((value) {
- SGMLogger.info(value);
- });
- },
- child: Container(
- margin: ScreenUtils.getMargin20(value: 4),
- width: double.infinity,
- height: ScreenUtils.getDip(40),
- alignment: AlignmentDirectional.center,
- decoration: BoxDecoration(
- color: color_f6f6f6,
- borderRadius: BorderRadius.circular(ScreenUtils.getDip(20)),
- ),
- child: Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- Icon(Icons.search , color: Colors.grey.withAlpha(80),size: 20,),
- const SizedBox(
- width: 5,
- ),
- Text(
- 'Search',
- style: TextStyle(
- color: color_00131D.withOpacity(.3),
- fontSize: ScreenUtils.getSp(14),
- fontWeight: FontWeight.w400),
- ),
- ],
- ),
- ),
- ),
- Container(
- height: ScreenUtils.getDip(40),
- child: Row(
- children: [
- Icon(Icons.ac_unit , color: Colors.redAccent ,size: 20,),
- const SizedBox(
- width: 8,
- ),
- Expanded(
- child: Text(
- '惊喜来袭!!! 森林公园免门票 快冲...',
- maxLines: 1,
- overflow: TextOverflow.ellipsis,
- style: TextStyle(
- color: Colors.redAccent,
- height: 1.2,
- fontSize: ScreenUtils.getSp(14),
- fontWeight: FontWeight.w400),
- ),
- ),
- ],
- ),
- ),
- ],
- ),
- );
- }
-
- Widget BodyView(ScrollController sc , ScrollPhysics? physics) {
-
- // return Container(height: 999,width: 380, color: Colors.yellowAccent,);
-
- Widget _itemView(int i) {
- return Container(
- color: color_fff,
- padding: ScreenUtils.edge(20, 21, 20, 0),
- height: ScreenUtils.getDip(94),
- child: Row(
- children: [
- Icon(Icons.add_a_photo_rounded , color: Colors.orange, size: 66,),
- const SizedBox(
- width: 18,
- ),
- Expanded(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- '森林公园游乐场',
- maxLines: 1,
- overflow: TextOverflow.ellipsis,
- style: TextStyle(
- color: color_00131D,
- fontSize: ScreenUtils.getSp(16),
- fontWeight: FontWeight.w500),
- ),
- const SizedBox(
- height: 8,
- ),
- Text(
- '景点热度声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/628182推荐阅读
相关标签
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。