2010-12-21 24 views
35

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.La animación de diseño no funciona en la primera ejecució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í es mi actividad de diseño

<?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> 

Este es el diagrama 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 llamada 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 

} 

Respuesta

98

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 a 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.

+0

esta solución no funciona en mi caso. ¿Alguna alternativa para renderizar la vista manualmente? –

+1

@sureshcheemalamudi Es difícil ayudar sin más información, ya que podría haber un problema con tu código de animación. Además, esta respuesta fue escrita en base a API 11 (Honeycomb). Por favor haga una nueva pregunta con detalles específicos de su problema y esperemos que alguien pueda dar una respuesta. – mindriot

+0

gracias, funcionó para mí (y). – vanloi999

9

Por supuesto que no 20 minutos después de la publicación de esta pregunta me di cuenta de 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); 
    } 
}); 
+0

Su solución es mejor que el "ajuste de la visibilidad a invisible" – breceivemail

+0

No, no es porque entonces usted tiene que preocuparse de donde la vista se coloca de modo el usuario no ve un salto. Está bien si la animación comienza en la posición de la vista, pero no si la animación se lleva a la posición de la vista (u otras animaciones de desplazamiento). –

0

Tuve exactamente el mismo problema, pero al usar el ViewPropertyAnimator. Por ejemplo, declara un GridView llamado mGridView. Todo lo que tiene que hacer ahora es llamar al mGridView.animate() con los cambios deseados.

Se activó la animación de mi GridView pero, debido a circunstancias desconocidas, no había ninguna animación real visible. También cambié todos View.GONE a View.VISIBLE, pero no cambió nada. En mi caso, descubrí que solo tenía que eliminar android:requiresFadingEdge="vertical" en mi XML de este particular GridView. Es posible que no se pueda usar un Fading Edge en combinación con ViewPropertyAnimator.

3

No sé si todavía está actualizado, pero sí, es un problema con la visibilidad.Así que me puse la visibilidad en el archivo XML para invisible y llamó al lugar donde se inicia la 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); 
    } 
} 

obras también en el primer tiempo.

0

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í. Debe ejecutar la animación después de que la ventana finalice la representación y la mejor manera es ejecutarla dentro de onWindowFocusChanged. 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); 
} 

más información se puede encontrar en este post: https://damianflannery.wordpress.com/2011/06/08/start-animation-in-oncreate-or-onresume-on-android/

1

Tenía el mismo problema a pesar de que yo estaba sentado a la vista visible en inicio de animación. Seguí el consejo de Brockoli y lo puse a visible antes de comenzar la animación y funcionó como un amuleto.

ANTES:

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