How do I put a ReorderableListView inside a Sliver?

1.2k views Asked by At

I want a SliverAppBar at the top of the screen and a SliverFillRemaining below the ReorderableListView.

I've tried multiple solutions and keep getting different errors with each one. CustomSCrollView with the ReorderableListView placed inside the slivers property gives the error "Failed assertion: line 4345 pos 14: 'owner._debugCurrentBuildTarget == this': is not true."

I have also tried adding a SliverChildListDelegate and putting the ReorderableListView inside that, which gives another error.

2

There are 2 answers

0
Grand On

Shows black screen - see comment. Also gives error: The following assertion was thrown during performResize(): _RenderTheatre object was given an infinite size during layout.

And also this error: BoxConstraints forces an infinite height.

@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();
                      },
                    ),
                  ),
                )
            ],
          ),
        )
      ]),
    );
  }
0
James Allen On

I believe this is why the reorderables package exists - I don't think ReorderableListView supports slivers out of the box, so someone made a version which does. It doesn't behave in exactly the same way and there are some limitations (eg you can't seem to customise which area of the widget or which gesture is the trigger for dragging - you can only long-press on the whole widget) but it seems to work for me.