简体   繁体   English

如何将 ReorderableListView 与 flutter_bloc 一起使用?

[英]How to use ReorderableListView with flutter_bloc?

I'm new to flutter_bloc and trying to implement a ReorderableListView, to allow the user to rerange the order of textfields in a listview.我是 flutter_bloc 的新手,并试图实现 ReorderableListView,以允许用户重新排列列表视图中文本字段的顺序。

Unfortunately it isn't working.不幸的是,它不起作用。 After dropping the listtile to the new position it changes back to the old one:将 listtile 放到新的 position 后,它会变回旧的:

演示

This is the output in the screen:这是屏幕中的 output:

class _Levels extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocBuilder<DifficultyLevelsCubit, DifficultyLevelsState>(
      builder: (context, state) {
        print('rebuild');
        return Flexible(
          child: ReorderableListView(
            shrinkWrap: true,
            children: state.levels
                .asMap()
                .map((i, lvl) => MapEntry(
                      i,
                      ListTile(
                        key: ValueKey(i),
                        title: TextField(
                          onChanged: (lvl) => context
                              .read<DifficultyLevelsCubit>()
                              .levelChanged(lvl, i),
                          decoration: InputDecoration(
                            labelText: 'Level',
                            helperText: '',
                            errorText: state.levels[i].invalid
                                ? 'invalid level'
                                : null,
                          ),
                        ),
                        trailing: Icon(Icons.menu),
                      ),
                    ))
                .values
                .toList(),
            onReorder: (int oldIndex, int newIndex) => context
                .read<DifficultyLevelsCubit>()
                .orderChanged(oldIndex, newIndex),
          ),
        );
      },
    );
  }
}

And this my implementation of the reorder function in my cubit class:这是我在我的cubit class 中重新排序 function 的实现:

void orderChanged(int oldIndex, int newIndex) {
    List<DiffLevel> _list = state.levels;

    if (newIndex > oldIndex) {
      newIndex -= 1;
    }
    final items = _list.removeAt(oldIndex);
    _list.insert(newIndex, items);

    emit(state.copyWith(levels: _list));
}

Does someone know why this behaviour appears and how to solve this?有人知道为什么会出现这种行为以及如何解决这个问题吗? Thanks in advance!提前致谢!

Note: print('rebuild )` is not being triggerd on reorder.注意:重新排序时不会触发print('rebuild )`。 I don't really understand why, cause I emit the state in the reorder function and expect the blocbuilder to react on that change.我真的不明白为什么,因为我在重新排序 function 中发出 state 并期望 blocbuilder 对该更改做出反应。

What's happening here is you are mutating the same list and not overwriting it - bloc expects and entirely new list in order to rebuild.这里发生的是你正在改变同一个列表而不是覆盖它 - bloc 期望和全新的列表以重建。

Also, I'm not entirely sure you can emit state directly like that.另外,我不完全确定您可以像这样直接发出 state 。 I generally follow the pattern suggested here where the emitted state carries the updated list我通常遵循此处建议的模式,其中发出的 state 带有更新的列表

 const ListState.success(List<Item> items)
      : this._(status: ListStatus.success, items: items);

With that said, here is the approach I would suggest !话虽如此,这是我建议的方法!

void orderChanged(int oldIndex, int newIndex) {

    if (newIndex > oldIndex) {
      newIndex -= 1;
    }

// First get the items at the old index
    final items = state.levels[oldIndex];

//Then remove it from the old position and insert it at the new one
    final reorderedList = List.of(state.levels)
    ..removeWhere((element) => element.id == items.id)
    ..insert(newIndex, items);

    emit((ListState.success(reorderedList);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM