简体   繁体   English

如何在 Flutter ReorderableListView 中的 ListTiles 之间创建空间

[英]How to create space between ListTiles in Flutter ReorderableListView

I have a ReorderableListView who looks like this:我有一个看起来像这样的ReorderableListView

在此处输入图像描述

And I would like it to have space between his ListTile like in the ListView.separated below:我希望它在他的 ListTile 之间有空间,就像下面的ListView.separated一样:

在此处输入图像描述

The problem is that I don't want to use ListView.separated because you can't drag and drop ListTiles with it.问题是我不想使用ListView.separated因为你不能用它拖放 ListTiles。

Update Solution found:发现更新解决方案:

I used Varun's answer below of wrapping my ListTile in a Column, but instead of using a SizedBox I used a Container to be able to change the color of the space from white to my background color:我在下面使用 Varun 的回答将我的 ListTile 包装在一个列中,但我没有使用 SizedBox,而是使用了一个 Container 能够将空间的颜色从白色更改为我的背景颜色:

Container(
          height: 5.0,
          color: MyColors.myBackgroundColor
        )

You could just wrap your listTile with a padding at the bottom as "divider" it might not be ideal as the padding would be part of the widget, whic would be visible when dragging.您可以只用底部的填充将您的 listTile 包装为“分隔符”,这可能并不理想,因为填充将成为小部件的一部分,在拖动时会可见。

在此处输入图像描述

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: Scaffold(
        appBar: AppBar(title: const Text(_title)),
        body: const MyStatefulWidget(),
      ),
    );
  }
}

class MyStatefulWidget extends StatefulWidget {
  const MyStatefulWidget({Key? key}) : super(key: key);

  @override
  State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  final List<int> _items = List<int>.generate(50, (int index) => index);

  @override
  Widget build(BuildContext context) {
    final ColorScheme colorScheme = Theme.of(context).colorScheme;
    final Color oddItemColor = colorScheme.primary.withOpacity(0.05);
    final Color evenItemColor = colorScheme.primary.withOpacity(0.15);

    return ReorderableListView(
      padding: const EdgeInsets.symmetric(horizontal: 40),
      children: <Widget>[
        for (int index = 0; index < _items.length; index++)
          Padding(
              key: Key('$index'),
              padding: const EdgeInsets.only(bottom: 4),
              child: ListTile(
                tileColor: _items[index].isOdd ? oddItemColor : evenItemColor,
                title: Text('Item ${_items[index]}'),
              )),
      ],
      onReorder: (int oldIndex, int newIndex) {
        setState(() {
          if (oldIndex < newIndex) {
            newIndex -= 1;
          }
          final int item = _items.removeAt(oldIndex);
          _items.insert(newIndex, item);
        });
      },
    );
  }
}


Adding the space as a non reorderable widget does not seem possible with ReorderableListView even adding dummy items interleaving the ListTiles with AbsorbPointer still renders them reorderable.使用 ReorderableListView 似乎无法将空间添加为不可重新排序的小部件,即使添加将 ListTiles 与 AbsorbPointer 交错的虚拟项目仍然会使它们可重新排序。 So the method above is at least doable所以上面的方法至少是可行的在此处输入图像描述

      children: <Widget>[
        for (int index = 0; index < _items.length; index++)
          if (index.isOdd)
            ListTile(
              key: Key('$index'),
              tileColor: _items[index].isOdd ? oddItemColor : evenItemColor,
              title: Text('Item ${_items[index]}'),
            )
          else if (index.isEven)
            AbsorbPointer(
              key: Key('$index'),
              child: SizedBox.square(
                key: Key('$index'),
                dimension: 40,
              ),
            ),
      ],

Wrap your ListTile in a column and use SizedBox to separate list items.将您的 ListTile 包装在一列中,并使用 SizedBox 分隔列表项。 Use key in column, not inside ListTile.在列中使用键,而不是在 ListTile 中。

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: Scaffold(
        appBar: AppBar(title: const Text(_title)),
        body: const MyStatefulWidget(),
      ),
    );
  }
}

class MyStatefulWidget extends StatefulWidget {
  const MyStatefulWidget({Key? key}) : super(key: key);

  @override
  State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  final List<int> _items = List<int>.generate(50, (int index) => index);

  @override
  Widget build(BuildContext context) {
    final ColorScheme colorScheme = Theme.of(context).colorScheme;
    final Color oddItemColor = colorScheme.primary.withOpacity(0.05);
    final Color evenItemColor = colorScheme.primary.withOpacity(0.15);

    return ReorderableListView(
      padding: const EdgeInsets.symmetric(horizontal: 40),
      children: <Widget>[
        for (int index = 0; index < _items.length; index++)
          Column(
            key: Key('$index'),
            children: [
              ListTile(
                tileColor: _items[index].isOdd ? oddItemColor : evenItemColor,
                title: Text('Item ${_items[index]}'),
              ),
              SizedBox(
                height: 5,
              ),
            ],
          ),
      ],
      onReorder: (int oldIndex, int newIndex) {
        setState(() {
          if (oldIndex < newIndex) {
            newIndex -= 1;
          }
          final int item = _items.removeAt(oldIndex);
          _items.insert(newIndex, item);
        });
      },
    );
  }
}

This is works like a mixture ViewList.separated and ReorderableList这就像 ViewList.separated 和 ReorderableList 的混合物

     import 'dart:math';

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

class CustomReorderableListView extends ReorderableListView {
  CustomReorderableListView.separated({
    Key? key,
    required IndexedWidgetBuilder itemBuilder,
    required IndexedWidgetBuilder separatorBuilder,
    required int itemCount,
    required ReorderCallback onReorder,
    double? itemExtent,
    Widget? prototypeItem,
    ReorderItemProxyDecorator? proxyDecorator,
    bool buildDefaultDragHandles = true,
    EdgeInsets? padding,
    Widget? header,
    Axis scrollDirection = Axis.vertical,
    bool reverse = false,
    ScrollController? scrollController,
    bool? primary,
    ScrollPhysics? physics,
    bool shrinkWrap = false,
    double anchor = 0.0,
    double? cacheExtent,
    DragStartBehavior dragStartBehavior = DragStartBehavior.start,
    ScrollViewKeyboardDismissBehavior keyboardDismissBehavior =
        ScrollViewKeyboardDismissBehavior.manual,
    String? restorationId,
    Clip clipBehavior = Clip.hardEdge,
  }) : super.builder(
    key: key,
    itemCount: max(0, itemCount * 2 - 1),
    itemBuilder: (BuildContext context, int index) {
      if (index % 2 == 1) {
        final separator = separatorBuilder.call(context, index);

        if (separator.key == null) {
          return KeyedSubtree(
            key: ValueKey('ReorderableSeparator${index}Key'),
            child: IgnorePointer(child: separator),
          );
        }

        return separator;
      }

      return itemBuilder.call(context, index ~/ 2);
    },
    onReorder: (int oldIndex, int newIndex) {
      if (oldIndex < newIndex) {
        newIndex -= 1;
      }

      if (oldIndex % 2 == 1) {
        //separator - should never happen
        return;
      }

      if ((oldIndex - newIndex).abs() == 1) {
        //moved behind the top/bottom separator
        return;
      }

      newIndex = oldIndex > newIndex && newIndex % 2 == 1
          ? (newIndex + 1) ~/ 2
          : newIndex ~/ 2;
      oldIndex = oldIndex ~/ 2;
      onReorder.call(oldIndex, newIndex);
    },
    itemExtent: itemExtent,
    prototypeItem: prototypeItem,
    proxyDecorator: proxyDecorator,
    buildDefaultDragHandles: buildDefaultDragHandles,
    padding: padding,
    header: header,
    scrollDirection: scrollDirection,
    reverse: reverse,
    scrollController: scrollController,
    primary: primary,
    physics: physics,
    shrinkWrap: shrinkWrap,
    anchor: anchor,
    cacheExtent: cacheExtent,
    dragStartBehavior: dragStartBehavior,
    keyboardDismissBehavior: keyboardDismissBehavior,
    restorationId: restorationId,
    clipBehavior: clipBehavior,
  );
}
    
                if ((oldIndex - newIndex).abs() == 1) {
                  return;
                }
    
                if (oldIndex > newIndex && newIndex % 2 == 1) {
                  newIndex = (newIndex + 1) ~/ 2;
                } else if (oldIndex > newIndex && newIndex % 2 != 1) {
                  newIndex = (newIndex) ~/ 2;
                } else if (newIndex == 0) {
                  newIndex = (newIndex ~/ 2);
                } else {
                  newIndex = (newIndex ~/ 2) + 1;
                }
                oldIndex = oldIndex ~/ 2;
                onReorder.call(oldIndex, newIndex);
              },
              itemExtent: itemExtent,
              prototypeItem: prototypeItem,
              proxyDecorator: proxyDecorator,
              buildDefaultDragHandles: buildDefaultDragHandles,
              padding: padding,
              header: header,
              scrollDirection: scrollDirection,
              reverse: reverse,
              scrollController: scrollController,
              primary: primary,
              physics: physics,
              shrinkWrap: shrinkWrap,
              anchor: anchor,
              cacheExtent: cacheExtent,
              dragStartBehavior: dragStartBehavior,
              keyboardDismissBehavior: keyboardDismissBehavior,
              restorationId: restorationId,
              clipBehavior: clipBehavior,
            );
    }

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

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