颤振-更改堆叠顺序

时间:2018-11-14 20:50:08

标签: stack flutter

我有一个堆栈,在某种情况下(例如,用户单击),我希望将一个较低级别的窗口小部件推入堆栈的顶部。使用下面的代码作为简单示例-我需要在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();
          },
        ),
      ],
    ),
  ),
);
}

}

3 个答案:

答案 0 :(得分: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;
        });
  }

编辑:如评论所建议,最好为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();
              },
            ),
          ],
        ),
      ),
    );
  }
}

答案 1 :(得分:0)

我发现了一个代码使用量较少的解决方案。您可以使用“可见性”小部件,该控件可以在状态更改后控制子小部件的可见性。

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

制作一个底部小部件的副本,并将其添加到Visibility方法中包裹的顶部,使其不可见,也包裹底部的部件。因此,当您要切换时,可以使底部的部件不可见,顶部的顶部可见并进行相应的切换

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()方法中相应地更改可见性布尔值。

答案 2 :(得分:0)

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

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