【问题标题】:How do I put a ReorderableListView inside a Sliver?如何将 ReorderableListView 放入 Sliver 中?
【发布时间】:2021-03-07 20:16:40
【问题描述】:

我想要屏幕顶部的 SliverAppBar 和 ReorderableListView 下方的 SliverFillRemaining。

我尝试了多种解决方案,但每种解决方案都不断出现不同的错误。将 ReorderableListView 放置在 slivers 属性内的 CustomSCrollView 会给出错误“断言失败:第 4345 行 pos 14: 'owner._debugCurrentBuildTarget == this': is not true。”

我还尝试添加一个 SliverChildListDelegate 并将 ReorderableListView 放入其中,这会产生另一个错误。

【问题讨论】:

  • 你试过将 ReorderableListView 放入 SliverToBoxAdapter 吗?
  • 是的,当我这样做时它只是显示黑屏。当我包含 Scaffold 时(如下例所示),屏幕是灰色的 - 与背景颜色相同,因为我将应用程序主题设置为暗。但是当我在没有 Scaffold 小部件的情况下尝试它时,它是纯黑色的。我将代码示例放在“答案中,因为注释的字符太多。

标签: flutter flutter-layout flutter-sliver reorderable-list


【解决方案1】:

我相信这就是 reorderables 包存在的原因 - 我认为 ReorderableListView 不支持开箱即用的条子,所以有人制作了一个支持的版本。它的行为方式并不完全相同,并且存在一些限制(例如,您似乎无法自定义小部件的哪个区域或哪个手势是拖动的触发器 - 您只能长按整个小部件)但是它似乎对我有用。

【讨论】:

    【解决方案2】:

    显示黑屏 - 见评论。 也给出错误: 在 performResize() 期间抛出了以下断言: _RenderTheatre 对象在布局期间被赋予无限大小。

    还有这个错误: BoxConstraints 强制无限高。

    @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: CustomScrollView(slivers: [
            SliverToBoxAdapter(
              child: ReorderableListView(
                onReorder: (oldIndex, newIndex) {
                  setState(() {
                    if (newIndex > oldIndex) {
                      newIndex -= 1;
                    }
                    final Todo item = TodoList.myTodos.removeAt(oldIndex);
                    TodoList.myTodos.insert(newIndex, item);
                  });
                },
                children: [
                  for (final todo in TodoList.myTodos)
                    Dismissible(
                      onDismissed: (direction) {
                        if (direction == DismissDirection.startToEnd && todo.done == false) {
                          // Mark todo as done
                          todo.done = true;
                          TodoList.myTodos.add(Todo(todo.title, todo.done = true,
                              todo.oldIndex = TodoList.myTodos.indexOf(todo)));
                          TodoList.myTodos.remove(todo);
                          debugPrint("Todo ${todo.title} marked as done");
                        } else if (direction == DismissDirection.startToEnd && todo.done == true) {
                          todo.done = false;
                          TodoList.myTodos.insert(todo.oldIndex, Todo(todo.title, todo.done = false));
                          TodoList.myTodos.remove(todo);
                          debugPrint("Todo ${todo.title} marked as undone");
                        } else if (direction == DismissDirection.endToStart) {
                          TodoList.myTodos.remove(todo);
                          debugPrint("Todo ${todo.title} deleted");
                        }
                        setState(() {});
                      },
                      key: todo.key,
                      background: Container(
                        color: Colors.green,
                        child: Icon(Icons.check),
                      ),
                      secondaryBackground: Container(
                        color: Colors.red,
                        child: Icon(Icons.delete),
                      ),
                      child: ListTile(
                        tileColor: calculateColor(todo),
                        key: todo.key,
                        title: TextField(
                          // TODO fix long press to drag todo instead of selecting the textfield. Short tap should be to select textfield!
                          // TODO Add app theme to textfield
                          style: (todo.done ? TextStyle(decoration: TextDecoration.lineThrough) : null),
                          controller: TextEditingController(text: todo.title),
                          decoration: null,
                          maxLength: 512,
                          maxLines: null,
                          textInputAction: TextInputAction.done,
                          onChanged: (text) {
                            //TODO check if correct
                            todo.title = text;
                          },
                          onEditingComplete: () {
                            //TODO check if correct
                            FocusScopeNode currentFocus = FocusScope.of(context);
                            currentFocus.unfocus();
                          },
                          onSubmitted: (text) {
                            //TODO check if correct
                            todo.title = text;
                            FocusScopeNode currentFocus = FocusScope.of(context);
                            currentFocus.unfocus();
                          },
                        ),
                      ),
                    )
                ],
              ),
            )
          ]),
        );
      }
    

    【讨论】:

      猜你喜欢
      • 2019-09-10
      • 2021-08-10
      • 2019-11-10
      • 2020-07-21
      • 2022-11-11
      • 2021-06-04
      • 2022-11-15
      • 2021-08-08
      • 2020-04-19
      相关资源
      最近更新 更多