我希望能够根据键(或其他一些ID)在位置插入(或更改)特定的小部件,例如JavaScript 中的
insertBefore(newNode, referenceNode)
函数。
当然,每次插入或更改某个小部件时,我都可以重建小部件树,重复先前构建中使用的所有步骤。
但是,在我的情况下,树将根据一些用户输入创建(更具体地说:基于带有LuaDardo的lua代码),我想避免每次再次解析完整的用户输入,也避免保留我的自己的树结构副本 - 因为无论如何它都可以在 flutter 中的某个地方使用,不是吗?
我只想创建这样的树:
class _MyHomePageState extends State<MyHomePage> {
final GlobalKey _key1 = GlobalKey(), _key2 = GlobalKey();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
key: _key1,
child: const Text(
'Text1',
),
),
Container(
key: _key2,
child: const Text(
'Text2',
),
),
],
),
),
);
}
}
然后,当按下某个按钮时,我想调用类似的东西
_key1a=GlobalKey();
insertBefore(key: _key2, widget: Container(
key: _key1a,
child: const Text(
'Text1a',
),
));
...导致包含“Text1”、“Text1a”、“Text2”的列。
对于如何编写 insertBefore 函数有什么建议吗?
我正在考虑
context.visitChildElements(visitor)
,但我不知道如何使用它,也不知道如何在找到正确的位置后插入小部件。
另外
find.byKey(key)
可能是一个选项,但这似乎只能用于测试?
这是您可以想到要做的事情: 您制作了小部件地图,地图键将成为您的小部件键
示例:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Material App',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
final String title = "Flutter Demo Home Page";
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Map<String, Widget> w = {
'a': const Text(
'a',
),
'b': const Text(
'b',
),
'd': const Text(
'd',
),
};
insertBefore(String keyBefore, String newKey, Widget newWidget) {
int index = w.keys.toList().indexOf(keyBefore);
Map<String, Widget> newMap = {};
newMap.addEntries(w.entries.toList().sublist(0, index));
newMap.addEntries({newKey: newWidget}.entries);
newMap.addEntries(w.entries.toList().sublist(index));
setState(() {
w = newMap;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
insertBefore('d', 'c', const Text('c'));
},
child: const Icon(Icons.add),
),
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
...w.values,
],
),
),
);
}
}