使用 ItemTouchHelper.SimpleCallback 禁用滑动查看 RecyclerView 中的位置
Disable Swipe for position in RecyclerView using ItemTouchHelper.SimpleCallback
我正在使用 recyclerview 22.2.0 和助手 class ItemTouchHelper.SimpleCallback 来为我的列表启用 swipe-to-dismiss 选项。但是因为我上面有一个 header 类型,所以我需要禁用适配器第一个位置的滑动行为。由于 RecyclerView.Adapter 没有 isEnabled() 方法,我试图通过方法禁用视图交互 isEnabled() 和 isFocusable() 在 ViewHolder 创建本身,但没有成功。我尝试将滑动阈值调整为完整值,例如 SimpleCallback 方法 getSwipeThreshold()[= 中的 0f ot 1f 33=],但也没有成功。
我的一些代码片段希望大家帮帮我。
我的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);
}
我有一个带有 两种 视图类型的通用适配器。在我想禁用滑动的 ViewHolder 中,我做了:
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);
}
}
玩了一会儿后,我发现 SimpleCallback 有一个名为 getSwipeDirs() 的方法。由于我有一个特定的 ViewHolder 用于 not swipable 位置,我可以使用 instanceof 来避免滑动。如果不是您的情况,您可以使用 Adapter 中 ViewHolder 的位置来执行此控制。
Java
@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
if (viewHolder instanceof CartAdapter.MyViewHolder) return 0;
return super.getSwipeDirs(recyclerView, viewHolder);
}
Kotlin
override fun getSwipeDirs (recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
if (viewHolder is CartAdapter.MyViewHolder) return 0
return super.getSwipeDirs(recyclerView, viewHolder)
}
如果有人在使用 ItemTouchHelper.Callback。然后您可以删除 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);
}
在这里代替 dragFlags 和 swipeFlags 你可以传递 0 来禁用相应的功能。
ItemTouchHelper.START 表示在从左到右语言环境(LTR 应用程序支持)的情况下从左向右滑动,但在从右到左语言环境中则相反( RTL 应用程序支持)。
ItemTouchHelper.END表示向START
相反的方向滑动。
因此您可以根据需要删除任何标志。
有几种方法可以解决这个问题,但如果您只有一个 ViewHolder,但有多个布局,您可以采用这种方法。
覆盖 getItemViewType 并为其提供一些逻辑,以根据 object 中的位置或数据类型确定视图类型(我的 object 中有一个 getType 函数)
@Override
public int getItemViewType(int position) {
return data.get(position).getType;
}
Return onCreateView 中基于 ViewType 的正确布局(确保将视图类型传递给 ViewHolder class。
@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);
}
}
根据视图类型获取不同布局的内容视图
public 静态 class AppListItemHolder 扩展 RecyclerView.ViewHolder {
public AppListItemHolder (View v, int viewType) {
super(v);
if (viewType == 0)
... get your views contents
else
... get other views contents
}
}
}
然后在您的 ItemTouchHelper 中根据 ViewType 更改操作。对我来说,这会禁用 RecyclerView 部分的滑动 header
@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
if (viewHolder.getItemViewType() == 1) return 0;
return super.getSwipeDirs(recyclerView, viewHolder);
}
}
这是一种简单的方法,它只取决于被滑动项目的位置:
@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
值从适配器获取数据以用于被刷卡的项目并相应地禁用。
如果您已经有不需要刷卡的特定持有人类型,接受的答案将有效。但是,创建持有人类型作为头寸的代理是一个错误,应该避免。
首先在recyclerView的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;
}
}
最后附加到 recyclerView:
final SwipeController swipeController = new SwipeController();
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(swipeController);
itemTouchHelper.attachToRecyclerView(recyclerView);
除了@Rafael Toledo 的回答之外,如果您想根据 Adapter 中对象中数据的位置或类型删除特定的滑动手势,如向左滑动或向右滑动,那么您可以这样做。
@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;
}
在我的例子中,在我的 Recyclerview 中,我正在加载聊天对话,它在每个项目上都有右(用于存档)和左(用于退出)滑动手势。但是如果对话不活跃,那么我需要在 Recycler 视图中禁用特定项目的右滑动。
所以我正在检查 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)
我正在使用 recyclerview 22.2.0 和助手 class ItemTouchHelper.SimpleCallback 来为我的列表启用 swipe-to-dismiss 选项。但是因为我上面有一个 header 类型,所以我需要禁用适配器第一个位置的滑动行为。由于 RecyclerView.Adapter 没有 isEnabled() 方法,我试图通过方法禁用视图交互 isEnabled() 和 isFocusable() 在 ViewHolder 创建本身,但没有成功。我尝试将滑动阈值调整为完整值,例如 SimpleCallback 方法 getSwipeThreshold()[= 中的 0f ot 1f 33=],但也没有成功。
我的一些代码片段希望大家帮帮我。
我的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);
}
我有一个带有 两种 视图类型的通用适配器。在我想禁用滑动的 ViewHolder 中,我做了:
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);
}
}
玩了一会儿后,我发现 SimpleCallback 有一个名为 getSwipeDirs() 的方法。由于我有一个特定的 ViewHolder 用于 not swipable 位置,我可以使用 instanceof 来避免滑动。如果不是您的情况,您可以使用 Adapter 中 ViewHolder 的位置来执行此控制。
Java
@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
if (viewHolder instanceof CartAdapter.MyViewHolder) return 0;
return super.getSwipeDirs(recyclerView, viewHolder);
}
Kotlin
override fun getSwipeDirs (recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
if (viewHolder is CartAdapter.MyViewHolder) return 0
return super.getSwipeDirs(recyclerView, viewHolder)
}
如果有人在使用 ItemTouchHelper.Callback。然后您可以删除 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);
}
在这里代替 dragFlags 和 swipeFlags 你可以传递 0 来禁用相应的功能。
ItemTouchHelper.START 表示在从左到右语言环境(LTR 应用程序支持)的情况下从左向右滑动,但在从右到左语言环境中则相反( RTL 应用程序支持)。
ItemTouchHelper.END表示向START
相反的方向滑动。
因此您可以根据需要删除任何标志。
有几种方法可以解决这个问题,但如果您只有一个 ViewHolder,但有多个布局,您可以采用这种方法。
覆盖 getItemViewType 并为其提供一些逻辑,以根据 object 中的位置或数据类型确定视图类型(我的 object 中有一个 getType 函数)
@Override
public int getItemViewType(int position) {
return data.get(position).getType;
}
Return onCreateView 中基于 ViewType 的正确布局(确保将视图类型传递给 ViewHolder class。
@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);
}
}
根据视图类型获取不同布局的内容视图 public 静态 class AppListItemHolder 扩展 RecyclerView.ViewHolder {
public AppListItemHolder (View v, int viewType) {
super(v);
if (viewType == 0)
... get your views contents
else
... get other views contents
}
}
}
然后在您的 ItemTouchHelper 中根据 ViewType 更改操作。对我来说,这会禁用 RecyclerView 部分的滑动 header
@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
if (viewHolder.getItemViewType() == 1) return 0;
return super.getSwipeDirs(recyclerView, viewHolder);
}
}
这是一种简单的方法,它只取决于被滑动项目的位置:
@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
值从适配器获取数据以用于被刷卡的项目并相应地禁用。
如果您已经有不需要刷卡的特定持有人类型,接受的答案将有效。但是,创建持有人类型作为头寸的代理是一个错误,应该避免。
首先在recyclerView的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;
}
}
最后附加到 recyclerView:
final SwipeController swipeController = new SwipeController();
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(swipeController);
itemTouchHelper.attachToRecyclerView(recyclerView);
除了@Rafael Toledo 的回答之外,如果您想根据 Adapter 中对象中数据的位置或类型删除特定的滑动手势,如向左滑动或向右滑动,那么您可以这样做。
@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;
}
在我的例子中,在我的 Recyclerview 中,我正在加载聊天对话,它在每个项目上都有右(用于存档)和左(用于退出)滑动手势。但是如果对话不活跃,那么我需要在 Recycler 视图中禁用特定项目的右滑动。
所以我正在检查 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)