2016-02-08 12 views
10

Ich habe die Anleitung von diesem Link "Drag and Swipe with RecyclerView - by IPaulPro" folgen und ich habe einige Probleme in einigen Situationen.RecyclerView Drag & Drop über itemTouchHelper bahaving seltsam beim Ziehen schnell

Also, ich habe im Grunde alles, was er erklärt + i ein Textview in Artikel hinzugefügt, die die Position eines Elements in RecyclerView, so etwas wie dies darstellt: enter image description here

Alles scheint schön, außer wenn ich „Schleuder schießen beginnen "Artikel schnell, dann habe ich zwei Probleme:

  1. Es passiert, ein Duplikat von Zahlen zu haben. enter image description here

    Auch das, was ich tat, war notifyAdapterSetChanged() im onItemClear() Methode verwendet - es es in einer Weise festgelegt, sondern verursacht IllegalStateException, die catched - zu IndexOutOfBounds Ausnahme führen würde.

  2. Gelegentlich, wenn man zu schnell wischt, wird das Element im "Hintergrund" angezeigt. Dies wird nur angezeigt, wenn die Artikel nicht die gleiche Größe haben. enter image description here

Ich werde meinen ganzen Adapter Code unten ein, muss es in ihm ein Fehler irgendwo sein.

LayoutInflater inflater; 
Context context; 
AndroidEntityQuestionResult androidEntityQuestionResult; 
ArrayList<AndroidEntityAnswer> list = new ArrayList<>(); 
ORDLayoutManagerQuestion ord; 
ScreenDimensionsConstants sdc; 


public OrderingRecycleAdapter(Context context, AndroidEntityQuestionResult androidEntityQuestionResult, ORDLayoutManagerQuestion ord) { 
    inflater = LayoutInflater.from(context); 
    this.context = context; 
    this.list = androidEntityQuestionResult.getAndroidEntityQuestion().getEntityAnswer(); 
    this.androidEntityQuestionResult = androidEntityQuestionResult; 
    this.ord = ord; 
    sdc = new ScreenDimensionsConstants(context); 
} 

@Override 
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
    View view = inflater.inflate(R.layout.custom_row_ordering_rv, parent, false); 
    final RecyclerView.ViewHolder holder = new OrderingViewHolder(view); 
    return holder; 
} 


@Override 
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 
    if (holder instanceof OrderingViewHolder) { 

     ((OrderingViewHolder) holder).answerText.setText(list.get(position).getAnswer().getANSWER_TEXT()); 
     int currentPosition = position + 1; 
     ((OrderingViewHolder) holder).position.setText("#" + currentPosition); 
    } 
} 

@Override 
public int getItemCount() { 
    return list.size(); 
} 

@Override 
public boolean onItemMove(int fromPosition, int toPosition) { 
    if (fromPosition < toPosition) { 
     for (int i = fromPosition; i < toPosition; i++) { 
      Collections.swap(list, i, i + 1); 
     } 
    } else { 
     for (int i = fromPosition; i > toPosition; i--) { 
      Collections.swap(list, i, i - 1); 
     } 
    } 
    notifyItemMoved(fromPosition, toPosition); 
    notifyItemChanged(fromPosition); 
    return true; 
} 

@Override 
public void onItemDismiss(int position) { 

} 

@Override 
public void onStartDrag(RecyclerView.ViewHolder viewHolder) { 
     ord.getItemTouchHelper().startDrag(viewHolder); 
} 

class OrderingViewHolder extends RecyclerView.ViewHolder implements ItemTouchHelperViewHolder { 
    private TextView answerText; 
    private ImageView pin; 
    private TextView position; 

    public OrderingViewHolder(View itemView) { 
     super(itemView); 
     answerText = (TextView) itemView.findViewById(R.id.orderingAnswer); 
     answerText.setTextSize(TypedValue.COMPLEX_UNIT_PX, sdc.getHeight()/40); 

     pin = (ImageView) itemView.findViewById(R.id.ordering_pin); 
     pin.getLayoutParams().width = sdc.getHeight()/15; 
     pin.getLayoutParams().height = sdc.getHeight()/15; 

     pin.setOnTouchListener(new View.OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       if (MotionEventCompat.getActionMasked(event) == 
         MotionEvent.ACTION_DOWN) { 
        OrderingRecycleAdapter.this.onStartDrag(OrderingViewHolder.this); 
       } 
       return false; 
      } 
     }); 
     position = (TextView) itemView.findViewById(R.id.answer_position); 
     position.setTextSize(TypedValue.COMPLEX_UNIT_PX, sdc.getHeight()/40); 

    } 

    @Override 
    public void onItemSelected() { 
     itemView.setBackgroundResource(R.drawable.menu_item_background_ice_blue); 
    } 

    @Override 
    public void onItemClear() { 
     itemView.setBackgroundResource(R.drawable.menu_item_background_white); 
     int currentPosition = getLayoutPosition() + 1; 
     position.setText("#" + currentPosition); 
     //notifyDataSetChanged(); 

    } 
} 

Bonus-Frage

Gibt es eine Anleitung oder eine Info per Drag & Drop zwischen 2 RecyclerViews zu tun?

Ich weiß, dass es eine Frage zu SO gibt, aber ohne Antwort, kann ich hier glücklicher sein.

+0

ich auch den Code aus dem Link oben genannten verwenden, und ich war auch in Schwierigkeiten, wenn ich zu viel schnell tun war swaping aber Ich löste das durch Überschreiben onSelectedChanged in der Klasse von ItemTouchHelper.Callback erweitert. –

+0

Mit welchem ​​Code haben Sie es überschrieben? Ich habe den Code von https://github.com/iPaulPro/Android-ItemTouchHelper-Demo/blob/master/app/src/main/java/co/paulburke/android/itemtouchhelperdemo/helper/SimpleItemTouchHelperCallback verwendet.Java – Sekula1991

+0

Möchten Sie meinen Code veröffentlichen und verwenden? oder willst du reparieren? * ich will nicht sehen "ich wollte keinen code, ich möchte eine reparatur" * darum frage ich. – Jaeger

Antwort

0

Für mich scheint es, dass Ihr onItemMove() nicht alle Änderungen berücksichtigt. Wenn sich etwas für mehr als einen Gegenstand bewegt (sagen wir zwischen A & B), tauscht man alle Gegenstände zwischen den beiden aus. Allerdings melden Sie Änderungen nur an A & B und nicht an den Rest der Elemente dazwischen.

Ich schlage vor, Sie eine Swap-Methode schreiben, das alle Änderungen berichtet:

public boolean swapItems(int fromPosition, int toPosition){ 
    Collections.swap(list, fromPosition, toPosition); 
    notifyItemMoved(fromPosition, toPosition); 
    notifyItemMoved(toPosition, fromPosition); 
    // And maybe also notifyItemChanged() as the item changes due to the shift 
    notifyItemChanged(fromPosition); 
    notifyItemChanged(toPosition); 
} 

Rufen Sie diese Funktion statt Collections.swap() und den Rest des Codes mitteilen entfernen.

+0

Leider funktioniert es nicht, wenn ein Element mit diesem Code gezogen wird, ändern alle Elemente ihre Werte während des Ziehens dynamisch, was wirklich merkwürdig aussieht, und wenn es freigegeben wird, kommt ein Element wieder an seinen Platz. – Sekula1991

+0

Übrigens, ist es nicht korrekt zu tun, wie ich es zuvor getan habe - nur A- und B-Items ändern ihre Position, die dazwischen bleiben wo sie sind? Vielleicht sollte ich diese Elemente um toPosition (+1 -1) benachrichtigen, weil sie manchmal stören und ich kann einfach nicht den Grund finden, warum es passiert (mit einigen if-Anweisungen wenn toPosition == list.size();) – Sekula1991

2

ändern onitemmove Methode

@Override 
public boolean onItemMove(int fromPosition, int toPosition) { 
    if (fromPosition < toPosition) { 
     for (int i = fromPosition; i < toPosition; i++) { 
      Collections.swap(list, i, i + 1); 
     } 
    } else { 
     for (int i = fromPosition; i > toPosition; i--) { 
      Collections.swap(list, i, i - 1); 
     } 
    } 
    notifyItemMoved(fromPosition, toPosition); 
    notifyItemChanged(fromPosition); 
    return true; 
} 

zu:

@Override 
public boolean onItemMove(int fromPosition, int toPosition) { 
    if (fromPosition < toPosition) { 
     for (int i = fromPosition; i < toPosition; i++) { 
      Collections.swap(list, i, i + 1); 
     } 
    } else { 
     for (int i = fromPosition; i > toPosition; i--) { 
      Collections.swap(list, i, i - 1); 
     } 
    } 
    notifyItemMoved(fromPosition, toPosition); 
    return true; 
} 
+0

Nicht funktioniert, haben Sie um es Position für Position auf diese Weise zu ziehen und das ist nicht das, was ich erreichen möchte. – Sekula1991

+0

nein, du willst es nicht Position für Position ziehen, probiere einfach diesen Code aus und sage mir –

+0

Mein Fehler, seine Position wird nicht durch Position verschoben - sie kann durch die Liste verschoben werden, aber sie wird wieder aus ihrer Position, wenn notifyItemRangeChanged freigegeben wird den Wert von Elementen, die sich in der Schwebe befinden, dynamisch zu ändern, sieht irgendwie schlecht aus. – Sekula1991

Verwandte Themen