2014-12-24 40 views
22

Sto cercando di implementare il mio recyclerview Animazione - Vorrei ottenere questo risultato senza utilizzare alcuna libreria esterna. Ecco come dovrebbe apparire l'animazione teorica .RecyclerView Animation on Item Click

enter image description here

L'utente fa clic su un elemento della lista e un'animazione si verifica che si apre un'altra vista.

Su un livello elevato con codice minimo, forse solo pseudo-codice, quale sarebbe il processo per creare un'animazione del genere?

Inoltre vorrei sottolineare che l'animazione deve essere in grado di essere fatto in senso inverso e se l'utente fa clic lo stesso articolo o di un altro elemento

Io non sono che la familiarità con la classe RecyclerView e sarebbe piace saperne di più su di esso e sulle animazioni ad esso associate.

+1

Hai visto [questa domanda] (http://stackoverflow.com/questions/26419161/expandable-list-with-recyclerview)? –

+0

Penso che dovrai fare la ricerca da solo e postare una domanda specifica dopo. Per me questa è solo una domanda troppo grande e porta qualche ricerca in questo solo se dovesse sembrare come posso farlo funzionare. La mia opinione. Buon Natale a te comunque! ;) – Mike

+0

Tanis grazie Non ho visto questa domanda, ma la mia linea di pensiero era corretta in quanto ViewHolder è molto più enfatizzato in RecyclerView - quindi quello che sto pensando è scrivere una vista personalizzata per contenere il layout espanso e associare un onItemClickListener o onItemTouchListener alla voce di elenco. – AndyRoid

risposta

15

Soluzione:

Il modo risolto questo problema è stato quello di realizzare un ascoltatore View.OnClickListener alla ViewHolder classe che extends RecyclerView.ViewHolder. Così otteniamo il seguente codice:

public static class ExampleViewHolder extends RecyclerView.ViewHolder 
    implements View.OnClickListener { 

    private int originalHeight = 0; 
    private boolean isViewExpanded = false; 
    private YourCustomView yourCustomView 

    // ..... CODE ..... // 

} 

Le variabili originalHeight e isViewExpanded vengono utilizzati nel processo di animazione. Nel costruttore ho inizializzare la vista del View.OnClickListener in questo modo:

public ExampleViewHolder(View v) { 
    super(v); 
    v.setOnClickListener(this); 

    // Initialize other views, like TextView, ImageView, etc. here 

    // If isViewExpanded == false then set the visibility 
    // of whatever will be in the expanded to GONE 

    if (isViewExpanded == false) { 
     // Set Views to View.GONE and .setEnabled(false) 
     yourCustomView.setVisibility(View.GONE); 
     yourCustomView.setEnabled(false); 
    } 

} 

Ora che il costruttore si è preso cura di noi desidera configurare cosa succede quando l'utente fa clic su un individuo RecyclerView elemento. Le classi che saranno utili in questo caso saranno gli oggetti ValueAnimator e . Abbiamo l'override del metodo onClick in questo modo per raggiungere questo obiettivo:.

@Override 
public void onClick(final View view) { 
    // If the originalHeight is 0 then find the height of the View being used 
    // This would be the height of the cardview 
    if (originalHeight == 0) { 
      originalHeight = view.getHeight(); 
     } 

    // Declare a ValueAnimator object 
    ValueAnimator valueAnimator; 
     if (!mIsViewExpanded) { 
      yourCustomView.setVisibility(View.VISIBLE); 
      yourCustomView.setEnabled(true); 
      mIsViewExpanded = true; 
      valueAnimator = ValueAnimator.ofInt(originalHeight, originalHeight + (int) (originalHeight * 2.0)); // These values in this method can be changed to expand however much you like 
     } else { 
      mIsViewExpanded = false; 
      valueAnimator = ValueAnimator.ofInt(originalHeight + (int) (originalHeight * 2.0), originalHeight); 

      Animation a = new AlphaAnimation(1.00f, 0.00f); // Fade out 

      a.setDuration(200); 
      // Set a listener to the animation and configure onAnimationEnd 
      a.setAnimationListener(new Animation.AnimationListener() { 
       @Override 
       public void onAnimationStart(Animation animation) { 

       } 

       @Override 
       public void onAnimationEnd(Animation animation) { 
        yourCustomView.setVisibility(View.INVISIBLE); 
        yourCustomView.setEnabled(false); 
       } 

       @Override 
       public void onAnimationRepeat(Animation animation) { 

       } 
      }); 

      // Set the animation on the custom view 
      yourCustomView.startAnimation(a); 
     } 
     valueAnimator.setDuration(200); 
     valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); 
     valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 
      public void onAnimationUpdate(ValueAnimator animation) { 
       Integer value = (Integer) animation.getAnimatedValue(); 
       view.getLayoutParams().height = value.intValue(); 
       view.requestLayout(); 
      } 
     }); 


     valueAnimator.start(); 

    } 

Ora, quando si tocca un CardView individuale sul RecyclerView (ammesso che abbiate una configurazione CardView allora dovrebbe espandersi fare in modo di dichiarare il vostro CustomView correttamente nella vostra file xml (esempio se vuoi che lo CardView si espanda verso il basso quando lo tocchi, quindi assegna correttamente la vista personalizzata sotto le altre viste e imposta la visibilità su andato quando lo dichiari e poi quando l'animazione inizia così nel codice sopra, quindi imposta il visibilità a Visibile e abilitazione della vista

Spero che questo possa aiutare qualcuno.

+0

Grazie per questo AndyRoid! È davvero utile per me. Nel mio caso l'altezza del 'CardView' differisce per articolo, ma il '' CustomView'' è lo stesso per tutti gli articoli. È possibile calcolare l'altezza necessaria affinché la carta si espanda completamente senza che sia visibile? L'uso di un 'originalHeight * x' non funziona nel mio caso. – SanderTuit

+0

Perché grazie? se hai più elementi, bug da schermare verso l'alto o verso il basso, utilizza i tag :) – delive

+0

Io uso una soluzione simile, ma ho un problema. Tutte le viste che si trovano al di sotto di quella in espansione si agganciano, ma voglio che si spostino verso il basso. @AndyRoid, hai lo stesso comportamento? –

4

Un'alternativa più semplice per la risposta @ AndyRoid consiste nell'utilizzare la proprietà android:animateLayoutChanges="true". In questo modo non è necessario scrivere alcun codice di animazione; tuttavia, questo non è un modo per andare se hai bisogno di avere un controllo sull'animazione.

è ancora necessario per creare un OnClickListener:

class CardTapListener implements View.OnClickListener { 
    @Override 
    public void onClick(View v) { 
     View someView = v.findViewById(R.id.view_to_expand); 

     if (someView.getVisibility() == View.GONE) { 
      someView.setVisibility(View.VISIBLE); 
     } 
     else if (someView.getVisibility() == View.VISIBLE){ 
      someView.setVisibility(View.GONE); 
     } 

    } 
} 

allegarlo a ogni ViewHolder:

@Override 
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { 
    View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_layout, viewGroup, false); 
    v.setOnClickListener(new CardTapListener()); 
    return new ItemViewHolder(v); 
} 

Non dimenticate di crollare vista quando si associa un nuovo elemento:

@Override 
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) { 
    ... 
    // Collapse (probably opened by user previously) view 
    ItemViewHolder itemHolder = (ItemViewHolder) viewHolder; 
    itemHolder.description.setVisibility(View.GONE); 
    ... 

} 

view_holder_layout.xml:

<LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:animateLayoutChanges="true" 
    android:orientation="vertical"> 

... 

    <AnyViewHere 
     android:visibility="gone" 
     android:id="@+id/view_to_expand" /> 

</LinearLayout>