android - studio - La animación de diseño no funciona en la primera ejecución
programacion android pdf 2018 (6)
Como descubriste, el problema es la visibilidad. Cuando una vista se establece inicialmente como ida en el archivo xml, Android no representará el diseño hasta que la visibilidad cambie a visible o invisible. Si intenta animar en una vista que aún no se ha renderizado, la animación se realizará en la vista sin un diseño. Una vez completada la animación, se procesará y, de repente, la vista aparecerá sin animación. Funciona veces posteriores porque la vista tiene un diseño incluso cuando se establece en ido.
La clave es establecer la visibilidad en invisible en lugar de ir en el archivo xml para que se represente pero esté oculto. Cuando la animación ocurre la primera vez que aparece la vista, se moverá como se espera.
Tengo una Actividad con una lista de elementos y cuando hace clic en un elemento, quiero que los controles de reproducción de ese elemento se deslicen desde la parte inferior de la pantalla y se vuelvan visibles. Definí un conjunto de animación para la diapositiva y la diapositiva y funcionan. Configuré mi animationListener en mi actividad y comencé mi diapositiva en la animación onClick de un elemento. Mi problema es que la primera vez que ejecuto la aplicación, cuando hago clic en un elemento, se ejecuta la devolución de llamada onClick, pero la animación no ocurre. La segunda vez que hago clic, ocurre la diapositiva en la animación, pero no la diapositiva. La tercera y posteriores veces, funciona como se esperaba. Aquí están mis conjuntos de animación.
vm_slide_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<translate
android:fromYDelta="800"
android:toYDelta="0"
android:duration="600" />
</set>
vm_slide_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<translate
android:fromYDelta="0"
android:toYDelta="800"
android:duration="600" />
</set>
Aquí está el diseño de mi actividad
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/AppBG">
<RelativeLayout
style="@style/LogoBar"
android:id="@+id/logo_bar"
android:layout_alignParentTop="true">
<include layout="@layout/logobar"></include>
</RelativeLayout>
<RelativeLayout
style="@style/TitleBar"
android:id="@+id/title_bar"
android:layout_below="@+id/logo_bar">
<include layout="@layout/titlebar"></include>"
<Button style="@style/TitleBarButton"
android:id="@+id/vm_speaker_btn"
android:text="@string/vm_speaker_btn_label"
android:layout_alignParentLeft="true"
android:layout_margin="4dp">
</Button>
<Button style="@style/TitleBarButton"
android:id="@+id/vm_edit_btn"
android:text="@string/vm_edit_btn_label"
android:layout_alignParentRight="true"
android:layout_margin="4dp">
</Button>
</RelativeLayout>
<ListView
android:id="@+id/@android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/title_bar"/>
<RelativeLayout
android:id="@+id/vm_control_panel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/footer"
android:visibility="gone">
<include layout="@layout/vm_control"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/footer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<include layout="@layout/taskbar"/>
</RelativeLayout>
</RelativeLayout>
Aquí está el diseño para el control incluido
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:id="@+id/vm_control"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/dark_grey">
<TextView
android:id="@+id/vm_ctl_branding"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dp"
android:text="@string/branding"
android:textColor="@color/white">
</TextView>
<TextView style="@style/TimeMark"
android:id="@+id/vm_timestamp"
android:layout_toLeftOf="@+id/vm_progress"
android:layout_below="@+id/vm_ctl_branding"
android:layout_marginRight="3dp"
android:text="0:00">
</TextView>
<SeekBar
android:id="@+id/vm_progress"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_below="@+id/vm_ctl_branding"
android:layout_centerHorizontal="true">
</SeekBar>
<TextView style="@style/TimeMark"
android:id="@+id/vm_timeleft"
android:layout_toRightOf="@+id/vm_progress"
android:layout_below="@+id/vm_ctl_branding"
android:layout_marginLeft="3dp"
android:text="-0:00">
</TextView>
<LinearLayout
android:id="@+id/vm_action_button_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/vm_timestamp"
android:layout_alignRight="@+id/vm_timeleft"
android:orientation="horizontal"
android:layout_below="@+id/vm_progress">
<TextView style="@style/Vm_Action_Button"
android:background="@drawable/vm_action_btn_call"
android:id="@+id/vm_callback_btn"
android:layout_marginRight="5dp"
android:text="@string/vm_action_btn_callback">
</TextView>
<TextView style="@style/Vm_Action_Button"
android:background="@drawable/vm_action_btn_delete"
android:id="@+id/vm_delete_btn"
android:layout_marginLeft="5dp"
android:text="@string/vm_action_btn_delete">
</TextView>
</LinearLayout>
</RelativeLayout>
</merge>
Desde mi método onCreate ...
// Handle list item selections
ListView lv = getListView();
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final Voicemail vmItem = (Voicemail) vmla.getItem(position);
Toast.makeText(ctx, "Name: " + vmItem.getCallerName() + " Position: " + position, Toast.LENGTH_SHORT)
.show();
vVm_controls.startAnimation(mSlideIn);
}
});
Y mis devoluciones de llamadas de animación ...
@Override
public void onAnimationStart(Animation animation) {
vm_controls_in = !vm_controls_in;
if (vm_controls_in) {
vVm_controls.setVisibility(View.GONE);
} else {
vVm_controls.setVisibility(View.VISIBLE);
// vVm_controls.bringToFront();
}
}
@Override
public void onAnimationEnd(Animation animation) {
if (!vm_controls_in) {
try {
Thread.sleep(1000);
vVm_controls.startAnimation(mSlideOut);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
No sé si todavía está actualizado, pero sí, es un problema con la visibilidad. Así que establecí la visibilidad en el archivo xml en invisible y llamé al lugar donde se inicializó su vista:
view.post(new Runnable() {
@Override
public void run() {
view.animate().translationY(view.getHeight());
}
};
Ahora la llamada
view.animate().translationY(0).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
view.setVisibility(View.VISIBLE);
}
}
funciona también la primera vez
Por supuesto, no 20 minutos después de publicar esta pregunta, descubrí mi problema. Como estaba configurando la visibilidad de mi diseño en "GONE", cuando traté de comenzar la animación, no se activaba por primera vez. No estoy seguro de por qué va la segunda y siguientes veces, pero si configuro la visibilidad como "VISIBLE" justo antes de comenzar la animación, solucionó el problema. Aquí está el código donde lo cambié ...
// Handle list item selections
ListView lv = getListView();
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final Voicemail vmItem = (Voicemail) vmla.getItem(position);
Toast.makeText(ctx, "Name: " + vmItem.getCallerName() + " Position: " + position, Toast.LENGTH_SHORT)
.show();
vVm_controls.setVisibility(View.VISIBLE);
vVm_controls.startAnimation(mSlideIn);
}
});
Tenía exactamente el mismo problema, pero al usar ViewPropertyAnimator
. Por ejemplo, declaras un GridView
llamado mGridView
. Todo lo que tienes que hacer ahora es llamar a mGridView.animate()
con los cambios deseados.
La animación de mi GridView
se activó pero, debido a circunstancias desconocidas, no había ninguna animación real visible. También cambié todo View.GONE
a View.VISIBLE
, pero no cambió nada. En mi caso, me di cuenta de que solo tenía que eliminar android:requiresFadingEdge="vertical"
en mi XML de este GridView
particular. Puede que no sea posible utilizar un Fading Edge en combinación con ViewPropertyAnimator
.
Tuve exactamente el mismo problema aunque estaba configurando la vista como visible en el inicio de la animación. Seguí el consejo de Brockoli y lo puse a visible antes de comenzar la animación y funcionó como un amuleto.
ANTES DE:
Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.slide_left);
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
view.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationEnd(Animation animation) { }
@Override
public void onAnimationRepeat(Animation animation) { }
);
view.startAnimation(animation);
DESPUÉS:
Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.slide_left);
view.setVisibility(View.VISIBLE);
view.startAnimation(animation);
Tuve un problema similar en Android 4.4.3. Probé la mayor parte de la solución propuesta, pero solo una solución funcionó bien para mí. Tienes que ejecutar tu animación después de que la ventana complete la representación y la mejor manera es ejecutarla dentro de Window FocusChanged . No use la demora mediante Runnable ya que afectará el rendimiento de la aplicación en teléfonos de alta velocidad.
@Override
public void onWindowFocusChanged (boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus)
yourView.startAnimation(anim);
}
se puede encontrar más información en esta publicación: https://damianflannery.wordpress.com/2011/06/08/start-animation-in-oncreate-or-onresume-on-android/