按下另一个按钮后,列表磁贴按钮会更改状态

Posted

技术标签:

【中文标题】按下另一个按钮后,列表磁贴按钮会更改状态【英文标题】:List tile button changes state after pressing another button 【发布时间】:2022-01-20 21:38:25 【问题描述】:

有一个带有列表图块的抽屉,其中包含选中所有和取消选中所有按钮,当我单击选中所有按钮时,它应该选中所有列表项的复选框,但只有在我单击任何其他按钮后 UI 才会更改或更新,取消选中按钮也会产生同样的问题。

drawer: Drawer(
    child: Obx(() => ListView(
          padding: EdgeInsets.zero,
          children: <Widget>[
            UserAccountsDrawerHeader(
              decoration: BoxDecoration(
                color: (Get.isDarkMode) ? Colors.black26 : Colors.grey[300],
              ),
              accountName: Text('Reminders',
                  style: TextStyle(
                    fontSize: 30.0,
                    color: Theme.of(context).textTheme.headline1!.color,
                  )),
              currentAccountPicture: CircleAvatar(
                  backgroundColor: Colors.white,
                  child: Image(
                    image: AssetImage("assets/App_icon.png"),
                  )),
              accountEmail: null,
            ),
            ListTile(
              title: Text("Check all",
                  style: TextStyle(
                      fontSize: 17.0,
                      color: Theme.of(context).textTheme.headline1!.color)),
              leading: Icon(Icons.check_box),
              onTap: () 
                checkAll();
              ,
            ),
            ListTile(
              title: Text("Uncheck all",
                  style: TextStyle(
                      fontSize: 17.0,
                      color: Theme.of(context).textTheme.headline1!.color)),
              leading: Icon(Icons.check_box_outline_blank),
              onTap: () 
                unCheckAll();
              ,
            ),
            ListTile(
              title: Text(
                (Get.isDarkMode)
                    ? 'Change theme:  light'
                    : 'change theme:  dark',
                style: TextStyle(
                    fontSize: 17.0,
                    color: Theme.of(context).textTheme.headline1!.color),
              ),
              leading: Icon(Icons.color_lens_sharp),
              onTap: () 
                if (Get.isDarkMode) 
                  Get.changeThemeMode(ThemeMode.light);
                 else 
                  Get.changeThemeMode(ThemeMode.dark);
                
              ,
            ),
            ListTile(
              title: Text(
                "Delete all",
                style: TextStyle(
                    fontSize: 17.0,
                    color: Theme.of(context).textTheme.headline1!.color),
              ),
              leading: Icon(Icons.delete),
              onTap: () 
                todoController.todos.clear();
              ,
            ),
            ListTile(
              title: Text(
                "No of tasks:  $todoController.todos.length",
                style: TextStyle(
                    fontSize: 20,
                    color: Theme.of(context).textTheme.headline1!.color),
              ),
              onTap: () ,
            ),
          ],
        )),

全选和取消全选功能:

void checkAll() 
  TodoController todoController = Get.put(TodoController());
  for (var i = 0; i < todoController.todos.length; i++) 
  todoController.todos[i].done = true;
 
 GetStorage().write('todos', todoController.todos.toList());


void unCheckAll() 
 TodoController todoController = Get.put(TodoController());
 for (var i = 0; i < todoController.todos.length; i++) 
   todoController.todos[i].done = false;
 
 GetStorage().write('todos', todoController.todos.toList());

【问题讨论】:

checkAllunCheckAll 中使用setState 我试过了,它奏效了,我之前确实尝试过,将它设为有状态小部件并添加设置状态,但在将 Obx 与其他按钮一起使用时它有效,所以不知道是什么导致了问题. 【参考方案1】:

虽然看起来很奇怪,但这样做会解决它:

.... 
todoController.todos.assignAll(todoController.todos.toList());
GetStorage().write('todos', todoController.todos.toList());

为什么?

假设todoController.todos 是一个RxList,更改列表中各个元素的属性对底层流没有影响。因此,尽管更改了值,但它不会触发 Obx 上的重建。

但是像todoController.todos.assignAll(todoController.todos.toList()); 这样的操作实际上会改变 RxList 的底层流/值。因此会触发应有的重建。

当使用 Rxobservables 时,请始终牢记Obx/GetX 只会,并且只有在 的实际 value 才会触发重建Rx/Observable 已更改。 todoController.todos[i].done = true; 之类的东西意味着更改 RxList 的第 i 个元素的 done 属性的值,而不是实际 RxList 的值>。 assignAll 就是这样做的。

同样适用于其他Rx。 假设以下是SomeModel 类的Rx 对象:

final someModel= SomeModel().obs;

做类似的事情:

someModel.value.someProperty = someValue;

不会触发 UI 重建,而是执行以下操作:

 someModel.value.someProperty = someValue;

  someModel.value = someModel.value;

会的。

但这有点奇怪吧? 在这种情况下,copyWith 实用程序方法可能很有用。

【讨论】:

以上是关于按下另一个按钮后,列表磁贴按钮会更改状态的主要内容,如果未能解决你的问题,请参考以下文章

如何更改 UIpickerView 上的元素按下按钮或按下另一个按钮

按下按钮后隐藏状态栏(iOS)

如何在按下按钮后每 10 分钟重复一次方法并在按下另一个按钮时结束它

按下其他按钮后无法更改uibutton的图像

Android:如何在按下按钮时关闭一个活动并在按下另一个按钮时关闭整个后台堆栈? [复制]

UITableView 复选框(按下另一个按钮时选择一个按钮)