Używam recyclinglerview 22.2.0 i klasy pomocniczej ItemTouchHelper.SimpleCallback, aby włączyć opcję przeciągnij, aby odrzucić do mojej listy. Ale ponieważ mam na nim typ nagłówka, muszę wyłączyć zachowanie przesuwania dla pierwszej pozycji adaptera. Ponieważ RecyclerView.Adapter nie ma metody isEnabled () , próbowałem wyłączyć interakcję widoku za pomocą metod isEnabled () i isFocusable () w samym tworzeniu ViewHolder, ale bez powodzenia. Próbowałem ustawić próg przesunięcia na pełną wartość, na przykład 0f ot 1f w metodzie getSwipeThreshold () SimpleCallback , ale również bez sukcesu.
Kilka fragmentów mojego kodu, które pomogą Ci mi pomóc.
Moja aktywność:
@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);
}
Mam wspólny adapter z dwoma typami widoku. W ViewHolder, który chcę wyłączyć przesuwanie, zrobiłem:
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);
}
}
źródło
SimpleCallback
developer.android.com/intl/pt-br/reference/android/support/v7/…return position == 0 ? ItemTouchHelper.LEFT : super.getSwipeDirs(recyclerView, viewHolder);
- ten, tj. Zezwalaj tylko na przesunięcia w lewo.Jeśli ktoś używa ItemTouchHelper.Callback . Następnie możesz usunąć wszelkie powiązane flagi w funkcji 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); }
Tutaj zamiast dragFlags i swipeFlags Możesz przekazać 0, aby wyłączyć odpowiednią funkcję.
ItemTouchHelper.START oznacza przesuwanie od lewej do prawej w przypadku ustawienia regionalnego od lewej do prawej (obsługa aplikacji LTR), ale na odwrót w ustawieniu od prawej do lewej (obsługa aplikacji RTL). ItemTouchHelper.END oznacza przesunięcie w kierunku przeciwnym do
START
.więc możesz usunąć dowolną flagę zgodnie z własnymi wymaganiami.
źródło
ItemTouchHelper.Callback
bezpośrednio.Oto prosty sposób na zrobienie tego, który zależy tylko od pozycji przesuwanego elementu:
@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; }
Powinno to również działać, jeśli używasz
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); }
Jeśli chcesz wyłączyć przesuwanie w zależności od danych w elemencie, użyj
position
wartości, aby pobrać dane z adaptera dla elementu, który ma być przesuwany, i wyłącz odpowiednio.Jeśli masz już określone typy uchwytów, których nie trzeba przesuwać, zaakceptowana odpowiedź będzie działać. Jednak tworzenie typów posiadaczy jako zastępczych dla pozycji jest niewygodne i należy tego unikać.
źródło
Jest na to kilka sposobów, ale jeśli masz tylko jeden ViewHolder, ale więcej niż jeden układ, możesz zastosować to podejście.
Zastąp getItemViewType i nadaj mu logikę, aby określić typ widoku na podstawie pozycji lub typu danych w obiekcie (mam funkcję getType w moim obiekcie)
@Override public int getItemViewType(int position) { return data.get(position).getType; }
Zwróć właściwy układ w onCreateView na podstawie ViewType (upewnij się, że typ widoku został przekazany do klasy 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); } }
Uzyskaj widoki zawartości różnych układów na podstawie typu widoku publiczna klasa statyczna AppListItemHolder rozszerza RecyclerView.ViewHolder {
public AppListItemHolder (View v, int viewType) { super(v); if (viewType == 0) ... get your views contents else ... get other views contents } } }
A następnie w akcjach zmiany ItemTouchHelper na podstawie ViewType. Dla mnie to wyłącza przesuwanie nagłówka sekcji RecyclerView
@Override public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { if (viewHolder.getItemViewType() == 1) return 0; return super.getSwipeDirs(recyclerView, viewHolder); } }
źródło
Najpierw w recyclinglerView w metodzie onCreateViewHolder, ustaw tag dla każdego typu viewHolder, jak poniżej:
@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; } }
następnie w implementacji ItemTouchHelper.Callback zaktualizuj metodę getMovementFlags, jak poniżej:
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; } }
na końcu dołącz do recyclinglerView:
final SwipeController swipeController = new SwipeController(); ItemTouchHelper itemTouchHelper = new ItemTouchHelper(swipeController); itemTouchHelper.attachToRecyclerView(recyclerView);
źródło
Oprócz odpowiedzi @Rafael Toledo, jeśli chcesz usunąć określony gest machnięcia, taki jak przesunięcie w LEWO lub przesunięcie w PRAWO, na podstawie pozycji lub typu danych w obiekcie w adapterze, możesz to zrobić.
@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; }
Tutaj, w moim przypadku, w moim Recyclerview ładuję rozmowy na czacie i mam gesty przesuwania w PRAWO (dla ARCHIWUM) i W LEWO (dla WYJŚCIA) na każdym elemencie. Ale w przypadku, gdy rozmowa nie jest aktywna, muszę wyłączyć przesuwanie w PRAWO dla określonego elementu w widoku Recycler.
Więc sprawdzam
activeChat
i odpowiednio i wyłączam przesunięcie w PRAWO.źródło
Można go wyłączyć za pomocą
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)
źródło