2012-06-25 10 views
20

Con el primer clic de un botón, quiero deslizar un View a lo largo del eje x (por 200 píxeles a la derecha digamos). Y en la segunda pulsación del botón, quiero deslizar el View hacia atrás a lo largo del eje x a su posición original.Cómo animar la traducción de una vista

El método View.setTranslationX(float) salta la vista a los lugares de destino horizontales con llamadas y myView.setTranslationX(200);myView.setTranslationX(0); respectivamente. Alguien sabe cómo puedo diapositivaView a las ubicaciones horizontales de destino en su lugar?

Nota 1: UnTranslateAnimation no es bueno ya que no mueve el View pero sólo presenta la ilusión de movimiento.

Nota 2: No me di cuenta en el momento de plantear la cuestión de que los métodos setTranslationX(float) y setTranslationY(float) se introdujeron a partir del nivel de API 11. Si se orienta de nido de abeja (API nivel 11) hacia arriba, a continuación, Gautam La respuesta de K será suficiente. De lo contrario, vea mi respuesta para una solución sugerida.

Respuesta

5

Esta me ha dejado perpleja unos días (poniéndola a trabajar antes del Ice Cream Sandwich) pero creo ¡Finalmente llegué allí!(gracias a Gautam K y Mike Israel por los clientes potenciales) Lo que hice al final fue extender mi View (a FrameLayout) para iniciar las animaciones de traducción derecha/izquierda según sea necesario y para escuchar el final de las animaciones para reubicarme FrameLayout mi derecha/izquierda según el caso, de la siguiente manera:

public class SlidingFrameLayout extends FrameLayout 
{ 
    private final int durationMilliseconds = 1000; 
    private final int displacementPixels = 200; 

    private boolean isInOriginalPosition = true; 
    private boolean isSliding = false; 

    public SlidingFrameLayout(Context context) 
    { 
    super(context); 
    } 

    public SlidingFrameLayout(Context context, AttributeSet attrs) 
    { 
    super(context, attrs); 
    } 

    public SlidingFrameLayout(Context context, AttributeSet attrs, int defStyle) 
    { 
    super(context, attrs, defStyle); 
    } 

    @Override 
    protected void onAnimationEnd() 
    { 
    super.onAnimationEnd(); 

    if (isInOriginalPosition) 
     offsetLeftAndRight(displacementPixels); 
    else 
     offsetLeftAndRight(-displacementPixels); 

    isSliding = false; 
    isInOriginalPosition = !isInOriginalPosition; 
    } 

    @Override 
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) 
    { 
    super.onLayout(changed, left, top, right, bottom); 

    // need this since otherwise this View jumps back to its original position 
    // ignoring its displacement 
    // when (re-)doing layout, e.g. when a fragment transaction is committed 
    if (changed && !isInOriginalPosition) 
     offsetLeftAndRight(displacementPixels); 
    } 

    public void toggleSlide() 
    { 
    // check whether frame layout is already sliding 
    if (isSliding) 
     return; // ignore request to slide 

    if (isInOriginalPosition) 
     startAnimation(new SlideRightAnimation()); 
    else 
     startAnimation(new SlideLeftAnimation()); 

    isSliding = true; 
    } 

    private class SlideRightAnimation extends TranslateAnimation 
    { 
    public SlideRightAnimation() 
    { 
     super(
      Animation.ABSOLUTE, 0, 
      Animation.ABSOLUTE, displacementPixels, 
      Animation.ABSOLUTE, 0, 
      Animation.ABSOLUTE, 0); 

     setDuration(durationMilliseconds); 
     setFillAfter(false); 
    } 
    } 

    private class SlideLeftAnimation extends TranslateAnimation 
    { 
    public SlideLeftAnimation() 
    { 
     super(
      Animation.ABSOLUTE, 0, 
      Animation.ABSOLUTE, -displacementPixels, 
      Animation.ABSOLUTE, 0, 
      Animation.ABSOLUTE, 0); 

     setDuration(durationMilliseconds); 
     setFillAfter(false); 
    } 
    } 
} 

Y, por último, para deslizar el SlidingFrameLayout derecha/izquierda, todo lo que tienes que hacer es llamar al método SlidingFrameLayout.toggleSlide(). Por supuesto, puede ajustar este SlidingFrameLayout para que su propósito sea deslizar una mayor cantidad de píxeles, deslizarse por más tiempo, etc., pero esto debería ser suficiente para comenzar :)

25

Trate de buscar en ObjectAnimator y su superclase Valor animador

se puede hacer algo como esto ObjectAnimator anim = ObjectAnimator.ofFloat(this, "translationX", 0,200); y luego anim.start();

utilizar un valor boolean y alternar con 200,0 en el animador de objetos deslizar hacia atrás

PD: puede usar setDuration método para establecer cuánto tiempo debe tomar la animación para completar

Editar:

Trate de buscar en el support library que proporciona compatibilidad con versiones anteriores.

Editar

Como @AdilHussain señaló que hay una biblioteca llamada nineoldandroids que puede ser usado para el mismo fin en androides mayores.

+0

@AdilHussain: luego debe implementar la funcionalidad con hilos usted mismo en teléfonos que no lo admiten. Simplemente verifique si el teléfono lo admite o escriba alguna alternativa simple. Esa es la mejor opción. – Gautam

+1

Encontré esta brillante biblioteca que hace el trabajo: [http://nineoldandroids.com] (http://nineoldandroids.com). Biblioteca disponible para descargar como un 'jar' desde aquí: [https://github.com/JakeWharton/NineOldAndroids/downloads](https://github.com/JakeWharton/NineOldAndroids/downloads) –

+1

Parece que hablé demasiado pronto. Al hacer una traducción utilizando la biblioteca [nineoldandroids] (https://github.com/JakeWharton/NineOldAndroids) en teléfonos más antiguos (pre-Honeycomb), los botones dentro de la vista traducida parecen haberse movido, pero aún se puede hacer clic en sus ubicaciones anteriores (y no sus nuevas ubicaciones). He enviado un correo electrónico al autor de la biblioteca pero aún no he recibido una respuesta. –

2

Tuve un problema similar, TranslateAnimation realmente mueve la vista si llama a setFillAfter now (android bug). Tuve que hacer algo similar, así que dije: oye, usemos un oyente de animación y luego simplemente movemos todo a la ubicación correcta. Lamentablemente, también hay un error en los oyentes de animación (stackoverflow solution). Así que creé mi propia clase de diseño de acuerdo con la solución en el stackoverflow solution y estaba listo para ir :)

+0

Gracias por la respuesta y los enlaces. Va a mostrar que usar 'TranslateAnimation' para esto es un poco complicado. Cuando dije 'TranslateAnimation' en realidad no mueve la vista (a pesar de usar 'setFillAfter (true)'), quise decir que los elementos cliqueables todavía están en sus posiciones originales. Mira este video para ver un ejemplo de lo que quiero decir: [http://www.youtube.com/watch?v=VY3kMFrA3wU](http://www.youtube.com/watch?v=VY3kMFrA3wU) –

+1

si, eso se ve exactamente como el error con fillAfter. Aunque parece extraño que el primer botón funciona, ¿cuál es la diferencia entre los dos botones, alguno? – MikeIsrael

+1

La solución que recomendé debería funcionar para todas las versiones. Construí una clase de diseño personalizado que invalida onAnimationEnd() y allí cambio el margen izquierdo del objeto según sea necesario para moverlo al lugar correcto. – MikeIsrael

Cuestiones relacionadas