Подтвердить что ты не робот

Отключить прокрутку для позиции в 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);      
    }
}
4b9b3361

Ответ 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

Спасибо за ответ, я боролась больше часа, чтобы найти решение. оно работает!