GetX 和 ListView 问题
GetX and ListView issues
我在 GetX 的整个状态管理上遇到了很多问题,所以我自然会遇到一些问题。
我从 firebase 获取了一个集合,我将其放入填充有 Card 小部件 (CustomCard()
) 的列表视图中,每个文档都放入一个 Card 小部件中。在此 Card 小部件中,我有一个布尔值,用于控制在点击 Card 时是否应展开卡片(只需添加一个 Row())。我面临的问题是,如果对这个布尔值使用 GetX,所有卡片都会触发,而不是每张卡片。在某种程度上,这似乎合乎逻辑,因为我只有一个控制器来管理这个布尔值。
所以澄清一下,bool isCardExpanded
似乎对所有卡片小部件都是全局的,这意味着如果我点击一张卡片,所有 张卡片都会展开,这不是我想要的想。我需要他们单独行动。
列表视图中的每张卡片是否需要一个单独的控制器,或者这是否可以通过其他方式解决?
控制器
class Controller extends GetxController {
RxBool isCardExpanded = false.obs;
void changeExpanded() {
isCardExpanded.value = !isCardExpanded.value;
update();
}
}
列表视图:
class CustomScreen extends State<CustomScreen>
implements ItemScreenInterface {
Controller ctrl = Get.find();
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: FirebaseFirestore.instance
.collection(someCol)
.doc(SomeDoc)
.collection(anotherCol).snapshots(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
return Column(
children: [
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.docs.length,
itemBuilder: (_, i) {
return CustomCard( // <------------ Card widget
document: snapshot.data.docs[i]);
}),
)
],
);
},
);
}
卡片class
class CustomCard extends StatefulWidget {
CustomCard({required this.doc});
var doc;
@override
_CustomCardState createState() => _CustomCardState();
}
class _CustomCardState extends State<CustomCard> {
Controller ctrl = Get.find();
RxBool _isCardExpanded = false.obs;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Card(
child: GestureDetector(
onTap: () {
ctrl.changeExpanded(); // <-- change bool
},
child: Padding(
padding: EdgeInsets.all(2),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Text('Top Part')
]),
if (_isCardExpanded.value) Divider(thickness: 2),
if (_isCardExpanded.value) // Controlled by _isCardExpanded. Add Row if true
Row(
children: <Widget>[
Text('EXPANDED'),
],
),
],
),
),
),
);
}
}
期望的结果:
实际结果:
因为您的控制器实例只初始化一次。
要解决您的问题,您需要制作一个 List
具有 Controller
中卡片状态的 List
。
或者不使用状态管理工具,而是将_isExpanded
值单独放在_CustomCardState
class中。并使用 setState()
函数。
编辑
还有一种方法是在创建控制器时使用 tag
参数,例如 Get.create(someController, tag: TAG_NAME);
我在 GetX 的整个状态管理上遇到了很多问题,所以我自然会遇到一些问题。
我从 firebase 获取了一个集合,我将其放入填充有 Card 小部件 (CustomCard()
) 的列表视图中,每个文档都放入一个 Card 小部件中。在此 Card 小部件中,我有一个布尔值,用于控制在点击 Card 时是否应展开卡片(只需添加一个 Row())。我面临的问题是,如果对这个布尔值使用 GetX,所有卡片都会触发,而不是每张卡片。在某种程度上,这似乎合乎逻辑,因为我只有一个控制器来管理这个布尔值。
所以澄清一下,bool isCardExpanded
似乎对所有卡片小部件都是全局的,这意味着如果我点击一张卡片,所有 张卡片都会展开,这不是我想要的想。我需要他们单独行动。
列表视图中的每张卡片是否需要一个单独的控制器,或者这是否可以通过其他方式解决?
控制器
class Controller extends GetxController {
RxBool isCardExpanded = false.obs;
void changeExpanded() {
isCardExpanded.value = !isCardExpanded.value;
update();
}
}
列表视图:
class CustomScreen extends State<CustomScreen>
implements ItemScreenInterface {
Controller ctrl = Get.find();
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: FirebaseFirestore.instance
.collection(someCol)
.doc(SomeDoc)
.collection(anotherCol).snapshots(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
return Column(
children: [
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.docs.length,
itemBuilder: (_, i) {
return CustomCard( // <------------ Card widget
document: snapshot.data.docs[i]);
}),
)
],
);
},
);
}
卡片class
class CustomCard extends StatefulWidget {
CustomCard({required this.doc});
var doc;
@override
_CustomCardState createState() => _CustomCardState();
}
class _CustomCardState extends State<CustomCard> {
Controller ctrl = Get.find();
RxBool _isCardExpanded = false.obs;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Card(
child: GestureDetector(
onTap: () {
ctrl.changeExpanded(); // <-- change bool
},
child: Padding(
padding: EdgeInsets.all(2),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Text('Top Part')
]),
if (_isCardExpanded.value) Divider(thickness: 2),
if (_isCardExpanded.value) // Controlled by _isCardExpanded. Add Row if true
Row(
children: <Widget>[
Text('EXPANDED'),
],
),
],
),
),
),
);
}
}
期望的结果:
实际结果:
因为您的控制器实例只初始化一次。
要解决您的问题,您需要制作一个 List
具有 Controller
中卡片状态的 List
。
或者不使用状态管理工具,而是将_isExpanded
值单独放在_CustomCardState
class中。并使用 setState()
函数。
编辑
还有一种方法是在创建控制器时使用 tag
参数,例如 Get.create(someController, tag: TAG_NAME);