我有一个堆栈,在某种情况下(例如,用户单击),我希望将一个较低级别的窗口小部件推入堆栈的顶部。使用下面的代码作为简单示例-我需要在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();
},
),
],
),
),
);
}
}
答案 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(){} 时重新渲染整个小部件,也不要忘记为堆栈小部件分配键。