英文:
How to change parent of widgets without rebuilding their states
问题
在Flutter中,我有如下的小部件:
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) => Scaffold(
body: OrientationBuilder(
builder: (context, orientation) {
const List<ColorfulBox> children = [ColorfulBox(), ColorfulBox()];
return orientation == Orientation.portrait ?
const Row(children: children) :
const Column(children: children);
},
),
);
}
class ColorfulBox extends StatefulWidget {
const ColorfulBox({super.key});
@override
State<ColorfulBox> createState() => _ColorfulBoxState();
}
class _ColorfulBoxState extends State<ColorfulBox> {
@override
Widget build(BuildContext context) => Container(
width: 100,
height: 100,
color: getRandomColor(),
);
}
Color getRandomColor() {
var generatedColor = Random().nextInt(Colors.primaries.length);
return Colors.primaries[generatedColor];
}
目前,当我旋转设备时,ColorfulBox
的新状态会重新构建,导致颜色改变。
我想知道如何保持ColorfulBox
的状态?
我尝试给ColorfulBox
添加不同的键名,还尝试添加AutomaticKeepAliveClientMixin
,但这两个想法都没有奏效。
英文:
In flutter, I have widgets like:
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) => Scaffold(
body: OrientationBuilder(
builder: (context, orientation) {
const List<ColorfulBox> children = [ColorfulBox(), ColorfulBox()];
return orientation == Orientation.portrait ?
const Row(children: children) :
const Column(children: children);
},
),
);
}
class ColorfulBox extends StatefulWidget {
const ColorfulBox({super.key});
@override
State<ColorfulBox> createState() => _ColorfulBoxState();
}
class _ColorfulBoxState extends State<ColorfulBox> {
@override
Widget build(BuildContext context) => Container(
width: 100,
height: 100,
color: getRandomColor(),
);
}
Color getRandomColor() {
var generatedColor = Random().nextInt(Colors.primaries.length);
return Colors.primaries[generatedColor];
}
Currently when I rotate the device, new state of ColorfulBox
will be build what causes color change.
I was wondering how can I keep ColorfulBox
state?
I tried adding keys differently named to ColorfulBox
and also adding AutomaticKeepAliveClientMixin
but none of those two ideas worked.
答案1
得分: 1
事实上,您的小部件状态并未重新创建,而是再次执行了构建函数。
您需要在build
方法之外调用getRandomColor()
:
使用以下代码:
class ColorfulBox extends StatefulWidget {
const ColorfulBox({super.key});
@override
State<ColorfulBox> createState() => _ColorfulBoxState();
}
class _ColorfulBoxState extends State<ColorfulBox> {
final _color = getRandomColor();
@override
Widget build(BuildContext context) => Container(
width: 100,
height: 100,
color: _color,
);
}
Color getRandomColor() {
var generatedColor = Random().nextInt(Colors.primaries.length);
return Colors.primaries[generatedColor];
}
更新:
另外,您需要将Row
和Column
小部件更改为Flex
小部件,否则无法在不重新创建的情况下将小部件从列移动到行(或反之亦然)。
因此,请将
return orientation == Orientation.portrait
? Row(children: children)
: Column(children: children);
更改为
return Flex(
direction: orientation == Orientation.portrait ? Axis.horizontal : Axis.vertical,
children: children,
);
英文:
In fact, your state of widget is not recreated, but the build function is executed again.
You need call getRandomColor()
outside of the build
method:
Use this code:
class ColorfulBox extends StatefulWidget {
const ColorfulBox({super.key});
@override
State<ColorfulBox> createState() => _ColorfulBoxState();
}
class _ColorfulBoxState extends State<ColorfulBox> {
final _color=getRandomColor();
@override
Widget build(BuildContext context) => Container(
width: 100,
height: 100,
color: _color,
);
}
Color getRandomColor() {
var generatedColor = Random().nextInt(Colors.primaries.length);
return Colors.primaries[generatedColor];
}
Update:
Also you need to change your Row and Column widget to Flex widget, you can't move widgets from Column to Row (or reverse) without recreating.
So, change
return orientation == Orientation.portrait
? Row(children: children)
: Column(children: children);
To
return Flex(
direction: orientation == Orientation.portrait ? Axis.horizontal : Axis.vertical,
children: children,
);
答案2
得分: 1
你可以在定义子项列表时将颜色设置得更高一些:
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
Color _getRandomColor() =>
Colors.primaries[Random().nextInt(Colors.primaries.length)];
class MyApp extends StatelessWidget {
const MyApp({Key? key});
@override
Widget build(BuildContext context) => const MaterialApp(home: MyHomePage());
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key});
@override
Widget build(BuildContext context) {
List<ColorfulBox> children = [
ColorfulBox(key: const Key("1"), color: _getRandomColor()),
ColorfulBox(key: const Key("2"), color: _getRandomColor()),
];
return Scaffold(body: OrientationBuilder(
builder: (BuildContext context, Orientation orientation) {
return orientation == Orientation.portrait
? Row(children: children)
: Column(children: children);
},
));
}
}
class ColorfulBox extends StatefulWidget {
const ColorfulBox({Key? key, required this.color});
final Color color;
@override
State<ColorfulBox> createState() => _ColorfulBoxState();
}
class _ColorfulBoxState extends State<ColorfulBox> {
@override
Widget build(BuildContext context) {
print("build ${widget.key}");
return Container(
width: 100,
height: 100,
color: widget.color,
);
}
}
英文:
You could set the colors higher up, when you define the children List:
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
Color _getRandomColor() =>
Colors.primaries[Random().nextInt(Colors.primaries.length)];
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) => const MaterialApp(home: MyHomePage());
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context) {
List<ColorfulBox> children = [
ColorfulBox(key: Key("1"), color: _getRandomColor()),
ColorfulBox(key: Key("2"), color: _getRandomColor()),
];
return Scaffold(body: OrientationBuilder(
builder: (BuildContext context, Orientation orientation) {
return orientation == Orientation.portrait
? Row(children: children)
: Column(children: children);
},
));
}
}
class ColorfulBox extends StatefulWidget {
const ColorfulBox({super.key, required this.color});
final Color color;
@override
State<ColorfulBox> createState() => _ColorfulBoxState();
}
class _ColorfulBoxState extends State<ColorfulBox> {
@override
Widget build(BuildContext context) {
print("build ${widget.key}");
return Container(
width: 100,
height: 100,
color: widget.color,
);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论