2012-01-08 17 views
29

È possibile avere un buon effetto di scorrimento su/giù durante l'espansione/compressione di un oggetto di ExpandableListView?Effetto scorrimento verso il basso su ExpandableListView

Se sì, come?

Grazie in anticipo.

+0

forse c'è un modo semplice per rallentare proprio lungo la velocità dell'effetto espandere su un ExpandableListView. C'è un modo ??? – thomaus

+1

Sono l'unico a chiedermi come ottenere questo ???? – thomaus

+1

Hai trovato qualche soluzione? Grazie. – user430926

risposta

30

Quindi questo è un duplicato completo di this. In breve, ho usato una lista regolare, creato la mia vista dropdown, usato un'animazione personalizzata a discesa e voilà successo (guarda il link per maggiori descrizioni).

Edit: Guida passo passo:

prima cosa creare il list_row xml:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:id="@+id/row_parent" 
    android:orientation="vertical"> 
    <RelativeLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:id="@+id/row_simple_parent" 
     > 
    <View 
     android:id="@+id/row_simple_parent_invis_cover" 
     android:visibility="gone" 
     android:layout_height="something that fills out your content" 
     android:layout_width="match_parent" 
     android:background="@android:color/transparent"/> 
    </RelativeLayout> 

    <!-- Dropdown --> 
    <RelativeLayout 
     android:id="@+id/row_dropdown" 
     android:layout_height="wrap_content" 
     android:layout_width="match_parent"> 
    </RelativeLayout> 
</LinearLayout> 

L'animazione per la discesa è la seguente:

import android.app.Activity; 
import android.util.DisplayMetrics; 
import android.view.View; 
import android.view.View.MeasureSpec; 
import android.view.animation.Animation; 
import android.view.animation.Transformation; 

/** 
* Class for handling collapse and expand animations. 
* @author Esben Gaarsmand 
* 
*/ 
public class ExpandCollapseAnimation extends Animation { 
    private View mAnimatedView; 
    private int mEndHeight; 
    private int mStartVisibility; 

    /** 
    * Initializes expand collapse animation. If the passed view is invisible/gone the animation will be a drop down, 
    * if it is visible the animation will be collapse from bottom 
    * @param view The view to animate 
    * @param duration 
    */ 
    public ExpandCollapseAnimation(View view, int duration) { 
     setDuration(duration); 
     mAnimatedView = view; 
     mEndHeight = mAnimatedView.getLayoutParams().height; 
     mStartVisibility = mAnimatedView.getVisibility(); 
     if(mStartVisibility == View.GONE || mStartVisibility == View.INVISIBLE) { 
      mAnimatedView.setVisibility(View.VISIBLE); 
      mAnimatedView.getLayoutParams().height = 0; 
     } 
    } 

    @Override 
    protected void applyTransformation(float interpolatedTime, Transformation t) { 
     super.applyTransformation(interpolatedTime, t); 
     if (interpolatedTime < 1.0f) { 
      if(mStartVisibility == View.GONE || mStartVisibility == View.INVISIBLE) { 
       mAnimatedView.getLayoutParams().height = (int) (mEndHeight * interpolatedTime); 
      } else { 
       mAnimatedView.getLayoutParams().height = mEndHeight - (int) (mEndHeight * interpolatedTime); 
      } 
      mAnimatedView.requestLayout(); 
     } else { 
      if(mStartVisibility == View.GONE || mStartVisibility == View.INVISIBLE) { 
       mAnimatedView.getLayoutParams().height = mEndHeight; 
       mAnimatedView.requestLayout(); 
      } else { 
       mAnimatedView.getLayoutParams().height = 0; 
       mAnimatedView.setVisibility(View.GONE); 
       mAnimatedView.requestLayout(); 
       mAnimatedView.getLayoutParams().height = mEndHeight; 
      } 
     } 
    } 

    /** 
    * This methode can be used to calculate the height and set itm for views with wrap_content as height. 
    * This should be done before ExpandCollapseAnimation is created. 
    * @param activity 
    * @param view 
    */ 
    public static void setHeightForWrapContent(Activity activity, View view) { 
     DisplayMetrics metrics = new DisplayMetrics(); 
     activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); 

     int screenWidth = metrics.widthPixels; 

     int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 
     int widthMeasureSpec = MeasureSpec.makeMeasureSpec(screenWidth, MeasureSpec.EXACTLY); 

     view.measure(widthMeasureSpec, heightMeasureSpec); 
     int height = view.getMeasuredHeight(); 
     view.getLayoutParams().height = height; 
    } 
} 

poi dentro il mio adattatore (si' Naturalmente aggiungo più sintassi, e se vuoi che il menu a discesa non si chiuda quando non è visibile nell'elenco, devi ricordarlo nel titolare con qualche tipo di parametro):

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    final ViewHolder holder; 
    if(convertView == null) { 
     // setup holder 
     holder = new ViewHolder(); 
     convertView = mInflater.inflate(R.layout.list_row, null); 
     holder.mDropDown = convertView.findViewById(R.id.row_dropdown); 
     convertView.setTag(holder); 
    } else { 
     // get existing row view 
     holder = (ViewHolder) convertView.getTag(); 
    } 
    holder.mDropDown.setVisibility(View.GONE); 
    return convertView; 
} 

Poi la magia accade negli elenchi onItemClick: commento

@Override 
public void onListItemClick(ListView list, View view, int position, long id) { 
    final ListItem item = (ListItem) list.getAdapter().getItem(position); 
    // set dropdown data 
    ViewHolder holder = (ViewHolder) view.getTag(); 
    final View dropDown = holder.mDropDown; 

    // set click close on top part of view, this is so you can click the view 
    // and it can close or whatever, if you start to add buttons etc. you'll loose 
    // the ability to click the view until you set the dropdown view to gone again. 
    final View simpleView = view.findViewById(R.id.row_simple_parent_invis_cover); 
    simpleView.setVisibility(View.VISIBLE); 

    final Handler handler = new Handler() { 
     @Override 
     public void handleMessage(Message msg) { 
      if(msg.what == 0) { 
       // first we measure height, we need to do this because we used wrap_content 
       // if we use a fixed height we could just pass that in px. 
       ExpandCollapseAnimation.setHeightForWrapContent(getActivity(), dropDown); 
       ExpandCollapseAnimation expandAni = new ExpandCollapseAnimation(dropDown, DROP_DOWN_TIME); 
       dropDown.startAnimation(expandAni); 

       Message newMsg = new Message(); 

      } else if(msg.what == 1) { 
       ExpandCollapseAnimation expandAni = new ExpandCollapseAnimation(dropDown, DROP_DOWN_TIME); 
       dropDown.startAnimation(expandAni); 

       simpleView.setOnClickListener(null); 
       simpleView.setVisibility(View.GONE); 
      } 
     } 
    }; 

    simpleView.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      handler.sendEmptyMessage(1); 
     } 
    }); 

    // start drop down animation 
    handler.sendEmptyMessage(0); 
} 

finale: Non sono sicuro che questo è il modo migliore di farlo, ma questo è ciò che ha funzionato per me.

Modifica: C'è una soluzione diversa da DevBytes su YouTube che può essere visualizzata here.

+0

Vuoi mostrarmi un esempio reale? Grazie – Kermia

+1

@Kermia Lo farò dopo. Non sono sicuro di postarlo qui/in altri post o in entrambi = /. Dal momento che lo chiedi, lo posterò qui, credo. – Warpzit

+0

Ciao, sto usando il tuo esempio per fare la mia animazione, ma non so cosa fa il 'postDropHandler', e sapere come è implementato se è possibile. Grazie –

5

La copia segnalata da Warpzit è corretta. Ho usato questo metodo per fornire una libreria che si può facilmente incorporare nella vostra applicazione senza dover conoscere come funziona realmente:

https://github.com/tjerkw/Android-SlideExpandableListView

più su di esso può essere letto in questo post del blog: http://tjerktech.wordpress.com/2012/06/23/an-emerging-android-ui-pattern-for-contextual-actions/

+0

la tua lib è abbastanza interessante. Lavoro eccellente. – user755

-1

Prova questo in classe java

 expListView.setAdapter(listAdapter); 
    expListView.setOnGroupExpandListener(new OnGroupExpandListener() { 
     int previousGroup = -1; 

     @Override 
     public void onGroupExpand(int groupPosition) { 
      if(groupPosition != previousGroup) 
       expListView.collapseGroup(previousGroup); 
      previousGroup = groupPosition; 
     } 
    }); 
3

L'attuazione da parte Warpzit sicuramente funziona, ma è inutilizzabile se è necessario supportare i gruppi con un sacco di bambini (diciamo 100) una s non sfrutterai la struttura ottimizzata di ListView (es. il riutilizzo/riciclaggio delle opinioni dei bambini). Invece, ho finito per estendere ExpandableListView per creare un AnimatedExpandableListView che utilizza la tecnica che ho descritto here. In questo modo, AnimatedExpandableListView può animare l'espansione del gruppo pur offrendo prestazioni eccellenti.Have a look.

1

L'espansione/compressione non funziona con il codice da qui: perché https://github.com/tjerkw/Android-SlideExpandableListViewOnItemExpandCollapseListener expandCollapseListener da AbstractSlideExpandableListAdapter è null; il metodo notifiyExpandCollapseListener viene chiamato quando l'animazione si avvia, ma l'ascoltatore è null perché: avete la ActionSlideExpandableListView:

ActionSlideExpandableListView lv = (ActionSlideExpandableListView) findViewById(R.id.list_view); 
SlideExpandableListAdapter slideAdapter = new SlideExpandableListAdapter(adapter,R.id.expandable_toggle_button, R.id.expandable); 

e si imposta l'adattatore: lv.setAdapter(slideAdapter); che chiama il metodo setAdapter da SlideExpandableListView e c'è una nuova istanza di SlideExpandableListAdapter è creato.

ho cambiato simili: setAdapter metodo dal ActionSlideExpandableListView prende come parametro anche AbstractSlideExpandableListAdapter.OnItemExpandCollapseListener che viene passato al metodo setAdapter da SlideExpandableListView. Ci quando creo SlideExpandableListAdapter mi passano anche questo listener:

public void setAdapter(ListAdapter adapter, AbstractSlideExpandableListAdapter.OnItemExpandCollapseListener expandCollapseListener) { 
     this.adapter = new SlideExpandableListAdapter(adapter, expandCollapseListener); 
     super.setAdapter(this.adapter); 
    } 

    public SlideExpandableListAdapter(ListAdapter wrapped, OnItemExpandCollapseListener expandCollapseListener) { 
     this(wrapped, R.id.expandable_toggle_button, R.id.expandable); 
     setItemExpandCollapseListener(expandCollapseListener); 
    } 
Problemi correlati