Flutter底部弹出视图插件snapping_sheet_nic的使用
Flutter底部弹出视图插件snapping_sheet_nic的使用
Snapping Sheet

一个提供了高度可定制的底部弹出视图组件的包,可以吸附到不同的垂直和水平位置。
特点
- 可以适应底部弹出视图内部的滚动控件。
- 完全自定义动画和内容。
- 不限于应用底部部分。



你可以找到并运行例子,关闭此仓库并从example
文件夹运行应用。
开始使用
首先,在你的pubspec.yaml
文件中添加该包。以下是基本的使用示例:
import 'package:flutter/material.dart';
import 'package:snapping_sheet/snapping_sheet.dart';
class GettingStartedExample extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
body: SnappingSheet(
// 背景内容(可留空)
child: MyOwnPageContent(),
grabbingHeight: 75,
// 拖拽区域
grabbing: MyOwnGrabbingWidget(),
sheetBelow: SnappingSheetContent(
draggable: true,
// 弹出视图内容
child: MyOwnSheetContent(),
),
),
);
}
}
自定义吸附位置
通过修改snappingPositions
参数来改变吸附位置,参数可以接受SnappingPosition.factor
或SnappingPosition.pixels
对象。这些对象用于指定位置使用因子或像素值。你还可以指定吸附的速度和动画曲线。
SnappingSheet(
snappingPositions: [
SnappingPosition.factor(
positionFactor: 0.0,
snappingCurve: Curves.easeOutExpo,
snappingDuration: Duration(seconds: 1),
grabbingContentOffset: GrabbingContentOffset.top,
),
SnappingPosition.pixels(
positionPixels: 400,
snappingCurve: Curves.elasticOut,
snappingDuration: Duration(milliseconds: 1750),
),
SnappingPosition.factor(
positionFactor: 1.0,
snappingCurve: Curves.bounceOut,
snappingDuration: Duration(seconds: 1),
grabbingContentOffset: GrabbingContentOffset.bottom,
),
],
)
添加内容到弹出视图
你可以在吸附区域的上方或下方添加内容。如果不需要在某个区域添加内容,可以传入null。
sizeBehavior
: 控制内容大小的行为,可以是SheetSizeFill
(填充可用空间)或SheetSizeStatic
(固定高度)。draggable
: 是否允许拖动展开或关闭弹出视图。child
: 任何你需要的Widget。
SnappingSheet(
sheetAbove: SnappingSheetContent(
sizeBehavior: SheetSizeFill(),
draggable: false,
child: Container(color: Colors.blue),
),
sheetBelow: SnappingSheetContent(
sizeBehavior: SheetSizeStatic(size: 300),
draggable: true,
child: Container(color: Colors.red),
),
)
使弹出视图适应滚动控制器
为了让弹出视图知道滚动控制器的存在,需要在SnappingSheetContent
类中传递它。建议将lockOverflowDrag
设置为true,以防止视图超出最大最小吸附位置。
SnappingSheet(
lockOverflowDrag: true, // 建议设置为true
sheetBelow: SnappingSheetContent(
// 传递滚动控制器
childScrollController: _myScrollController,
draggable: true,
child: ListView(
// 在滚动控件中使用相同的控制器
controller: _myScrollController,
// 注意:如果在sheetBelow中,应设置为false;如果在sheetAbove中,应设置为true
reverse: false,
),
),
)
注意:滚动控件如ListView
或SingleChildScrollView
等需要根据其位置正确设置reverse
属性。如果在sheetBelow
中,reverse
应设为false;如果在sheetAbove
中,应设为true。
使用SnappingSheetController
可以通过SnappingSheetController
控制弹出视图。
// 创建控制器
final snappingSheetController = SnappingSheetController();
SnappingSheet(
controller: snappingSheetController,
sheetAbove: SnappingSheetContent(
draggable: false,
child: Container(color: Colors.blue),
),
sheetBelow: SnappingSheetContent(
draggable: true,
child: Container(color: Colors.red),
),
)
// 控制弹出视图
snappingSheetController.snapToPosition(
SnappingPosition.factor(positionFactor: 0.75),
);
snappingSheetController.stopCurrentSnapping();
snappingSheetController.setSnappingSheetPosition(100);
// 获取弹出视图信息
snappingSheetController.currentPosition;
snappingSheetController.currentSnappingPosition;
snappingSheetController.currentlySnapping;
snappingSheetController.isAttached;
监听变化
你可以监听移动和吸附动画完成事件:
SnappingSheet(
onSheetMoved: (sheetPosition) {
print("当前位置 ${sheetPosition.pixels}");
},
onSnapCompleted: (sheetPosition, snappingPosition) {
print("当前位置 ${sheetPosition.pixels}");
print("当前吸附位置 $snappingPosition");
},
onSnapStart: (sheetPosition, snappingPosition) {
print("当前位置 ${sheetPosition.pixels}");
print("下一个吸附位置 $snappingPosition");
},
)
水平吸附视图
还存在水平模式的吸附视图。要使用它,请参阅以下代码:
SnappingSheet.horizontal(
// 背景内容(可留空)
child: MyOwnPageContent(),
grabbingWidth: 50,
// 拖拽区域
grabbing: MyOwnGrabbingWidget(),
sheetLeft: SnappingSheetContent(
draggable: true,
// 弹出视图内容
child: MyOwnSheetContent(),
),
),
更复杂的水平吸附视图示例可以在这里找到。
完整示例
以下是一个完整的示例,展示了如何使用snapping_sheet_nic插件创建一个带有列表的底部弹出视图。
import 'package:example/pages/menu.dart';
import 'package:flutter/material.dart';
import 'package:snapping_sheet/snapping_sheet.dart';
void main() {
runApp(SnappingSheetExampleApp());
}
class SimpleSnappingSheet extends StatelessWidget {
final ScrollController listViewController = new ScrollController();
[@override](/user/override)
Widget build(BuildContext context) {
return SnappingSheet(
child: Background(),
lockOverflowDrag: true,
snappingPositions: [
SnappingPosition.factor(
positionFactor: 0.0,
snappingCurve: Curves.easeOutExpo,
snappingDuration: Duration(seconds: 1),
grabbingContentOffset: GrabbingContentOffset.top,
),
SnappingPosition.factor(
snappingCurve: Curves.elasticOut,
snappingDuration: Duration(milliseconds: 1750),
positionFactor: 0.5,
),
SnappingPosition.factor(
grabbingContentOffset: GrabbingContentOffset.bottom,
snappingCurve: Curves.easeInExpo,
snappingDuration: Duration(seconds: 1),
positionFactor: 0.9,
),
],
grabbing: GrabbingWidget(),
grabbingHeight: 75,
sheetAbove: null,
sheetBelow: SnappingSheetContent(
draggable: true,
childScrollController: listViewController,
child: Container(
color: Colors.white,
child: ListView.builder(
controller: listViewController,
itemBuilder: (context, index) {
return Container(
margin: EdgeInsets.all(15),
color: Colors.green[200],
height: 100,
child: Center(
child: Text(index.toString()),
),
);
},
),
),
),
);
}
}
/// 辅助组件
class Background extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return Container(
color: Colors.grey[200],
child: Placeholder(
color: Colors.green[200]!,
),
);
}
}
class GrabbingWidget extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
boxShadow: [
BoxShadow(blurRadius: 25, color: Colors.black.withOpacity(0.2)),
],
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
margin: EdgeInsets.only(top: 20),
width: 100,
height: 7,
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.circular(5),
),
),
Container(
color: Colors.grey[200],
height: 2,
margin: EdgeInsets.all(15).copyWith(top: 0, bottom: 0),
)
],
),
);
}
}
class SnappingSheetExampleApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Snapping Sheet Examples',
theme: ThemeData(
appBarTheme: AppBarTheme(
backgroundColor: Colors.grey[700],
elevation: 0,
foregroundColor: Colors.white,
titleTextStyle: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
iconTheme: IconThemeData(color: Colors.white),
),
primarySwatch: Colors.grey,
),
home: PageWrapper(),
);
}
}
class PageWrapper extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"Example",
style: TextStyle(color: Colors.white),
),
actions: [
IconButton(
icon: Icon(Icons.menu),
onPressed: () => {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return Menu();
}),
),
},
)
],
),
body: SimpleSnappingSheet(),
);
}
}
更多关于Flutter底部弹出视图插件snapping_sheet_nic的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter底部弹出视图插件snapping_sheet_nic的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
snapping_sheet_nic
是一个用于 Flutter 的插件,它允许你创建一个底部弹出的视图,并且可以自定义其行为和样式。这个插件特别适合用于实现类似 Google Maps 或 Apple Maps 中的底部可拖动面板。
安装
首先,你需要在 pubspec.yaml
文件中添加 snapping_sheet_nic
插件的依赖:
dependencies:
flutter:
sdk: flutter
snapping_sheet_nic: ^1.0.0 # 请使用最新版本
然后运行 flutter pub get
来安装依赖。
基本用法
以下是一个简单的例子,展示了如何使用 snapping_sheet_nic
插件创建一个底部弹出的视图:
import 'package:flutter/material.dart';
import 'package:snapping_sheet_nic/snapping_sheet_nic.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Snapping Sheet Demo'),
),
body: SnappingSheetDemo(),
),
);
}
}
class SnappingSheetDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SnappingSheet(
child: Center(
child: Text('Main Content'),
),
grabbingHeight: 75,
grabbing: Container(
color: Colors.blue,
child: Center(
child: Text('Grabbing Area'),
),
),
sheetAbove: SnappingSheetContent(
child: Container(
color: Colors.white,
child: Center(
child: Text('Sheet Above Content'),
),
),
),
sheetBelow: SnappingSheetContent(
child: Container(
color: Colors.green,
child: Center(
child: Text('Sheet Below Content'),
),
),
),
snappingPositions: [
SnappingPosition.factor(
positionFactor: 0.0,
grabbingContentOffset: GrabbingContentOffset.top,
),
SnappingPosition.factor(
positionFactor: 0.5,
grabbingContentOffset: GrabbingContentOffset.top,
),
SnappingPosition.factor(
positionFactor: 1.0,
grabbingContentOffset: GrabbingContentOffset.top,
),
],
);
}
}
参数解释
child
: 主内容区域,通常是一个Widget
,例如Center
、Column
等。grabbingHeight
: 抓取区域的高度,用户可以通过拖动这个区域来控制面板的展开和收起。grabbing
: 抓取区域的Widget
,通常是一个容器或按钮。sheetAbove
: 面板上面的内容,通常是一个SnappingSheetContent
。sheetBelow
: 面板下面的内容,通常是一个SnappingSheetContent
。snappingPositions
: 面板的吸附位置,你可以通过SnappingPosition.factor
来定义不同的吸附位置。
自定义
你可以通过调整 snappingPositions
来定义面板的吸附位置。例如,你可以设置面板在 0%、50% 和 100% 的位置吸附。
snappingPositions: [
SnappingPosition.factor(
positionFactor: 0.0,
grabbingContentOffset: GrabbingContentOffset.top,
),
SnappingPosition.factor(
positionFactor: 0.5,
grabbingContentOffset: GrabbingContentOffset.top,
),
SnappingPosition.factor(
positionFactor: 1.0,
grabbingContentOffset: GrabbingContentOffset.top,
),
],