如何在不释放实例的情况下更改堆栈中项目的顺序?

问题描述 投票:0回答:1

我正在尝试制作一个内置于堆栈中的主页,其中有许多动画小部件,当点击时拖动或平移滑入和滑出视图。我将添加一个视频来清楚地说明这一点。然而,我面临的一个问题是,当这些小部件进入和退出视图时,因为它们都在堆栈内,所以其中一个小部件部分显示在另一个顶部。我曾尝试设置堆栈的顺序或添加一个新的小部件列表,这些小部件之前具有更新的小部件顺序,但它在动画收报机仍处于活动状态时处理了小部件。我可以使用什么方法来解决这个问题?这个问题的一个很好的类比是在 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: 当前行为

如您所见,左侧的小部件位于底部小部件的后面。我想让它根据正在打开的那个来改变堆栈中的位置

flutter dart layout
1个回答
0
投票

您可以使用 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)),
            );
          }),
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.