【问题标题】:Flutter - changing a Stack OrderFlutter - 更改堆栈顺序
【发布时间】:2018-11-14 20:50:08
【问题描述】:

我有一个堆栈,在某个条件下(例如用户单击),我希望将其中一个低阶小部件推到堆栈顶部。使用下面的代码作为一个简单的示例 - 我需要在 setState() 方法中重新排序以使第一个(底部)小部件成为最后一个(顶部)小部件的代码?

new Stack(
        children: <Widget>[
          new Icon(Icons.monetization_on, key: GlobalKey(), size: 60.0, color: const 
Color.fromRGBO(200, 100, 180, 1.0)),
          new Positioned(
            left: 20.0,
            child: new Icon(Icons.monetization_on, key: GlobalKey(), size: 60.0, color: const 
Color.fromRGBO(000, 10, 130, 1.0)),
          ),
          new Positioned(
            left:40.0,
            child: new Icon(Icons.monetization_on, key: GlobalKey(), size: 60.0, color: const Color.fromRGBO(218, 165, 32, 1.0)),
          )

        ],
      );

我已经编辑了建议的解决方案,堆栈没有改变顺序。这是完整的示例代码(按下按钮时打印语句按预期打印到控制台):

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

AnimationController timerController;

void main() => runApp(MaterialApp(
  home: MyApp(),
));

class MyApp extends StatefulWidget {
 @override
   MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
  AnimationController timerController;

  @override
  Widget build(BuildContext context) {
List<Widget> stackChildren = <Widget>[
  new Icon(Icons.monetization_on,
      key: GlobalKey(),
      size: 60.0,
      color: const Color.fromRGBO(50, 50, 50, 1.0)),
  new Positioned(
    left: 20.0,
    child: new Icon(Icons.monetization_on,
        key: GlobalKey(),
        size: 60.0,
        color: const Color.fromRGBO(50, 100, 150, 1.0)),
  ),
];

void swapStackChildren() {
     setState(() {
       print("swapStackChildren");
    stackChildren = [
      new Positioned(
          left: 40.0,
          child: new Icon(Icons.monetization_on,
              key: GlobalKey(),
              size: 60.0,
              color: const Color.fromRGBO(150, 00, 200, 1.0))),
      new Icon(Icons.monetization_on,
          key: GlobalKey(),
          size: 100.0,
          color: const Color.fromRGBO(200, 200, 100, 1.0)),
    ];
  });
}

return Scaffold(
  body: Padding(
    padding: EdgeInsets.all(8.0),
    child: Column(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: <Widget>[
        Stack(children: stackChildren),
        new RaisedButton(
          child: const Text('Swop'),
          color: Theme.of(context).accentColor,
          elevation: 4.0,
          splashColor: Colors.blueGrey,
          onPressed: () {
            swapStackChildren();
          },
        ),
      ],
    ),
  ),
);
}

}

【问题讨论】:

  • 我再次更新了我的解决方案。您需要将stackChildren 设为小部件本身的字段,而不是构建函数内的变量。

标签: stack flutter


【解决方案1】:

在您的小部件中创建一个变量来跟踪子项:

List<Widget> stackChildren = <Widget>[
          new Icon(Icons.monetization_on, key: GlobalKey(), size: 60.0, color: const 
Color.fromRGBO(200, 100, 180, 1.0)),
          new Positioned(
            left: 20.0,
            child: new Icon(Icons.monetization_on, key: GlobalKey(), size: 60.0, color: const 
Color.fromRGBO(000, 10, 130, 1.0)),
          ),
          new Positioned(
            left:40.0,
            child: new Icon(Icons.monetization_on, key: GlobalKey(), size: 60.0, color: const Color.fromRGBO(218, 165, 32, 1.0)),
          )

        ];

然后在任何你必须触发顺序切换的函数中,你都可以调用以下函数:

void swapStackChildren() {
    final temp = stackChildren[0];
    setState(() {
          stackChildren[0] = stackChildren[2];
          stackChildren[2] = temp;
        });
  }

编辑:根据 cmets 的建议,最好只为 stackChildren 分配一个新值,而不是修改它。所以你应该这样做:

void swapStackChildren() {
  setState(() {
    stackChildren = [
      new Positioned(
          left: 40.0,
          child: new Icon(Icons.monetization_on,
              key: GlobalKey(),
              size: 60.0,
              color: const Color.fromRGBO(218, 165, 32, 1.0))),
      new Icon(Icons.monetization_on,
          key: GlobalKey(),
          size: 60.0,
          color: const Color.fromRGBO(200, 100, 180, 1.0)),
      new Positioned(
        left: 20.0,
        child: new Icon(Icons.monetization_on,
            key: GlobalKey(),
            size: 60.0,
            color: const Color.fromRGBO(000, 10, 130, 1.0)),
      ),
    ];
  });
}

编辑:

Here is with the full sample code:
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

AnimationController timerController;

void main() => runApp(MaterialApp(
      home: MyApp(),
    ));

class MyApp extends StatefulWidget {
  @override
  MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
  AnimationController timerController;
  List<Widget> stackChildren = <Widget>[
      new Icon(Icons.monetization_on,
          key: GlobalKey(),
          size: 60.0,
          color: const Color.fromRGBO(50, 50, 50, 1.0)),
      new Positioned(
        left: 20.0,
        child: new Icon(Icons.monetization_on,
            key: GlobalKey(),
            size: 60.0,
            color: const Color.fromRGBO(50, 100, 150, 1.0)),
      ),
    ];

  void swapStackChildren() {
      setState(() {
        print("swapStackChildren");
        stackChildren = [
          new Positioned(
              left: 40.0,
              child: new Icon(Icons.monetization_on,
                  key: GlobalKey(),
                  size: 60.0,
                  color: const Color.fromRGBO(150, 00, 200, 1.0))),
          new Icon(Icons.monetization_on,
              key: GlobalKey(),
              size: 100.0,
              color: const Color.fromRGBO(200, 200, 100, 1.0)),
        ];
      });
    }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: EdgeInsets.all(8.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Stack(children: stackChildren),
            new RaisedButton(
              child: const Text('Swop'),
              color: Theme.of(context).accentColor,
              elevation: 4.0,
              splashColor: Colors.blueGrey,
              onPressed: () {
                swapStackChildren();
              },
            ),
          ],
        ),
      ),
    );
  }
}

【讨论】:

  • 不要编辑列表内容。用一个新的来代替它
  • @RémiRousselet 你的意思是swapStackChildren 还是你的意思是使用StatelessWidget 代替?因为对于前者,我认为提议的实现与 setState(() =&gt; stackChildren = newStackChildrenOrder); 之类的实现之间没有太大区别
  • Flutter 使用不变性。你不应该改变对象。相同的代码但使用ListView 而不是Stack 会因此而出现错误
  • @KevinDev 你给swapStackChildren 打过电话吗?
  • 是的 - 脚手架中有一个凸起的按钮小部件,我在 onPressed 中调用了 swop 函数。
【解决方案2】:

我找到了一个代码密集度较低的解决方案。您可以使用 Visibility 小部件,您可以在状态更改后控制子小部件的可见性。

 Visibility(
visible:visibility,//it takes bool
//here you can add the bottom widget that you want on top keeping it invisible
),

复制底部小部件并将其添加到顶部,并以可见性方法包裹为不可见,并将底部小部件也包裹起来。因此,当您想要切换时,可以使底部小部件不可见,顶部可见并相应切换

new Stack(
        children: <Widget>[
 Visibility(
visible:topvisibility
  new Positioned(
            left:40.0,
            child: new Icon(Icons.monetization_on, key: GlobalKey(), size: 60.0, color: const Color.fromRGBO(218, 165, 32, 1.0)),
          )
),

          new Icon(Icons.monetization_on, key: GlobalKey(), size: 60.0, color: const 
Color.fromRGBO(200, 100, 180, 1.0)),
          new Positioned(
            left: 20.0,
            child: new Icon(Icons.monetization_on, key: GlobalKey(), size: 60.0, color: const 
Color.fromRGBO(000, 10, 130, 1.0)),
          ),
 Visibility(
visible:bottomvisibility
          new Positioned(
            left:40.0,
            child: new Icon(Icons.monetization_on, key: GlobalKey(), size: 60.0, color: const Color.fromRGBO(218, 165, 32, 1.0)),
          )
),

        ],
      );

然后在 setState() 方法中相应地更改可见性 bool。

【讨论】:

    【解决方案3】:

    你可以参考这篇关于重新排序堆栈项的文章-LINK

    如果您不想在调用 setState(){} 时重新渲染整个小部件,也不要忘记为堆栈小部件分配键。

    【讨论】:

      猜你喜欢
      • 2020-01-13
      • 1970-01-01
      • 1970-01-01
      • 2016-04-15
      • 2022-11-17
      • 2015-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多