para - manual programacion android español pdf
Animación de Android desplegable/vista adecuada (2)
Así que terminé haciéndolo con la ayuda de: https://stackoverflow.com/a/9112691/969325 . Si hubiera sido Android 3.0 ( http://developer.android.com/guide/topics/graphics/animation.html ) podría haber usado la animación de propiedades, pero no es así que tuve que hacerlo yo mismo.
Esto es lo que terminé con:
import android.view.View;
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 mType;
/**
* Initializes expand collapse animation, has two types, collapse (1) and expand (0).
* @param view The view to animate
* @param duration
* @param type The type of animation: 0 will expand from gone and 0 size to visible and layout size defined in xml.
* 1 will collapse view and set to gone
*/
public ExpandCollapseAnimation(View view, int duration, int type) {
setDuration(duration);
mAnimatedView = view;
mEndHeight = mAnimatedView.getLayoutParams().height;
mType = type;
if(mType == 0) {
mAnimatedView.getLayoutParams().height = 0;
mAnimatedView.setVisibility(View.VISIBLE);
}
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
if (interpolatedTime < 1.0f) {
if(mType == 0) {
mAnimatedView.getLayoutParams().height = (int) (mEndHeight * interpolatedTime);
} else {
mAnimatedView.getLayoutParams().height = mEndHeight - (int) (mEndHeight * interpolatedTime);
}
mAnimatedView.requestLayout();
} else {
if(mType == 0) {
mAnimatedView.getLayoutParams().height = mEndHeight;
mAnimatedView.requestLayout();
} else {
mAnimatedView.getLayoutParams().height = 0;
mAnimatedView.setVisibility(View.GONE);
mAnimatedView.requestLayout();
mAnimatedView.getLayoutParams().height = mEndHeight;
}
}
}
}
Ejemplo de uso:
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class AnimationTestActivity extends Activity {
private boolean mActive = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final Button animatedButton = (Button) findViewById(R.id.animatedButton);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
ExpandCollapseAnimation animation = null;
if(mActive) {
animation = new ExpandCollapseAnimation(animatedButton, 1000, 1);
mActive = false;
} else {
animation = new ExpandCollapseAnimation(animatedButton, 1000, 0);
mActive = true;
}
animatedButton.startAnimation(animation);
}
});
}
}
xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/animatedButton"
android:visibility="gone"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:text="@string/hello"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
<Button
android:id="@+id/button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"/>
</LinearLayout>
Editar :
Medida wrap_content altura:
Así que para que esto funcione para wrap_content, medí la altura de la vista antes de comenzar la animación y luego usar esta altura medida como la altura real. A continuación se muestra el código para medir la altura de la vista y establecer esto como la nueva altura (supongo que la vista utiliza el ancho de la pantalla, cambiar de acuerdo con sus propias necesidades):
/**
* This methode can be used to calculate the height and set it 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;
}
Está bien, estoy tratando de hacer una correcta animación deslizante hacia abajo. La vista que se desliza hacia abajo debe empujar todas las vistas hacia abajo en un movimiento suave y nuevamente, cuando se desliza hacia arriba, todas las vistas deben seguir en un movimiento suave.
Lo que he intentado : En código:
LinearLayout lin = (LinearLayout)findViewById(R.id.user_list_container);
setLayoutAnimSlidedownfromtop(lin, this);
lin.addView(getLayoutInflater().inflate(R.layout.user_panel,null),0);
Y:
public static void setLayoutAnimSlidedownfromtop(ViewGroup panel, Context ctx) {
AnimationSet set = new AnimationSet(true);
Animation animation = new AlphaAnimation(0.0f, 1.0f);
animation.setDuration(100);
set.addAnimation(animation);
animation = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, -1.0f, Animation.RELATIVE_TO_SELF, 0.0f
);
animation.setDuration(500);
set.addAnimation(animation);
LayoutAnimationController controller =
new LayoutAnimationController(set, 0.25f);
panel.setLayoutAnimation(controller);
}
Mi user_panel.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="40dp"
android:orientation="vertical" >
<ImageView
android:layout_alignParentLeft="true"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/icon" />
</LinearLayout>
Principio del xml principal:
<LinearLayout
android:id="@+id/user_list_container"
android:layout_alignParentTop="true"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<LinearLayout
android:id="@+id/container"
android:layout_below="@+id/user_list_container"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
El problema con el enfoque anterior es que cuando comienzo la animación, primero se crea el espacio vacío para la vista y luego la vista se desliza hacia abajo. Me gustaría que empuje lentamente todas las otras vistas hacia abajo en lugar de hacerlo en un solo movimiento.
Gracias Warpzit! Esa fue una respuesta muy útil. En mi caso, solo estaba tratando de animar vistas con altura que era wrap_content. Intenté activar la sugerencia de dos líneas, pero no funcionó en mi caso. (No pasé mucho tiempo persiguiendo por qué). Terminé usando una forma ligeramente modificada de ExpandCollapseAnimation de ExpandCollapseAnimation
con su método estático para determinar la altura de la vista
En un poco más de detalle:
-
setHeightForWrapContent()
su método estáticosetHeightForWrapContent()
en la claseExpandCollapseAnimation
. - Llamo a
setHeightForWrapContent()
en el constructorExpandCollapseAnimation
para determinar correctamente la altura de la vista. Para hacer esto, tengo que pasar la actividad con el constructor. - En el método
applyTransformation()
, cuando la vista finalmente se reduce a la altura cero, devuelvo la altura de la vista a wrap_content. Si no lo hace y cambia el contenido de la vista más adelante, cuando la expanda, la vista se expandirá a la altura determinada previamente.
El código está aquí:
public class ExpandCollapseAnimation extends Animation {
private View mAnimatedView;
private int mEndHeight;
private int mType;
public ExpandCollapseAnimation(View view, int duration, int type, Activity activity) {
setDuration(duration);
mAnimatedView = view;
setHeightForWrapContent(activity, view);
mEndHeight = mAnimatedView.getLayoutParams().height;
mType = type;
if(mType == 0) {
mAnimatedView.getLayoutParams().height = 0;
mAnimatedView.setVisibility(View.VISIBLE);
}
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
if (interpolatedTime < 1.0f) {
if(mType == 0) {
mAnimatedView.getLayoutParams().height = (int) (mEndHeight * interpolatedTime);
} else {
mAnimatedView.getLayoutParams().height = mEndHeight - (int) (mEndHeight * interpolatedTime);
}
mAnimatedView.requestLayout();
} else {
if(mType == 0) {
mAnimatedView.getLayoutParams().height = mEndHeight;
mAnimatedView.requestLayout();
} else {
mAnimatedView.getLayoutParams().height = 0;
mAnimatedView.setVisibility(View.GONE);
mAnimatedView.requestLayout();
mAnimatedView.getLayoutParams().height = LayoutParams.WRAP_CONTENT; // Return to wrap
}
}
}
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;
}
}
Gracias de nuevo, Warpzit!