使用ItemTouchHelper.SimpleCallback禁用在RecyclerView中滑动位置

时间:2015-06-08 15:22:43

标签: android android-recyclerview

我正在使用recyclerview 22.2.0和帮助程序类ItemTouchHelper.SimpleCallback来启用 swipe-to-dismiss 选项到我的列表中。但由于我有一种类型的标题,我需要禁用适配器的第一个位置的滑动行为。由于 RecyclerView.Adapter 没有 isEnabled()方法,我尝试通过 isEnabled()方法禁用视图互动ViewHolder创建本身中的 isFocusable(),但没有成功。我尝试将滑动阈值调整为完整值,例如SimpleCallback的方法 getSwipeThreshold()中的 0f ot 1f ,但是也没有成功。

我的代码的一些片段可以帮助你帮助我。

我的活动:

@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);      
    }
}

6 个答案:

答案 0 :(得分:151)

在玩了一下后,我设法 SimpleCallback 有一个名为 getSwipeDirs()的方法。由于我有 not swipable 位置的特定ViewHolder,我可以使用 instanceof 来避免滑动。如果不是这种情况,您可以使用适配器中ViewHolder的位置执行此控制。

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

答案 1 :(得分:58)

如果有人使用 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的相反方向滑动。

因此您可以根据自己的要求删除任何标记。

答案 2 :(得分:18)

这是一种简单的方法,只取决于被刷物品的位置:

@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值从适配器获取要刷过的项目的数据并相应地禁用。

如果您已经有特定的持有人类型需要不刷卡,则接受的答案将起作用。但是,创建持有人类型作为头寸的代理是一种风险,应该避免。

答案 3 :(得分:5)

有几种方法可以解决这个问题,但是如果你只有一个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);
    }
}

根据视图类型获取不同布局的内容视图     public static 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部分标题

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

答案 4 :(得分:1)

除了@Rafael Toledo答案之外,如果你想根据适配器中对象中的数据位置或类型删除特定的滑动手势,如LEFT滑动或RIGHT滑动,那么你可以这样做。

@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中,我正在加载聊天对话,它有正确(对于ARCHIVE)& LEFT(用于退出)在每个项目上滑动手势。但是如果对话未激活,那么我需要在Recycler视图中禁用RIGHT滑动特定项目。

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

希望它对某人有帮助。 “ 干杯!!

答案 5 :(得分:0)

可以使用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)