Disable Swipe for position in RecyclerView using ItemTouchHelper.SimpleCallback

I am using recyclerview 22.2.0 and the helper class ItemTouchHelper.SimpleCallback to enable swipe-to-dismiss option to my list. But as I have a type of header on it, I need to disable the swipe behavior for the first position of the adapter. As RecyclerView.Adapter doesn't have a isEnabled() method, I tried to disable the view interaction through the methods isEnabled() and isFocusable() in the ViewHolder creation itself, but had no success. I tried to adjust the swipe threshold to a full value, like 0f ot 1f in the SimpleCallback's method getSwipeThreshold(), but no success too.

Some fragments of my code to help you to help me.

My Activity:

@Override
protected void onCreate(Bundle bundle) {
//... initialization
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0,
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {


@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
RecyclerView.ViewHolder target) {
return false;
}


@Override
public float getSwipeThreshold(RecyclerView.ViewHolder viewHolder) {
if (viewHolder instanceof CartAdapter.MyViewHolder) return 1f;
return super.getSwipeThreshold(viewHolder);
}


@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {


}
};


ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
itemTouchHelper.attachToRecyclerView(recyclerView);
}

And I have a common adapter with two view types. In the ViewHolder that I want to disable swiping, I did:

public static class MyViewHolder extends RecyclerView.ViewHolder {
public ViewGroup mContainer;


public MyViewHolder(View v) {
super(v);
v.setFocusable(false);
v.setEnabled(false);
mContainer = (ViewGroup) v.findViewById(R.id.container);
}
}
49991 次浏览

玩了一会儿之后,我设法使 简单回拨有一个名为 GetSwipeDirs ()的方法。因为我有一个特定的 不能偷位置的 ViewHolder,我可以利用 Instanceof来避免滑动。如果不是这种情况,可以使用 ViewHolder 在适配器中的位置来执行此控件。

爪哇咖啡

@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
if (viewHolder instanceof CartAdapter.MyViewHolder) return 0;
return super.getSwipeDirs(recyclerView, viewHolder);
}

科特林

override fun getSwipeDirs (recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
if (viewHolder is CartAdapter.MyViewHolder) return 0
return super.getSwipeDirs(recyclerView, viewHolder)
}

如果有人正在使用 项目触摸助手。回调,那么您可以删除 GetMovementFlags (. .)函数中的任何相关标志。

@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(dragFlags, swipeFlags);
}

在这里,你可以传递0来禁用相应的特性,而不是 拖旗滑动标志

ItemTouchHelper.START means swiping left to right in case of left to right locale (LTR application Support), but the other way around in a right to left locale (RTL application Support). END 表示在 START的相反方向上滑动。

所以你可以根据你的要求去掉任何标志。

有几种方法可以实现这一点,但是如果您只有一个 ViewHolder,但是有多个布局,则可以采用这种方法。

重写 getItemViewType 并给它一些逻辑,以根据对象中数据的位置或类型确定视图类型(我的对象中有一个 getType 函数)

@Override
public int getItemViewType(int position) {
return data.get(position).getType;
}

返回基于 ViewType 的 onCreateView 中的正确布局(确保将视图类型传递给 ViewHolder 类。

@Override
public AppListItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
mContext = parent.getContext();


if (viewType == 0){
return new AppListItemHolder(LayoutInflater.from(mContext).inflate(R.layout.layout, parent, false), viewType);
else
return new AppListItemHolder(LayoutInflater.from(mContext).inflate(R.layout.header, parent, false), viewType);
}
}

Get the content views of the different layouts based on view type 公共静态类 AppListItemHolder 扩展回收视图

    public AppListItemHolder (View v, int viewType) {
super(v);


if (viewType == 0)
... get your views contents
else
... get other views contents
}
}
}

然后在 ItemTouchHelper 中基于 ViewType 更改操作

@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
if (viewHolder.getItemViewType() == 1) return 0;
return super.getSwipeDirs(recyclerView, viewHolder);
}
}

Here's a simple way to do this that only depends upon the position of the item being swiped:

@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder holder) {
int position = holder.getAdapterPosition();
int dragFlags = 0; // whatever your dragFlags need to be
int swipeFlags = createSwipeFlags(position)


return makeMovementFlags(dragFlags, swipeFlags);
}


private int createSwipeFlags(int position) {
return position == 0 ? 0 : ItemTouchHelper.START | ItemTouchHelper.END;
}

如果你正在使用 SimpleCallback,这也应该起作用:

@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder holder) {
int position = holder.getAdapterPosition();
return createSwipeFlags(position);
}


private int createSwipeFlags(int position) {
return position == 0 ? 0 : super.getSwipeDirs(recyclerView, viewHolder);
}

如果希望禁用对项中数据的条件刷新,请使用 position值从适配器获取要刷新的项的数据,然后相应地禁用。

如果您已经有特定的持有人类型,不需要刷卡,接受的答案将工作。然而,创建持有者类型作为位置的代理是一个组合,应该避免。

首先在回收视图 onCreateViewHolder 方法中,为每个 viewHolder 类型设置标记,如下面的代码所示:

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
if(ITEM_TYPE_NORMAL == viewType) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.deposite_card_view, viewGroup, false);
ItemViewHolder holder = new ItemViewHolder(context, v);
holder.itemView.setTag("normal");
return holder;
} else {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_header, viewGroup, false);
HeaderViewHolder holder = new HeaderViewHolder(context, v);
holder.itemView.setTag("header");
return holder;
}
}

然后在 ItemTouchHelper.Callback 实现中,更新 getMovementFlags 方法,如下所示:

public class SwipeController extends ItemTouchHelper.Callback {


@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
if("normal".equalsIgnoreCase((String) viewHolder.itemView.getTag())) {
return makeMovementFlags(0, LEFT | RIGHT);
} else {
return 0;
}
}

附于回收站查看:

final SwipeController swipeController = new SwipeController();


ItemTouchHelper itemTouchHelper = new ItemTouchHelper(swipeController);
itemTouchHelper.attachToRecyclerView(recyclerView);

除了@Rafael Toledo 的回答,如果你想删除特定的滑动手势,如左滑动或右滑动基于位置或类型的数据在适配器中的对象,然后你可以这样做。

@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)
{
int position = viewHolder.getAdapterPosition();
ConversationDataModel conversationModel = null;
conversationModel = mHomeAdapter.getItems().get(position);
boolean activeChat = true;
if(conversationModel!=null && !conversationModel.isActive())
{
activeChat = false;
}
return activeChat ? super.getSwipeDirs(recyclerView, viewHolder): ItemTouchHelper.RIGHT;
}

Here in my case, In my Recyclerview I am loading the chat conversations and it have RIGHT (for ARCHIVE) & LEFT ( for EXIT) swipe gestures on each item. But in case if the conversation is not active, then I need to disable the RIGHT swipe for the specific item in the Recycler view.

所以我正在检查 activeChat,并相应地禁用了右滑动。

可以使用 ItemTouchHelper.ACTION_STATE_IDLE禁用它

ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP or ItemTouchHelper.DOWN, //drag directions
ItemTouchHelper.ACTION_STATE_IDLE //swipe directions
)
val touchHelperCallback = object : ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP or ItemTouchHelper.DOWN, ItemTouchHelper.ACTION_STATE_IDLE) {
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
(recyclerView.adapter as MyAdapter).onItemMove(viewHolder.adapterPosition, target.adapterPosition)
return true
}


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


}
val touchHelper = ItemTouchHelper(touchHelperCallback)
touchHelper.attachToRecyclerView(recyclerViewX)