我正在尝试制作一个内置于堆栈中的主页,其中有许多动画小部件,当点击时拖动或平移滑入和滑出视图。我将添加一个视频来清楚地说明这一点。然而,我面临的一个问题是,当这些小部件进入和退出视图时,因为它们都在堆栈内,所以其中一个小部件部分显示在另一个顶部。我曾尝试设置堆栈的顺序或添加一个新的小部件列表,这些小部件之前具有更新的小部件顺序,但它在动画收报机仍处于活动状态时处理了小部件。我可以使用什么方法来解决这个问题?这个问题的一个很好的类比是在 CSS 中,你可以设置 z 索引,但我在 flutter 中找不到类似的东西。
这是我的构建函数:
@override
Widget build(BuildContext context) {
bottomTaskBar ??= SizedBox(
width: 100.safeAreaW(context),
height: 100.safeAreaH(context),
child: SliderWithTextFieldWidget(),
);
leftMenuSliderWidget ??= SlideWidget();
topDragDownWidget ??= SlideWidget();
stackChildren[0] = topDragDownWidget!;
stackChildren[1] = Positioned(
top: 0,
child: SizedBox(
width: 100.safeAreaW(context),
height: 100.safeAreaH(context),
child: Center(
child: Padding(
padding: const EdgeInsets.only(bottom: 70.0),
child: ClockWidget(
width: 60.sw(context),
workDuration: const Duration(minutes: 25),
breakDuration:const Duration(minutes: 5),
),
),
),
),
);
stackChildren[2] = Positioned(
right: 0,
top: 0,
child: Container(
width: 200,
padding: const EdgeInsets.only(top: 30, right: 10),
child: SlideWidget(
threshold: 40,
position: Position.right,
width: 60,
openLength: 190 ,
closedLength: 60,
content: Container(
color: Colors.deepPurple,
),
),
),
);
stackChildren[3] = leftMenuSliderWidget!;
stackChildren[4] = bottomTaskBar!;
return Scaffold(
backgroundColor: Theme.of(context).colorScheme.primary,
body: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Padding(
padding: EdgeInsets.only(top: 100.devicePaddingTop(context),bottom: 100.devicePaddingBottom(context)),
child: Stack(
children: stackChildren
),
),
),
);
}
这是当前行为的 gif: 当前行为
如您所见,左侧的小部件位于底部小部件的后面。我想让它根据正在打开的那个来改变堆栈中的位置
您可以使用 GlobalKey(在状态中创建它们而不是构建)来保留构建之间的状态。并对孩子们进行排序以确定他们的顺序。
import 'package:flutter/material.dart';
class MyWidget extends StatefulWidget {
const MyWidget({super.key});
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
final Map<Color, int> rank = {
Colors.red: 1,
Colors.blue: 2,
Colors.green: 3,
Colors.yellow: 4,
};
final Map<Color, GlobalKey> keys = {
Colors.red: GlobalKey(),
Colors.blue: GlobalKey(),
Colors.green: GlobalKey(),
Colors.yellow: GlobalKey(),
};
final Map<Color, EdgeInsets> padding = {
Colors.red: EdgeInsets.only(top: 100, left: 100),
Colors.blue: EdgeInsets.only(top: 100, right: 100),
Colors.green: EdgeInsets.only(bottom: 100, left: 100),
Colors.yellow: EdgeInsets.only(bottom: 100, right: 100),
};
int nextRank = 5;
@override
Widget build(BuildContext context) {
final rankedColors = rank.keys.toList()..sort((a, b) => rank[a]!.compareTo(rank[b]!));
return Stack(
children: [
for (final color in rankedColors)
Padding(
padding: padding[color]!,
child: GestureDetector(
onTap: () {
setState(() {
rank[color] = nextRank;
nextRank += 1;
});
},
child: MyTimer(
key: keys[color],
color: color,
),
),
),
],
);
}
}
class MyTimer extends StatefulWidget {
final Color color;
const MyTimer({super.key, required this.color});
@override
State<MyTimer> createState() => _MyTimerState();
}
class _MyTimerState extends State<MyTimer> with SingleTickerProviderStateMixin {
late final AnimationController controller = AnimationController(
upperBound: 1000,
duration: const Duration(minutes: 10),
vsync: this,
)..forward();
@override
Widget build(BuildContext context) {
return Container(
color: widget.color,
width: 200,
height: 200,
child: AnimatedBuilder(
animation: controller,
builder: (context, snapshot) {
return Center(
child: Text(controller.value.toStringAsFixed(3)),
);
}),
);
}
}