Flutter可滚动面板插件scrollable_panel的使用
Flutter可滚动面板插件scrollable_panel的使用
scrollable_panel
是一个用于Flutter的插件,它允许用户通过拖动来展开和滚动内容,类似于Google地图应用中的“附近地点”面板。本文将介绍如何使用这个插件,并提供一个完整的示例demo。
插件特性
- builder: 用于定义内部面板视图的构建器。
- controller: 控制面板状态(如打开、关闭等)。
- defaultPanelState: 设置默认面板状态。
- defaultPanelSize: 设置默认面板高度因子。
- minPanelSize: 设置最小面板高度因子。
- maxPanelSize: 设置最大面板高度因子。
- onOpen, onClose, onExpand: 面板状态变化时的回调函数。
PanelController 动作
open()
: 打开面板。expand()
: 展开面板。close()
: 关闭面板。animateTo(double value)
: 动画到指定高度。
使用示例
以下是一个完整的示例代码,展示如何在Flutter应用中使用scrollable_panel
插件。
import 'package:flutter/material.dart';
import 'package:scrollable_panel/scrollable_panel.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({
Key? key,
required this.title,
}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
PanelController _panelController = PanelController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(kToolbarHeight),
child: _AnimatedAppBar(panelController: _panelController),
),
body: Stack(
children: [
Positioned.fill(
child: _FirstView(controller: _panelController),
),
ScrollablePanel(
defaultPanelState: PanelState.close,
controller: _panelController,
onOpen: () => print('onOpen'),
onClose: () => print('onClose'),
onExpand: () => print('onExpand'),
builder: (context, controller) {
return SingleChildScrollView(
controller: controller,
child: _SecondView(),
);
},
),
],
),
);
}
}
class _AnimatedAppBar extends StatefulWidget {
const _AnimatedAppBar({
Key? key,
required this.panelController,
}) : super(key: key);
final PanelController panelController;
@override
__AnimatedAppBarState createState() => __AnimatedAppBarState();
}
class __AnimatedAppBarState extends State<_AnimatedAppBar> with SingleTickerProviderStateMixin {
late final Animation _animation;
late final AnimationController _animationController;
@override
void initState() {
super.initState();
_animationController = AnimationController(vsync: this, duration: const Duration(milliseconds: 300));
widget.panelController.animation?.addListener(() {
if (widget.panelController.animation!.value >= 0.8) {
_animationController.value = (0.2 - (1.0 - widget.panelController.animation!.value)) * 5;
} else {
_animationController.value = 0;
}
});
_animation = ColorTween(begin: Colors.white, end: Colors.red).animate(_animationController);
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animationController,
builder: (context, child) {
return Material(
elevation: 4.0,
color: _animation.value,
child: SafeArea(
bottom: false,
top: true,
child: Container(
height: kToolbarHeight,
child: const Center(child: Text('scrollable panel')),
),
),
);
},
);
}
}
class _FirstView extends StatelessWidget {
const _FirstView({
Key? key,
required this.controller,
}) : super(key: key);
final PanelController controller;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(onPressed: () => controller.open(), child: const Text('open panel')),
ElevatedButton(onPressed: () => controller.close(), child: const Text('close panel')),
ElevatedButton(onPressed: () => controller.expand(), child: const Text('expand panel')),
],
);
}
}
class _SecondView extends StatelessWidget {
@override
Widget build(BuildContext context) {
const double circularBoxHeight = 16.0;
final Size size = MediaQuery.of(context).size;
return LayoutBuilder(
builder: (context, constraints) {
return ConstrainedBox(
constraints: BoxConstraints(minHeight: size.height + kToolbarHeight + 44.0),
child: Container(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: const BorderRadius.only(topLeft: Radius.circular(circularBoxHeight), topRight: Radius.circular(circularBoxHeight)),
border: Border.all(color: Colors.blue),
),
child: const Center(child: Text("second")),
),
);
},
);
}
}
总结
通过上述示例,您可以轻松地在Flutter应用中集成scrollable_panel
插件,实现类似Google地图应用中的可滚动面板效果。希望这个示例能帮助您快速上手并应用于实际项目中。
更多关于Flutter可滚动面板插件scrollable_panel的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter可滚动面板插件scrollable_panel的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter中使用scrollable_panel
插件的示例代码。scrollable_panel
插件允许你创建一个可滚动的面板,这在创建复杂UI时非常有用。首先,确保你已经在pubspec.yaml
文件中添加了scrollable_panel
依赖:
dependencies:
flutter:
sdk: flutter
scrollable_panel: ^x.y.z # 请替换为最新版本号
然后,运行flutter pub get
来安装依赖。
以下是一个简单的示例,展示如何使用ScrollablePanel
来创建一个可滚动的面板:
import 'package:flutter/material.dart';
import 'package:scrollable_panel/scrollable_panel.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Scrollable Panel Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('Scrollable Panel Demo'),
),
body: Center(
child: ScrollablePanelDemo(),
),
),
);
}
}
class ScrollablePanelDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'This is a demo of ScrollablePanel in Flutter.',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 20),
ScrollablePanel(
// 设置面板的最小高度和最大高度
minHeight: 100,
maxHeight: 300,
// 设置初始高度(可选)
initialHeight: 200,
// 设置面板内容
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: List.generate(
50,
(index) => Padding(
padding: const EdgeInsets.only(left: 16.0, bottom: 8.0),
child: Text(
'Item $index',
style: TextStyle(fontSize: 18),
),
),
),
),
// 设置面板头部(可选)
header: Container(
color: Colors.grey[300],
padding: EdgeInsets.all(8.0),
child: Text(
'Panel Header',
style: TextStyle(fontSize: 18, color: Colors.black),
),
),
// 设置面板底部控制按钮(可选)
footer: Container(
color: Colors.grey[300],
padding: EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
TextButton(
onPressed: () {
// 收缩面板
ScrollablePanel.of(context)?.collapse();
},
child: Text('Collapse'),
),
TextButton(
onPressed: () {
// 展开面板到最大高度
ScrollablePanel.of(context)?.expand();
},
child: Text('Expand'),
),
],
),
),
),
],
),
);
}
}
在这个示例中:
ScrollablePanel
被用来创建一个可滚动且可调整高度的面板。minHeight
和maxHeight
属性定义了面板的最小和最大高度。initialHeight
属性定义了面板的初始高度。header
和footer
属性允许你添加面板的头部和底部控件,比如按钮。child
属性定义了面板的内容。
运行这个示例应用,你将看到一个带有可调整高度面板的页面,面板内容超出了初始高度时可以滚动,同时有按钮可以控制面板的收缩和展开。