使用 Getx 进行 Flutter ListView.builder 管理
Flutter ListView.builder management with Getx
我刚开始学习 Getx,我遇到了以下问题:我有一个带有 CodeLine() 小部件的 ListView.builder,您可以在其中 select它与一个 onLongPress。这里的想法是 select 一行,但是当我给 onLongPress 时,所有行都 select 在一起。
class CodeEditor extends GetView<CodeEditorController> {
const CodeEditor({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
ScrollController scrollCode = ScrollController();
return Padding(
padding: const EdgeInsets.fromLTRB(0.0, 0.0, 10.0, 120.0),
child: ListView.builder(
controller: scrollCode,
itemCount: 10,
itemBuilder: (BuildContext context, int index){
return CodeLine();
}
)
);
}
}
在 CodeLine 中,我有 isSelected 变量在 selected 或未编辑时显示在屏幕上,我在 CodeLineController 控制器中更改它的值
class CodeLine extends GetView<CodeLineController> {
CodeLine({Key? key}) : super(key: key);
@override
final controller = Get.put(CodeLineController());
@override
Widget build(BuildContext context) {
return GestureDetector(
child: GetX<CodeLineController>(
builder: (_){
return !_.isHidden ? Container(
color: _.isSelected ? const Color(0x327a7a7a) : Colors.transparent,
height: 35.0,
child: Row(
children: <Widget>[
SizedBox(
width: 25.0,
child: Text(
"1",
textAlign: TextAlign.end,
style: TextStyle(
color: codeLineTheme.hintColor,
fontSize: 15.0,
fontWeight: FontWeight.bold
)
)
),
const SizedBox(width: 7.5),
const Expanded(
child: SizedBox()
)
]
)
) : const SizedBox();
}
),
onLongPress: (){
controller.isSelected = !controller.isSelected;
}
);
}
}
在 CodeLineController 中,我将 isSelected 变量作为可观察变量,但是当我更改它的布尔值时,所有 CodeLine 实例的此值也会更改,我如何才能仅更改特定 CodeLine 的 isSelected 变量?
class CodeLineController extends GetxController{
CodeLineController();
final _isHidden = false.obs;
get isHidden => _isHidden.value;
set isHidden(value) => _isHidden.value = value;
final _isSelected = false.obs;
get isSelected => _isSelected.value;
set isSelected(value) => _isSelected.value = value;
}
当您使用 Get.put 调用使用 GetxController 扩展的 class 时,在项目中只能找到该对象之一。而且您始终在代码行小部件中定义相同的对象。因此,更改会影响其所有小部件。你可以这样解决你的问题:
在 CodeLineController 中添加地图。使用特殊键将您使用 ListView 复制的所有 CodeLine 小部件保存到地图。
class CodeLineController extends GetxController {
final RxMap<Key, bool> _map = <Key, bool>{}.obs;
void setKey(Key key, bool value) {
_map[key] = value;
}
void changeValue(Key key) {
if (_map[key] != null) {
_map[key] = !_map[key]!;
}
}
bool getValue(Key key) {
if (_map[key] != null) {
return _map[key]!;
} else {
return false;
}
}
...
}
它可以是一个int“index”值而不是Map中的“key”或者你想要的唯一数据。
您可以将“key”作为参数传递给代码行class。
class CodeLine extends GetView<CodeLineController> {
final Key myKey;
CodeLine({
Key? key,
required this.myKey,
}) : super(key: key);
...
}
创建代码行时 class,将键作为参数传递到 ListView 中。
...
Key myKey;
return Padding(
...
itemBuilder: (BuildContext context, int index) {
myKey = GlobalKey();
controller.setKey(myKey, false);
return CodeLine(myKey: myKey);
},
...
长按
...
onLongPress: () {
controller.changeValue(myKey);
},
...
这是您检查的方式
...
Container(
color: controller.getValue(myKey)
? const Color(0x327a7a7a)
: Colors.transparent,
...
我刚开始学习 Getx,我遇到了以下问题:我有一个带有 CodeLine() 小部件的 ListView.builder,您可以在其中 select它与一个 onLongPress。这里的想法是 select 一行,但是当我给 onLongPress 时,所有行都 select 在一起。
class CodeEditor extends GetView<CodeEditorController> {
const CodeEditor({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
ScrollController scrollCode = ScrollController();
return Padding(
padding: const EdgeInsets.fromLTRB(0.0, 0.0, 10.0, 120.0),
child: ListView.builder(
controller: scrollCode,
itemCount: 10,
itemBuilder: (BuildContext context, int index){
return CodeLine();
}
)
);
}
}
在 CodeLine 中,我有 isSelected 变量在 selected 或未编辑时显示在屏幕上,我在 CodeLineController 控制器中更改它的值
class CodeLine extends GetView<CodeLineController> {
CodeLine({Key? key}) : super(key: key);
@override
final controller = Get.put(CodeLineController());
@override
Widget build(BuildContext context) {
return GestureDetector(
child: GetX<CodeLineController>(
builder: (_){
return !_.isHidden ? Container(
color: _.isSelected ? const Color(0x327a7a7a) : Colors.transparent,
height: 35.0,
child: Row(
children: <Widget>[
SizedBox(
width: 25.0,
child: Text(
"1",
textAlign: TextAlign.end,
style: TextStyle(
color: codeLineTheme.hintColor,
fontSize: 15.0,
fontWeight: FontWeight.bold
)
)
),
const SizedBox(width: 7.5),
const Expanded(
child: SizedBox()
)
]
)
) : const SizedBox();
}
),
onLongPress: (){
controller.isSelected = !controller.isSelected;
}
);
}
}
在 CodeLineController 中,我将 isSelected 变量作为可观察变量,但是当我更改它的布尔值时,所有 CodeLine 实例的此值也会更改,我如何才能仅更改特定 CodeLine 的 isSelected 变量?
class CodeLineController extends GetxController{
CodeLineController();
final _isHidden = false.obs;
get isHidden => _isHidden.value;
set isHidden(value) => _isHidden.value = value;
final _isSelected = false.obs;
get isSelected => _isSelected.value;
set isSelected(value) => _isSelected.value = value;
}
当您使用 Get.put 调用使用 GetxController 扩展的 class 时,在项目中只能找到该对象之一。而且您始终在代码行小部件中定义相同的对象。因此,更改会影响其所有小部件。你可以这样解决你的问题: 在 CodeLineController 中添加地图。使用特殊键将您使用 ListView 复制的所有 CodeLine 小部件保存到地图。
class CodeLineController extends GetxController {
final RxMap<Key, bool> _map = <Key, bool>{}.obs;
void setKey(Key key, bool value) {
_map[key] = value;
}
void changeValue(Key key) {
if (_map[key] != null) {
_map[key] = !_map[key]!;
}
}
bool getValue(Key key) {
if (_map[key] != null) {
return _map[key]!;
} else {
return false;
}
}
...
}
它可以是一个int“index”值而不是Map中的“key”或者你想要的唯一数据。
您可以将“key”作为参数传递给代码行class。
class CodeLine extends GetView<CodeLineController> {
final Key myKey;
CodeLine({
Key? key,
required this.myKey,
}) : super(key: key);
...
}
创建代码行时 class,将键作为参数传递到 ListView 中。
...
Key myKey;
return Padding(
...
itemBuilder: (BuildContext context, int index) {
myKey = GlobalKey();
controller.setKey(myKey, false);
return CodeLine(myKey: myKey);
},
...
长按
...
onLongPress: () {
controller.changeValue(myKey);
},
...
这是您检查的方式
...
Container(
color: controller.getValue(myKey)
? const Color(0x327a7a7a)
: Colors.transparent,
...