Отключить прокрутку для позиции в RecyclerView с помощью ItemTouchHelper.SimpleCallback
Я использую recyclerview 22.2.0 и вспомогательный класс ItemTouchHelper.SimpleCallback, чтобы включить опцию swipe-to-reject в моем списке. Но поскольку у меня есть тип заголовка, мне нужно отключить поведение салфетки для первой позиции адаптера. Поскольку RecyclerView.Adapter не имеет метода 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);
}
}
Ответы
Ответ 1
После небольшого воспроизведения мне удалось, что SimpleCallback имеет метод getSwipeDirs(). Поскольку у меня есть определенный ViewHolder для неперемещаемой позиции, я могу использовать экземпляр, чтобы избежать прокрутки. Если это не ваше дело, вы можете выполнить этот контроль, используя положение ViewHolder в адаптере.
@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
if (viewHolder instanceof CartAdapter.MyViewHolder) return 0;
return super.getSwipeDirs(recyclerView, viewHolder);
}
Ответ 2
Если кто-то использует 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
.
чтобы вы могли удалить любой флаг в соответствии с вашими требованиями.
Ответ 3
Вот простой способ сделать это, который зависит только от положения предмета, проведенного пальцем:
@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
чтобы получить данные от адаптера для предмета, подлежащего прокрутке, и отключите его соответствующим образом.
Если у вас уже есть определенные типы держателей, которые не нужно проводить, принятый ответ будет работать. Однако создание типов держателей в качестве прокси для позиции является препятствием, и его следует избегать.
Ответ 4
Есть несколько способов сделать это, но если у вас есть только один 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);
}
}
Получить представления контента различных макетов на основе типа представления 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);
}
}
Ответ 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;
}
}
затем в реализации 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);
Ответ 6
В дополнение к ответу @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
и соответственно и отключил ПРАВОЙ пролистывание.
Ответ 7
Спасибо за ответ, я боролась больше часа, чтобы найти решение. оно работает!