我希望在应用程序屏幕主体的左侧放置一个迷你按钮,用于在 Flutter 中打开迷你抽屉。为了能够弄清楚,我准备了以下图片:
如图所示,当用户点击迷你按钮时,会出现一个迷你抽屉式面板,当用户再次单击同一按钮时,会关闭该面板。
谢谢你
您可以创建自己的小部件,如下例所示。
import 'dart:math';
import 'package:flutter/material.dart';
class MiniDrawer extends StatefulWidget {
final Widget child;
final Widget drawerContent;
final Duration animationDuration;
final Size drawerSize;
final Size drawerButtonSize;
final Color background;
final Color iconColor;
const MiniDrawer({
super.key,
required this.child,
required this.drawerContent,
this.iconColor = Colors.white,
this.background = const Color.fromRGBO(255, 120, 0, 1),
this.drawerSize = const Size(250, 300),
this.drawerButtonSize = const Size(50, 90),
this.animationDuration = const Duration(milliseconds: 200),
});
@override
State<MiniDrawer> createState() => _MiniDrawerState();
}
class _MiniDrawerState extends State<MiniDrawer> {
bool _isOpen = false;
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
return Stack(
clipBehavior: Clip.none,
children: [
widget.child,
_buildDrawer(constraints),
],
);
});
}
Widget _buildDrawer(BoxConstraints constraints) {
return AnimatedPositioned(
duration: widget.animationDuration,
top: constraints.maxHeight / 2 - widget.drawerSize.height / 2,
left: _isOpen ? 0 : min(-widget.drawerSize.width, constraints.maxWidth),
child: SizedBox(
height: widget.drawerSize.height,
width: widget.drawerSize.width + widget.drawerButtonSize.width,
child: Stack(
alignment: Alignment.centerRight,
clipBehavior: Clip.none,
children: [
_buildDrawerBtn(),
Row(
children: [
Expanded(
child: SingleChildScrollView(
child: Container(
constraints: BoxConstraints(minHeight: widget.drawerButtonSize.height),
color: widget.background,
child: widget.drawerContent,
),
),
),
SizedBox(width: widget.drawerButtonSize.width),
],
),
],
),
),
);
}
Widget _buildDrawerBtn() {
Radius radius = Radius.circular(widget.drawerButtonSize.height / 2);
return Positioned(
right: 10,
child: GestureDetector(
onTap: () {
setState(() {
_isOpen = !_isOpen;
});
},
child: Container(
decoration: BoxDecoration(
color: widget.background,
borderRadius: BorderRadius.only(
topRight: radius,
bottomRight: radius,
),
),
width: widget.drawerButtonSize.width,
height: widget.drawerButtonSize.height,
child: AnimatedRotation(
duration: widget.animationDuration,
turns: _isOpen ? 0.5 : 0,
child: Icon(
Icons.chevron_right,
size: 32,
color: widget.iconColor,
),
),
),
),
);
}
}
然后您可以像这样在代码中使用该小部件。
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('app bar')),
body: MiniDrawer(
drawerContent: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: List.generate(
10,
(index) => ListTile(
title: Text('Item $index'),
),
),
),
),
child: const Column(
children: [
Text('Page content'),
],
),
),
);
}