Отключите салфетки для позиции в RecyclerView с помощью ItemTouchHelper.SimpleCallback
Я использую recyclerview 22.2.0 и вспомогательный класс ItemTouchHelper.SimpleCallback для включения swipe-to-dismiss в моем списке. Но поскольку у меня есть тип заголовка на нем, мне нужно отключить поведение салфетки для первой позиции адаптера. Как RecyclerView.Адаптер нет isEnabled () метод, я попытался отключить взаимодействие с видом через методы isEnabled () и isFocusable() в Само создание ViewHolder, но не имело успеха. Я попытался настроить порог салфетки на полное значение, например 0f ot 1f в методе SimpleCallback getSwipeThreshold(), но и без успеха тоже.
некоторые фрагменты моего кода, чтобы помочь вам помочь мне.
Мои Действия:
@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 ответов:
поиграв немного, мне это удалось 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); }
Если кто-то использует ItemTouchHelper.Обратный вызов. Затем вы можете удалить все связанные флаги в getMovementFlags(..)
вот простой способ сделать это, который зависит только от положения элемента свистнул:
@Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder holder) { int position = holder.getAdapterPosition(); int dragFlags = 0; // whatever your dragFlags need to be int swipeFlags = position == 0 ? 0 : ItemTouchHelper.START | ItemTouchHelper.END; return makeMovementFlags(dragFlags, swipeFlags); }
Это также должно работать, если вы используете
SimpleCallback
:@Override public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder holder) { int position = holder.getAdapterPosition(); return position == 0 ? 0 : super.getSwipeDirs(recyclerView, viewHolder); }
лучше ли это, чем другие ответы, зависит от ваших потребностей.
- если вы просто хотите отключить на основе позиции, используйте этот подход.
- если swipe-способность зависит от данных для элемента, то вы можете использовать этот подход. Используйте
position
значение для получения данных от адаптера для элемента, который считывается и отключается соответственно.- если у вас есть определенные типы держателей, которые не нужно прокручивать, принятый ответ будет работать.
есть несколько способов сделать это, но если у вас есть только один ViewHolder, но более одного макета, вы можете использовать этот подход.
переопределите getItemViewType и дайте ему некоторую логику, чтобы определить тип представления на основе позиции или типа данных в объекте (у меня есть функция getType в моем объекте)
@Override public int getItemViewType(int position) { return data.get(position).getType; }
возвращает правильный макет в onCreateView на основе ViewType (обязательно передайте тип представления классу 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); } }
получить содержание виды различных компоновок в зависимости от типа вида открытый статический класс 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); } }
в дополнение к ответу @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; }
здесь, в моем случае, в моем Recyclerview я загружаю разговоры в чате, и у него есть правые ( для архива) и левые ( для выхода) жесты салфетки на каждом элементе. Но в случае, если разговор не активен, то мне нужно отключить правый свайп для конкретного элемент в представлении Recycler.
поэтому я проверяю activeChat и, соответственно, отключил правый свайп.
надеюсь, что это поможет кому-то. " Ура !!
сначала в 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.Реализация обратного вызова, обновление 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);