我想创建一个 UI 组件,它将堆叠在屏幕其余部分的顶部,因此我可以在用户视图中转换它,但我也想让它可滚动。
我能想到的唯一方法是使用 Stack 和 Positioned 小部件,但不幸的是 Stack 中的组件不能滚动。
我正在考虑 GestureDetector 并手动将列表向右滚动,这意味着将其中的大部分放置在屏幕的渲染区域之外。
你能想出一个更优雅的解决方案吗?
谢谢,托马斯
我想创建一个 UI 组件,它将堆叠在屏幕其余部分的顶部,因此我可以在用户视图中转换它,但我也想让它可滚动。
我能想到的唯一方法是使用 Stack 和 Positioned 小部件,但不幸的是 Stack 中的组件不能滚动。
我正在考虑 GestureDetector 并手动将列表向右滚动,这意味着将其中的大部分放置在屏幕的渲染区域之外。
你能想出一个更优雅的解决方案吗?
谢谢,托马斯
import 'package:flutter/material.dart';
class SlidingDrawer extends StatelessWidget {
final Widget drawer;
final OpenableController openableController;
SlidingDrawer({@required this.drawer, @required this.openableController});
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
GestureDetector(
onTap: openableController.isOpen() ? openableController.close : null,
),
FractionalTranslation(
translation: Offset(1.0 - openableController.percentOpen, 0.0),
child: Align(
child: drawer,
alignment: Alignment.centerRight,
),
),
],
);
}
}
class OpenableController extends ChangeNotifier {
OpenedState _state;
AnimationController openingController;
OpenableController(
{@required TickerProvider vsync, @required Duration openDuration})
: openingController =
AnimationController(vsync: vsync, duration: openDuration) {
openingController
..addListener(notifyListeners)
..addStatusListener((status) {
switch (status) {
case AnimationStatus.forward:
_state = OpenedState.opening;
break;
case AnimationStatus.reverse:
_state = OpenedState.closing;
break;
case AnimationStatus.completed:
_state = OpenedState.open;
break;
case AnimationStatus.dismissed:
_state = OpenedState.closed;
break;
}
notifyListeners();
});
}
get state => _state;
get percentOpen => openingController.value;
bool isOpen() {
return _state == OpenedState.open;
}
bool isOpening() {
return _state == OpenedState.opening;
}
bool isClosed() {
return _state == OpenedState.closed;
}
bool isClosing() {
return _state == OpenedState.closing;
}
void open() {
openingController.forward();
}
void close() {
openingController.reverse();
}
void toggle() {
if (isClosed()) {
open();
} else if (isOpen()) {
close();
}
}
}
enum OpenedState { open, closed, opening, closing }
上面是一个通用组件,只需要从右边提供你想要抽屉的内容,然后把它放在一个堆栈中,
在你的主要
OpenableController openableController;
@override
void initState() {
super.initState();
openableController = OpenableController(
vsync: this, openDuration: Duration(milliseconds: 250))
..addListener(() => setState(() {}));
}
并打开
openableController.open