2016-02-08 7 views
10

Ho seguito la guida da questo link "Drag and Swipe with RecyclerView - by IPaulPro" e sto avendo pochi problemi in alcune situazioni.RecyclerView drag & drop tramite itemTouchHelper bahaving strano durante il trascinamento veloce

Così, ho praticamente fatto tutto ciò che ha spiegato + Ho aggiunto un TextView al punto che rappresenta la posizione di un elemento in RecyclerView, qualcosa di simile: enter image description here

Tutto sembra bello tranne quando inizio "riprese fionda "veloce, quindi ho due problemi:

  1. Capita di avere un duplicato di numeri. enter image description here

    Anche quello che ho fatto è stato utilizzando notifyAdapterSetChanged() nel metodo onItemClear() - è risolto in un modo, ma ha causato IllegalStateException, che catturato - porterebbe ad IndexOutOfBounds eccezione.

  2. A volte, quando si scorre troppo velocemente, l'elemento entra nello "sfondo". Questo può essere visto solo se gli articoli non hanno le stesse dimensioni. enter image description here

ho incollerà il mio codice adattatore tutta di seguito, ci deve essere un difetto da qualche parte in esso.

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 DOMANDA

C'è qualche tutorial o qualsiasi informazione relativa a trascinare tra i 2 RecyclerViews?

So che c'è una domanda su SO, ma senza risposta, potrei essere più fortunato qui.

+0

Inoltre sto usando il codice dal link lei ha fatto riferimento sopra e sono stato anche in difficoltà quando stavo facendo swaping troppo veloce ma Ho risolto questo problema con l'over onSelectedChanged nella classe estesa da ItemTouchHelper.Callback. –

+0

Con quale codice l'hai sovrascritto? Ho utilizzato il codice da https://github.com/iPaulPro/Android-ItemTouchHelper-Demo/blob/master/app/src/main/java/co/paulburke/android/itemtouchhelperdemo/helper/SimpleItemTouchHelperCallback.java – Sekula1991

+0

Vuoi pubblicare il mio codice e usarlo? o vuoi una correzione? * Non voglio vedere "non volevo codice, voglio una correzione" * è per questo che sto chiedendo. – Jaeger

risposta

0

Per me sembra che il tuo onItemMove() non tenga conto di tutte le modifiche. Quando qualcosa si muove per più di un oggetto (diciamo tra A & B), stai scambiando tutti gli elementi tra i due. Tuttavia, si riportano le modifiche solo ad A & B e non al resto degli elementi in mezzo.

vi consiglio di scrivere un metodo di scambio che riporta tutte le modifiche:

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

chiamata questa funzione invece di Collections.swap() e rimuovere il resto del codice notifica.

+0

Purtroppo non funziona, quando si trascina un elemento con questo codice, tutti gli elementi cambiano i loro valori dinamicamente durante il trascinamento, il che sembra davvero strano, e una volta rilasciato, un oggetto torna al suo posto. – Sekula1991

+0

A proposito, non è corretto fare come ho fatto in precedenza - solo gli oggetti A e B cambiano la loro posizione, quelli in mezzo rimangono dove sono? Forse dovrei notificare quegli elementi intorno aPosition (+1 -1) perché a volte interferiscono e non riesco a trovare il motivo per cui ciò accade (con alcune istruzioni if ​​if toPosition == list.size();) – Sekula1991

2

cambiare il metodo di onitemmove

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

a:

@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

Non funziona, hai trascinare la posizione in base alla posizione in questo modo e questo non è ciò che voglio ottenere. – Sekula1991

+0

no non vuoi trascinarlo posizione per posizione, basta provare questo codice e dirmi –

+0

L'errore, la sua posizione non spostata per posizione, può essere spostato nell'elenco ma torna su fromPosition quando viene rilasciato e notifyItemRangeChanged lo forza cambiare dinamicamente il valore degli oggetti che sono in bilico, sembra un po 'brutto. – Sekula1991