Flutter - 如何创建带有持久按钮的底部侧边栏以打开和关闭它
Flutter - How to create a Bottom sidebar with a persistent Button to open and close it
我想创建底部侧边栏,带有一个用于打开和关闭它的固定按钮,现在使用 showModalBottomSheet
,但我不知道如何将按钮附加到 ModalBottomSheet
这就是我的应用程序现在所做的:
这是我想要实现的:
我希望我明白你的意思,尝试在 Stack
中使用这个 class 并根据你的需要调整它:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';
class CycleSideBar extends StatefulWidget {
const CycleSideBar({Key? key}) : super(key: key);
@override
_CycleSideBarState createState() => _CycleSideBarState();
}
class _CycleSideBarState extends State<CycleSideBar>
with SingleTickerProviderStateMixin<CycleSideBar> {
AnimationController? _animationController;
StreamController<bool>? isSideBarOpenedStreamController;
Stream<bool>? isSideBarOpenedStream;
StreamSink<bool>? isSideBarOpenedSink;
final _animationDuration = const Duration(milliseconds: 400);
@override
void initState() {
super.initState();
_animationController =
AnimationController(vsync: this, duration: _animationDuration);
isSideBarOpenedStreamController = PublishSubject<bool>();
isSideBarOpenedStream = isSideBarOpenedStreamController!.stream;
isSideBarOpenedSink = isSideBarOpenedStreamController!.sink;
}
@override
void dispose() {
_animationController!.dispose();
isSideBarOpenedStreamController!.close();
isSideBarOpenedSink!.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
var heightOfScreen = MediaQuery.of(context).size.height;
List<Widget> children = [];
return StreamBuilder<bool>(
initialData: false,
stream: isSideBarOpenedStream,
builder: (context, isCycleSideBarOpenedAsync) {
return AnimatedPositioned(
duration: _animationDuration,
top: isCycleSideBarOpenedAsync.data!
? heightOfScreen - 300
: heightOfScreen - 113,
left: 0,
right: 0,
bottom: 0,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
TextButton(
onPressed: () => onIconPressed(),
child: Text('Test'),
),
SizedBox(
height: 10,
),
Expanded(
child: Container(
color: Colors.white.withOpacity(0.4),
child: Wrap(
alignment: WrapAlignment.center,
spacing: 10,
runSpacing: 10,
children: _builItemsOfBottomSheet(children),
),
),
),
],
),
);
},
);
}
void onIconPressed() {
final animationStatus = _animationController!.status;
final isAnimationCompleted = animationStatus == AnimationStatus.completed;
if (isAnimationCompleted) {
isSideBarOpenedSink!.add(false);
_animationController!.reverse();
} else {
isSideBarOpenedSink!.add(true);
_animationController!.forward();
}
}
List<Widget> _builItemsOfBottomSheet(List<Widget> children) {
children.clear();
for (int i = 0; i < 10; i++) {
children.add(Container(color: Colors.green, child: Text('Text_$i')));
}
return children;
}
}
希望对您有所帮助
我想创建底部侧边栏,带有一个用于打开和关闭它的固定按钮,现在使用 showModalBottomSheet
,但我不知道如何将按钮附加到 ModalBottomSheet
这就是我的应用程序现在所做的:
这是我想要实现的:
我希望我明白你的意思,尝试在 Stack
中使用这个 class 并根据你的需要调整它:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';
class CycleSideBar extends StatefulWidget {
const CycleSideBar({Key? key}) : super(key: key);
@override
_CycleSideBarState createState() => _CycleSideBarState();
}
class _CycleSideBarState extends State<CycleSideBar>
with SingleTickerProviderStateMixin<CycleSideBar> {
AnimationController? _animationController;
StreamController<bool>? isSideBarOpenedStreamController;
Stream<bool>? isSideBarOpenedStream;
StreamSink<bool>? isSideBarOpenedSink;
final _animationDuration = const Duration(milliseconds: 400);
@override
void initState() {
super.initState();
_animationController =
AnimationController(vsync: this, duration: _animationDuration);
isSideBarOpenedStreamController = PublishSubject<bool>();
isSideBarOpenedStream = isSideBarOpenedStreamController!.stream;
isSideBarOpenedSink = isSideBarOpenedStreamController!.sink;
}
@override
void dispose() {
_animationController!.dispose();
isSideBarOpenedStreamController!.close();
isSideBarOpenedSink!.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
var heightOfScreen = MediaQuery.of(context).size.height;
List<Widget> children = [];
return StreamBuilder<bool>(
initialData: false,
stream: isSideBarOpenedStream,
builder: (context, isCycleSideBarOpenedAsync) {
return AnimatedPositioned(
duration: _animationDuration,
top: isCycleSideBarOpenedAsync.data!
? heightOfScreen - 300
: heightOfScreen - 113,
left: 0,
right: 0,
bottom: 0,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
TextButton(
onPressed: () => onIconPressed(),
child: Text('Test'),
),
SizedBox(
height: 10,
),
Expanded(
child: Container(
color: Colors.white.withOpacity(0.4),
child: Wrap(
alignment: WrapAlignment.center,
spacing: 10,
runSpacing: 10,
children: _builItemsOfBottomSheet(children),
),
),
),
],
),
);
},
);
}
void onIconPressed() {
final animationStatus = _animationController!.status;
final isAnimationCompleted = animationStatus == AnimationStatus.completed;
if (isAnimationCompleted) {
isSideBarOpenedSink!.add(false);
_animationController!.reverse();
} else {
isSideBarOpenedSink!.add(true);
_animationController!.forward();
}
}
List<Widget> _builItemsOfBottomSheet(List<Widget> children) {
children.clear();
for (int i = 0; i < 10; i++) {
children.add(Container(color: Colors.green, child: Text('Text_$i')));
}
return children;
}
}
希望对您有所帮助