在ListView中添加向右滑动以删除项目

15

我有一个使用自定义适配器(继承BaseAdapter)的ListView。如何添加左滑删除手势?

我想使用与Gmail应用程序相同的功能。


1
你可以使用类似 https://github.com/baoyongzhang/SwipeMenuListView 或 https://github.com/chthai64/SwipeRevealLayout 或 https://github.com/daimajia/AndroidSwipeLayout 的库。 - AndroidRuntimeException
问题在于为了实现这个库,我必须重写所有的内容..... - Fra87
5个回答

26

最简单的方法是将您的ListView切换到RecyclerView,并使用单列的GridLayoutManager。它的外观不会改变,但可以使用ItemTouchHelper进行滑动删除。

     recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
     recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 1));

     recyclerView.setAdapter(adapter);


    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
        @Override
        public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
            // Remove item from backing list here
            adapter.notifyDataSetChanged();
        }
    });

    itemTouchHelper.attachToRecyclerView(recyclerView);

是的,你需要将ListView更改为RecyclerView,更改适配器基类类型,然后为数据创建一个或多个处理程序。 - Gary Bak
我已经做到了,但是现在我在RecycleView中滚动,我不想滚动,我已经使用了ScrollView,是否可能移除滚动? - Fra87
我已经解决了滚动问题,我的适配器是RecyclerView.Adapter,如果我想要一个返回特定位置项目的方法,我该怎么做? - Fra87
我想在RecyclerView.Adapter中创建自定义的delete方法,但我有一个疑问,在我从ArrayList中删除项目之后,我是调用notifyDataSetChanged()还是notifyItemRemoved()? - Fra87
删除操作可能是更好的选择,这样适配器就知道它必须重新绘制哪些位置。notifyDataSetChanged将强制它重新绘制屏幕上的任何内容。 - Gary Bak
显示剩余3条评论

1

2
此存储库已被弃用。 - zypro

1

使用ListAdapter的Kotlin版本

所有的功劳归于这篇博客文章: https://theeasiestwayy.medium.com/listadapter-and-swipe-to-delete-741e32e5f824(其中代码示例有几个错别字)

abstract class ListAdapterSwipeable <T, VH: RecyclerView.ViewHolder>(
    diffCallback: DiffUtil.ItemCallback<T>
): ListAdapter<T, VH>(diffCallback) {

    private val removedItems: MutableList<T> = mutableListOf()

    fun removeItem(position: Int): T? {
        if (position >= itemCount) return null
        val item = currentList[position]
        removedItems.add(item)
        val actualList = currentList - removedItems
        if (actualList.isEmpty()) removedItems.clear()
        submit(actualList, true)
        return item
    }

    private fun submit(list: List<T>?, isLocalSubmit: Boolean) {
        if (!isLocalSubmit) removedItems.clear()
        super.submitList(list)
    }

    @CallSuper
    override fun submitList(list: List<T>?) {
        submit(list, false)
    }
}

class ItemSwipeHandler<T>(
    private val adapter: ListAdapterSwipeable<T, *>,
    private val onItemRemoved: ((item: T) -> Unit)? = null
) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {

    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
//        val position = viewHolder.adapterPosition  DEPRECATED!!
        val position = viewHolder.bindingAdapterPosition
        val item = adapter.removeItem(position) ?: return
        onItemRemoved?.invoke(item)
    }

    override fun onMove(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder,
        target: RecyclerView.ViewHolder
    ): Boolean = false
}

更多关于它的使用方法,请参阅上面的博客文章


1

已接受的答案翻译为 Kotlin:

val itemTouchHelper =  ItemTouchHelper(object: ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
    override fun onMove(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder,
        target: RecyclerView.ViewHolder
    ): Boolean {
        TODO("Not yet implemented")
    }

    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
            todoListAdapter.notifyDataSetChanged()
    }

})
this.runOnUiThread {
    itemTouchHelper.attachToRecyclerView(recyclerView)
}

-4
我发现最简单的方法是在StatefullWidget中使用ListView.builder,并将子元素包装在Dismissible组件中:
ListView.builder(
  itemCount: sampleList.length, //number of items on the list
  itemBuilder: (BuildContext context, int index) {
      return Dismissible(
        key: Key(sampleList[index]), //unique key string for each element (in this case each string is unique)
        onDismissed: (direction) {
          setState(() {
            sampleList.removeAt(index); //remove list element at given index and repaint
          });
        },
        child: child: Text('${sampleList[index]}'), //what to display form the list
      );
  },
);

您可以检查/复制下面的代码作为一个工作示例,并将其作为子组件传递:

import 'package:flutter/material.dart';

class DismissibleList extends StatefulWidget {
  @override
  _DismissibleListState createState() => _DismissibleListState();
}

class _DismissibleListState extends State<DismissibleList> {
  @override
  Widget build(BuildContext context) {
    List<String> sampleList = ['aa', 'bb', 'cc']; // the list of elements
    return ListView.builder(
        itemCount: sampleList.length, //number of items on the list
        itemBuilder: (BuildContext context, int index) {
            return Dismissible(
              key: Key(sampleList[index]), //unique key string for each element (in this case each string is unique)
              onDismissed: (direction) {
                setState(() {
                  sampleList.removeAt(index); //remove list element at given index and repaint
                });
              },
              child: child: Padding(
                padding: EdgeInsets.all(16.0), // just to help the visual
                child: Text('${sampleList[index]}'),
              ) //what to display form the list
            );
        },
      );
  }
}

这是关于Flutter的答案。然而,问题针对原生Android。 - Bennik2000

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接