2012-01-08 13 views
29

¿Es posible tener un buen efecto de deslizamiento arriba/abajo al expandir/contraer un elemento de una ExpandableListView?Efecto de deslizamiento en ExpandableListView

En caso afirmativo, ¿cómo?

Gracias de antemano.

+0

tal vez hay una forma sencilla de simplemente reducir la velocidad del efecto de ampliar en una ExpandableListView. ¿Hay alguna manera? – thomaus

+1

¿Soy el único que se pregunta cómo lograr esto ???? – thomaus

+1

¿Encontró alguna solución? Gracias. – user430926

Respuesta

30

Este es un duplicado completo de this. En resumen, utilicé una lista regular, hice mi propia vista desplegable, utilicé una animación desplegable personalizada y un éxito voila (mire el enlace para más descripción).

Editar: Guía paso a paso:

Primero crear el 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> 

La animación para desplegable es el siguiente:

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

A continuación, dentro de mi adaptador (que' Por supuesto, agrego más sintaxis, y si desea que el menú desplegable no se cierre cuando está fuera de la vista en la lista, debe recordar esto en el titular con algún tipo de parámetro también):

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

Entonces sucede la magia en sus listas: onItemClick comentario

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

final: No estoy seguro de que esta es la mejor manera de hacerlo, pero esto es lo que funcionó para mí.

Editar: Hay una solución diferente por DevBytes en youtube que se puede ver here.

+0

¿Me mostrarías un ejemplo real? Gracias – Kermia

+1

@Kermia lo haré más tarde. No estoy seguro de publicarlo aquí/en otra publicación o en ambos = /. Como lo solicitas lo publicaré aquí, creo. – Warpzit

+0

Hola, estoy usando tu ejemplo para hacer mi propia animación, pero no sé qué hace el 'postDropHandler', y para saber cómo se implementa si es posible. Gracias –

5

El indicador señalado por Warpzit es correcto. He utilizado este método para proporcionar una biblioteca que puede fácilmente integrar en su aplicación sin tener que saber cómo funciona realmente:

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

más sobre ella se puede leer en esta entrada del blog: http://tjerktech.wordpress.com/2012/06/23/an-emerging-android-ui-pattern-for-contextual-actions/

+0

su lib es bastante interesante. Excelente trabajo. – user755

-1

Prueba esto en la clase 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

La aplicación por Warpzit definitivamente funciona, sin embargo, no se puede utilizar si es necesario apoyar a los grupos con una gran cantidad de niños (digamos 100) una s no utilizará la estructura optimizada de ListView (es decir. la reutilización/reciclaje de vistas de niños). En cambio, terminé ampliando ExpandableListView para crear un AnimatedExpandableListView que utiliza la técnica que describí here. Al hacerlo, AnimatedExpandableListView puede animar la expansión del grupo sin dejar de ofrecer el mejor rendimiento.Have a look.

1

La expandir/contraer no funciona con el código de aquí: https://github.com/tjerkw/Android-SlideExpandableListView porque OnItemExpandCollapseListener expandCollapseListener de AbstractSlideExpandableListAdapter es null; el método notifiyExpandCollapseListener se llama cuando se inicia la animación, pero el oyente es null porque: usted tiene la ActionSlideExpandableListView:

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

y se establece el adaptador: lv.setAdapter(slideAdapter); que llama al método setAdapter de SlideExpandableListView y hay una nueva instancia de SlideExpandableListAdapter es creado.

he cambiado como esto: setAdapter método de ActionSlideExpandableListView toma como parámetro también AbstractSlideExpandableListAdapter.OnItemExpandCollapseListener que se pasa al método setAdapter de SlideExpandableListView. Hay cuando creo SlideExpandableListAdapter que también pasan a este oyente:

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