我想创建一个UI组件,该组件将堆叠在屏幕其余部分的顶部,因此我可以在用户视图中转换它,但我也想使其可滚动。
Screen without the scrollable component
Scrollable component on top of the screen
我唯一想到的方法是使用Stack and Positioned小部件,但是不幸的是Stack中的组件无法滚动。
我正在考虑GestureDetector,并手动将列表向右滚动,这意味着将其中的很大一部分放在屏幕渲染区域之外。
您能想到一个更优雅的解决方案吗?
谢谢, 托马斯
答案 0 :(得分:0)
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