Search code examples
androidlayoutrunnablelayout-inflater

Updating a Layout class


My problem is, that I have a Layout class called by an Inflater and I want to run a method from this class to update a picture every few seconds.

I wanted to do this with handlers and the run() method, but my problem is, the picture only updates itself when I am interacting with the screen (clicking my only button).

Do you know what I did wrong?

Here is my GameLayout class:

package de.undeadleech.frogjump;

public class GameLayout extends View implements Runnable
{
private Sprite sprite;
private Bitmap bmp;
private Handler handler = new Handler();

public GameLayout(Context context) 
{
    super(context);
    bmp = BitmapFactory.decodeResource(getResources(), R.drawable.froschanimation);
    sprite = new Sprite(bmp, 0, 0, 400, 100, 5, 4);
    handler.postDelayed(this, 0);
}

@Override
protected void onDraw(Canvas canvas)
{
    sprite.draw(canvas);
}

public void update(long currentTimeMillis) 
{
    sprite.update(currentTimeMillis);
}

@Override
public void run()
{
    sprite.update(System.currentTimeMillis());
    handler.postDelayed(this,  0);
}
}

EDIT:

Here is my Sprite class because you wanted to see it:

package de.undeadleech.frogjump;



public class Sprite 
{   
//private static final String TAG = Sprite.class.getSimpleName();

private Bitmap bitmap;      // the animation sequence
private Rect sourceRect;    // the rectangle to be drawn from the animation bitmap
private int frameNr;        // number of frames in animation
private int currentFrame;   // the current frame
private long frameTicker;   // the time of the last frame update
private int framePeriod;    // milliseconds between each frame (1000/fps)

private int spriteWidth;    // the width of the sprite to calculate the cut out rectangle
private int spriteHeight;   // the height of the sprite

private int x;              // the X coordinate of the object (top left of the image)
private int y;              // the Y coordinate of the object (top left of the image)

public Sprite(Bitmap bitmap, int x, int y, int width, int height, int fps, int frameCount) 
{
    this.bitmap = bitmap;
    this.x = x;
    this.y = y;
    currentFrame = 0;
    frameNr = frameCount;
    spriteWidth = bitmap.getWidth() / frameCount;
    spriteHeight = bitmap.getHeight();
    sourceRect = new Rect( 0, 0, spriteWidth, spriteHeight);
    framePeriod = 1000 / fps;
    frameTicker = 0l;
}

public void update(long gameTime) 
{
    if (gameTime > frameTicker + framePeriod) 
    {
        frameTicker = gameTime;
        // increment the frame
        currentFrame++;
        if (currentFrame >= frameNr) 
        {
            currentFrame = 0;
        }
    }
    // define the rectangle to cut out sprite
    this.sourceRect.left = currentFrame * spriteWidth;
    this.sourceRect.right = this.sourceRect.left + spriteWidth;
}

public void draw(Canvas canvas) 
{
    // where to draw the sprite
    Rect destRect = new Rect( x, y, x + spriteWidth, y + spriteHeight);
    canvas.drawBitmap(bitmap, sourceRect, destRect, null);
}
}

Solution

  • Instead of posting Runnable you should call invalidate() when you need to redraw your layout. Also you should update state of your Sprite in onDraw method as well.