Question

I'm just starting to learn android and I searched online how can I force a onDraw update and the only method I found is invalidate. It work for a while but after that it just doesn't update anymore.

This is my code:

package com.andrewxd.test01;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class Game extends View {

    private Bitmap enemy;
    private Paint dpaint;
    private float x,y;

    public Game(Context context) {
        super(context);
        enemy = BitmapFactory.decodeResource(getResources(), R.drawable.enemy);
        enemy = Bitmap.createScaledBitmap(enemy, 300 , 300, false);
        dpaint = new Paint();
        x = 0;
        y = 0;
    }

    @Override
    protected void onDraw(Canvas canvas){
        canvas.drawBitmap(enemy, x, y, dpaint);
        Log.d("GAME", "REDRAWN");
    }

    @Override
    public boolean onTouchEvent(MotionEvent event){
        x = event.getX();
        y = event.getY();
        invalidate();
        return true;
    }
}

Can somebody suggest me a better way of redrawing after the x and y changes?

Was it helpful?

Solution

From the API-Docs:

The basic cycle of a view is as follows:

  • An event comes in and is dispatched to the appropriate view. The view handles the event and notifies any listeners.
  • If in the course of processing the event, the view's bounds may need to be changed, the view will call requestLayout().
  • Similarly, if in the course of processing the event the view's appearance may need to be changed, the view will call invalidate().
  • If either requestLayout() or invalidate() were called, the framework will take care of measuring, laying out, and drawing the tree as appropriate.

So, it's probably the way to do it!

OTHER TIPS

Everything looks good, and I tried out your sample code to be sure, and it updates fine. The only difference from my code and yours is that I overrode the constructors as such and dropped your view into a layout:

public class Game extends View {

private Bitmap enemy;
private Paint dpaint;
private float x, y;

public Game(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    enemy = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
    enemy = Bitmap.createScaledBitmap(enemy, 300, 300, false);
    dpaint = new Paint();
    x = 0;
    y = 0;
}

public Game(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
    // TODO Auto-generated constructor stub
}

public Game(Context context) {
    this(context, null);

}

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawBitmap(enemy, x, y, dpaint);
    Log.d("GAME", "REDRAWN");
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    x = event.getX();
    y = event.getY();
    invalidate();
    return true;
}

}

Layout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world" />

<com.example.gametest.Game
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
</RelativeLayout>

Having the same problem. Calling invalidate with four parameters works for me:

invalidate(0,0,getWidth(),getHeight());

Looks like some bug in Android.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top