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

Raf*_*edo 78 android android-recyclerview

我正在使用recyclelerview 22.2.0和帮助程序类ItemTouchHelper.SimpleCallback来启用我的列表中的轻扫到解除选项.但由于我有一种类型的标题,我需要禁用适配器的第一个位置的滑动行为.由于RecyclerView.Adapter没有isEnabled()方法,我尝试通过ViewHolder创建本身中的方法isEnabled()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);
}
Run Code Online (Sandbox Code Playgroud)

我有一个具有两种视图类型的通用适配器.在我要禁用刷卡的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);      
    }
}
Run Code Online (Sandbox Code Playgroud)

Raf*_*edo 166

在玩了一下之后,我设法说SimpleCallback有一个名为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);
}
Run Code Online (Sandbox Code Playgroud)

  • 正是我一直在寻找的东西!特别是当这个方法没有出现在[官方文档](http://developer.android.com/reference/android/support/v7/widget/helper/ItemTouchHelper.Callback.html)... (2认同)
  • 值得一提的是:如果你只想在某些项目上允许一个方向,那么使用`return position == 0?ItemTouchHelper.LEFT:super.getSwipeDirs(recyclerView,viewHolder);` - 这个只允许左滑动. (2认同)

Muh*_*dil 66

如果有人正在使用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);
}
Run Code Online (Sandbox Code Playgroud)

这里代替dragFlagsswipeFlags你可以传递0来禁用相应的功能.

ItemTouchHelper.START表示从左到右区域设置(LTR应用程序支持)从左向右滑动,但从右到左区域设置(RTL应用程序支持)则相反. ItemTouchHelper.END表示向相反方向滑动START.

所以你可以根据你的要求删除任何标志.


Rob*_*ore 19

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

@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;
}
Run Code Online (Sandbox Code Playgroud)

如果您正在使用,这也应该有效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);
}
Run Code Online (Sandbox Code Playgroud)

如果要根据项目中的数据禁用滑动条件,请使用该position值从适配器获取正在刷新的项目的数据并相应地禁用.

如果您已经具有不需要滑动的特定持有者类型,则接受的答案将起作用.但是,创建持有人类型作为头寸的代理是一个障碍,应该避免.


小智 5

有几种方法可以解决这个问题,但是如果你只有一个ViewHolder,但是你可以使用这种方法.

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

@Override
public int getItemViewType(int position) {
    return data.get(position).getType;
}
Run Code Online (Sandbox Code Playgroud)

基于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);
    }
}
Run Code Online (Sandbox Code Playgroud)

基于视图类型获取不同布局的内容视图public static class AppListItemHolder extends RecyclerView.ViewHolder {

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

        if (viewType == 0)
            ... get your views contents
        else
            ... get other views contents
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在您的ItemTouchHelper中根据ViewType更改操作.对我来说,这会禁用刷新RecyclerView部分标题

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


M.K*_*chi 5

首先在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;
    }
} 
Run Code Online (Sandbox Code Playgroud)

然后在 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

最后附加到recyclerView:

final SwipeController swipeController = new SwipeController();

    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(swipeController);
    itemTouchHelper.attachToRecyclerView(recyclerView);
Run Code Online (Sandbox Code Playgroud)