2015-06-08 2 views
53

Ich benutze Recyclerview 22.2.0 und die Helper-Klasse ItemTouchHelper.SimpleCallback zu aktivieren swipe-to-entlassen Option zu meiner Liste. Aber da ich eine Art Header habe, muss ich das Wischverhalten für die erste Position des Adapters deaktivieren. Wie RecyclerView.Adapter keine isEnabled() Methode habe ich versucht, die Ansicht Interaktion durch die Methoden isEnabled() und isFocusable() in der ViewHolder Schöpfung selbst, hatte aber keinen Erfolg zu deaktivieren. Ich habe versucht, die Swipe-Schwelle auf einen vollen Wert, wie 0f1f in der SimpleCallback-Methode getSwipeThreshold(), aber auch keinen Erfolg.Deaktivieren Swipe für die Position in RecyclerView mit ItemTouchHelper.SimpleCallback

Einige Fragmente meines Codes, um Ihnen zu helfen, mir zu helfen.

Meine Aktivität:

@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); 
} 

Und ich habe einen gemeinsamen Adapter mit zwei Ansichtstypen. Im ViewHolder, die ich klauen deaktivieren wollen, ich habe:

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);  
    } 
} 

Antwort

118

Nach dem Spiel ein wenig, ich es geschafft, dass SimpleCallback ein Verfahren getSwipeDirs() genannt hat. Da ich einen speziellen ViewHolder für die nicht swipable Position habe, kann ich instanceof verwenden, um den Swipe zu vermeiden. Wenn dies nicht der Fall ist, können Sie dieses Steuerelement mithilfe der Position von ViewHolder im Adapter ausführen.

@Override 
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { 
    if (viewHolder instanceof CartAdapter.MyViewHolder) return 0; 
    return super.getSwipeDirs(recyclerView, viewHolder); 
} 
+0

Genau das, was ich gesucht habe! Vor allem, wenn diese Methode nicht auf der [offiziellen Dokumentation] (http://developer.android.com/reference/android/support/v7/widget/helper/ItemTouchHelper.Callback.html) erscheint ... – ptitvinou

+1

@ptitvinou ist es vorhanden auf 'SimpleCallback' http://developer.android.com/intl/pt-br/reference/android/support/v7/widget/helper/ItemTouchHelper.SimpleCallback.html –

+1

Erwähnenswert: wenn Sie nur für eine Richtung zulassen möchten bei bestimmten Artikeln dann 'return position == 0? ItemTouchHelper.LEFT: super.getSwipeDirs (recyclerView, viewHolder); '- dies erlaubt nur für Links wischen. –

45

Wenn jemand ItemTouchHelper.Callback verwenden. Dann können Sie alle zugehörigen Flags in getMovementFlags (..) Funktion entfernen.

@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); 
} 

hier statt dragFlags und swipeFlags Sie haben 0 passieren kann entsprechende Funktion zu deaktivieren.

ItemTouchHelper.START Mittel Streich nach von links nach rechts locale falls links nach rechts (LTR Anwendung Support), aber umgekehrt in einem von rechts nach links locale (RTL Anwendung Support). ItemTouchHelper.END bedeutet Wischen in die entgegengesetzte Richtung von START.

so können Sie jede Flagge nach Ihren Anforderungen entfernen.

+0

Vielen Dank! Ich verwende den Code: @Override public int getMovementFlags (RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; // Bewegungen ziehen return makeFlag (ItemTouchHelper.ACTION_STATE_DRAG, dragFlags); // als Parameter, Aktion ziehen und Flags ziehen } –

+0

Dies ist die bevorzugte Antwort, wenn Sie (im Gegensatz zu OP) 'ItemTouchHelper.Callback' direkt erweitern. – tir38

4

Es gibt einige Möglichkeiten, dies zu tun, aber wenn Sie nur einen ViewHolder, aber mehr als ein Layout haben, können Sie diesen Ansatz verwenden.

die getItemViewType außer Kraft setzen und ihm eine gewisse Logik geben als Ansichtstyp in Objekt basierend auf Position oder die Art der Daten zu bestimmen (Ich habe eine getType Funktion in meinem Objekt)

@Override 
public int getItemViewType(int position) { 
    return data.get(position).getType; 
} 

Return richtiges Layout in onCreateView basierend auf Viewtype (Achten Sie darauf, Ansicht Typen ViewHolder Klasse zu übergeben.

@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); 
    } 
} 

den Inhalt Blick auf die verschiedenen Layouts auf Basis von Ansichtstyp public static Klasse Get AppListItemHolder erstreckt RecyclerView.ViewHolder {

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

     if (viewType == 0) 
      ... get your views contents 
     else 
      ... get other views contents 
     } 
    } 
} 

Und dann in Ihrem ItemTouchHelper Aktionen basierend auf ViewType ändern. Für mich deaktiviert diese klauen einen RecyclerView section header

@Override 
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { 
    if (viewHolder.getItemViewType() == 1) return 0; 
     return super.getSwipeDirs(recyclerView, viewHolder); 
    } 
} 
+0

Schöne Idee, aber getItemViewType ist endgültig – tim

+0

Das ist was ich will, danke –

10

Hier ist ein einfacher Weg, um diese so zu tun, dass es nur auf die Position des Elements hängt geklaut werden:

@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); 
} 

Dies sollte auch funktionieren, wenn Sie sind Usinge SimpleCallback:

@Override 
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder holder) { 
    int position = holder.getAdapterPosition(); 
    return position == 0 ? 0 : super.getSwipeDirs(recyclerView, viewHolder); 
} 

Ob dies besser ist als die anderen Antworten hängt von Ihren Bedürfnissen ab. Wenn Sie bestimmte Haltertypen haben, die nicht geklaut werden müssen, funktioniert die akzeptierte Antwort gut. Wenn die Swipe-Fähigkeit von den Daten für das Element abhängt, können Sie position verwenden, um Daten vom Adapter für das Objekt zu erhalten, das kopiert wird, und entsprechend deaktivieren. Und schließlich, wenn Sie wirklich nur basierend auf Position deaktivieren möchten, wird diese Antwort gut funktionieren.

0

Zuerst in recyclerView bei onCreateViewHolder Verfahren setzten Tag für jeden viewHolder Typen, wie unten Code:

@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; 
    } 
} 

dann in ItemTouchHelper.Callback Implementierung, update getMovementFlags Verfahren, wie unten:

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; 
    } 
} 

am ende an recyclerAnzeigen:

final SwipeController swipeController = new SwipeController(); 

    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(swipeController); 
    itemTouchHelper.attachToRecyclerView(recyclerView);