2010-12-30 13 views
11

Primero déjame explicarte mi objetivo. Estoy tratando de hacer un Animation que cambie las propiedades de un ArcShape. Un constructor ArcShape's toma dos campos: startAngle y sweepAngle. Quiero animar el sweepAngle para que aparezca en la pantalla como un círculo que se reduce continuamente.Animación personalizada de Android para ArcShape

Puede imaginar esta animación imaginando PacMan. Imagina que su boca está cerrada. Esta animación sería similar a la apertura de su mandíbula superior más y más hasta que no haya más PacMan.

Ahora ... Tengo un par de problemas con la implementación de esto. Primero, una vez que se crea un ArcShape, no hay métodos integrados para cambiarlo sweepAngle. Esto me lleva a mi primera pregunta: ¿hay alguna manera de anular ArcShape e implementar algún método setSweepAngle? ¿O tendré que crear un new ArcShape por cada sweepAngle que deseo mostrar?

Ahora vamos al segundo problema ... Suponiendo que encontré una solución al primer problema, ¿cómo podría crear este Animation? Esta es la esencia de lo que tengo ahora:

public class OpenPacman extends Animation { 
    public OpenPacman(float startAngle, float sweepAngle) { 
    mStartAngle = startAngle; 
    mSweepAngle = sweepAngle; 
    } 

    @Override 
    protected void applyTransformation(float interpolatedTime, Transformation t) { 
    /* This represents the current sweepAngle */ 
    float currAngle = mStartAngle + ((mSweepAngle - mStartAngle) * interpolatedTime); 

    //Now I need to update the ArcShape's sweepAngle to currAngle. But HOW? 
    } 
} 

Respuesta

16

He encontrado una solución. Tengo una clase que se extiende View Llamaremos a esto Pacman anidé mi Animation personalizado dentro de esta clase Pacman. Esto me permitió acceder al member variables de la clase Pacman.

public class Pacman extends View { 
    float mSweepAngle; 
    ... 
    //include constructors 
    //override onMeasure 
    ... 

    /* Here we override onDraw */ 
    @Override 
    protected void onDraw(final Canvas canvas) { 
    Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); 
    RectF oval = new RectF(canvas.getClipBounds()); 
    canvas.drawArc(oval, 0, mCurrAngle, true, p); 
    } 

    /* Here we define our nested custom animation */ 
    public class OpenPacman extends Animation { 
    float mStartAngle; 
    float mSweepAngle; 

    public OpenPacman (int startAngle, int sweepAngle, long duration) { 
     mStartAngle = startAngle; 
     mSweepAngle = sweepAngle; 
     setDuration(duration); 
     setInterpolator(new LinearInterpolator()); 
    } 

    @Override 
    protected void applyTransformation(float interpolatedTime, Transformation t) { 
     float currAngle = mStartAngle + ((mSweepAngle - mStartAngle) * interpolatedTime); 
     Pacman.this.mCurrAngle = -currAngle; //negative for counterclockwise animation. 
    } 
    } 
} 

Ahora, cuando la animación personalizada actualiza las clases de contenedores mCurrAngle, onDraw se llama automáticamente, lo que señala a la adecuada ArcShape.

+4

Tuve que agregar "invalidate();" al método applyTransformation para que la vista se vuelva a dibujar con el nuevo ángulo. – marmor

+0

Seguí las instrucciones pero mi vista personalizada no aparece en la IU. ¿puedes publicar tu código completo? –

+2

Lo sé, siempre viejo mensaje .... Pero no veo cómo esto anima el arco. Simplemente actualiza el ángulo actual y luego puede volver a dibujarlo, pero no está animado. Entonces ... ¿Cómo animaste esto exactamente? –

1

creo que puede ser mejor extendiéndose Disponibles y anular la función draw() para modificar el ángulo de barrido en cada llamada y dibujar el arco correspondiente. Se suele llamar a Draw cada vez que se actualiza el objeto, lo que significa que tendrá que crear una nueva ArcShape cada vez que se dibuje. La animación es más para realizar transformaciones en Vistas y otros componentes de la IU.

Algo así como:

public class OpenPacman 
{ 

public OpenPacman(float startAngle, float sweepAngle) { 
    this.mStartAngle = startAngle; 
    this.mSweepAngle = sweepAngle; 
    this.wakaWaka = new ArcShape(this.startAngle, this.mSweepAngle); 
} 

public void draw(Canvas c){ 
    //Do drawing stuff here with the canvas 
} 

//Your other functions for calculating angle, etc and making the ArcShape changes 
//Can call these from inside draw function so that when the view that contains your 
//object calls draw, it updates correctly. 

public float mStartAngle; 
public float msweepAngle; 
private ArcShape wakaWaka; 
} 

espero que esto le pone en el camino correcto.

Cuestiones relacionadas