Search code examples
androidlayoutviewspriterunnable

Avoid a View Class to update on pressing a button


I have a bitmap, which is drawn in my Sprite class, this bitmap is more than one picture in one, so I can animate it.

When I inflate the GameLayout next to my XML, this sprite is drawn. Every time the run() method of my GameActivity is called (with special circumstances) this picture updates itself 4 times, so the animation is through.

This is all running perfectly, but my Problem is, that if I press the button (no matter if the curcumstances are fulfilled), the bitmap jumps to the next picture, so, the bitmap updates itself, without me calling it with view.invalidate().

Do you have any idea how I could stop this?

GameActivity:

public class GameActivity extends Activity implements OnClickListener, Runnable
{
private int punkte;
private int highscore;
private Handler handler = new Handler();
private int balken = 0;
private boolean abnehmend = false;
private int Klick = 0;
private boolean balkenAktiv = true;
private boolean gewartet = false;
private int versuche;
private View view;
private int counter = 0;

@Override
protected void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);

    // inflate mainXML->
    View mainView = getLayoutInflater().inflate(R.layout.activity_game, null);
    // find container->
    LinearLayout container = (LinearLayout) mainView.findViewById(R.id.container);
    // initialize your custom view->
    view = new GameLayout(this);
    // add your custom view to container->
    container.addView(view);

    setContentView(mainView);

    versuche = leseVersuche();
    highscore = leseHighscore();
    setupActionBar();
    neueRunde();    

    Button button = (Button) findViewById(R.id.thebutton);
    button.setOnClickListener(this);
}

/**
 * Set up the {@link android.app.ActionBar}, if the API is available.
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void setupActionBar() 
{
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 
    {
        getActionBar().setDisplayHomeAsUpEnabled(true);
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) 
{
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.game, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) 
{
    switch (item.getItemId()) 
    {
    case android.R.id.home:
        NavUtils.navigateUpFromSameTask(this);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

private void neueRunde()
{
    punkte = 0;
    refreshScreen();
}

private void refreshScreen()
{
    TextView tvPunkte = (TextView) findViewById(R.id.points);
    tvPunkte.setText("Punkte: " + Integer.toString(punkte));    

    TextView tvHighscores = (TextView) findViewById(R.id.highscores);
    tvHighscores.setText("Highscore: " + Integer.toString(highscore));

    TextView tvVersuche = (TextView) findViewById(R.id.versuches);
    tvVersuche.setText("Versuche: " + Integer.toString(versuche));
}

@Override
public void onClick(View v)
{
    if(Klick == 0)
    {
        handler.postDelayed(this, 0);
        Klick = 1;
    }
    else
    {
        if(Klick == 1)
        {   
            balkenAktiv = false;
            handler.postDelayed(this, 500);
            punkte = balken;
            versuche++;
            schreibeVersuche(versuche);
            highscore += punkte;
            schreibeHighscore(highscore);
            Klick = 2;
            refreshScreen();
        }
        else
        {
        if(Klick == 2)
            {
                Klick = 0;
                punkte = 0;
                balken = 0;
                ProgressBar proBar = (ProgressBar) findViewById(R.id.sprung);
                proBar.setProgress(balken);
                refreshScreen();
            }
        }
    }
}

@Override
public void run()
{   
    if(balkenAktiv == true)
    {
        gewartet = false;
        ProgressBar proBar = (ProgressBar) findViewById(R.id.sprung);
        if(abnehmend == false)
        {
            if(balken < 100)
            {
                balken+=5;
                proBar.setProgress(balken);
                refreshScreen();
                handler.postDelayed(this, 0);
            }
            else if(balken == 100)
            {
                abnehmend = true;
                proBar.setProgress(balken);
                refreshScreen();
                handler.postDelayed(this, 0);
            }
        }

        else if(abnehmend == true)
        {
            if(balken > 0)
            {
                balken-=5;
                proBar.setProgress(balken);
                refreshScreen();
                handler.postDelayed(this, 0);
            }
            else if (balken == 0)
            {
                abnehmend = false;
                proBar.setProgress(balken);
                refreshScreen();
                handler.postDelayed(this, 0);
            }
        }       
    }       
    else if (balkenAktiv == false)
    {       
        if(gewartet == true)
        {
            if(counter < 4)
            {
                counter++;
                view.invalidate();
                handler.postDelayed(this, 500);
            }
            else if (counter >= 4)
            {
                balkenAktiv = true;
                counter = 0;
            }
        }
        gewartet = true;
    }
}   

private void schreibeHighscore(int highscore)
{
    SharedPreferences pref = getSharedPreferences("GAME", 0);
    SharedPreferences.Editor editor = pref.edit();
    editor.putInt("HIGHSCORE", highscore);
    editor.commit();
}

private void schreibeVersuche(int versuche)
{
    SharedPreferences pref = getSharedPreferences("GAME", 0);
    SharedPreferences.Editor editor = pref.edit();
    editor.putInt("VERSUCHE", versuche);
    editor.commit();
}

private int leseVersuche()
{
    SharedPreferences pref = getSharedPreferences("GAME", 0);
    return pref.getInt("VERSUCHE", 0);
}

private int leseHighscore()
{
    SharedPreferences pref = getSharedPreferences("GAME", 0);
    return pref.getInt("HIGHSCORE", 0);
}   
}

onDraw of View Class:

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

The Sprite Class:

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

  • The solution for this was pretty easy:

    Instead of using view.invalidate() in my run() method I used
    ((GameLayout) view).update(System.currentTimeMillis()) so I call the
    update() isntead of the onDraw() of my GameLayout class.

    With this change I could delete the update() method out of my onDraw() so if onDraw() is getting updated the picture will update, but will not change.

    Then I added invalidate() to my update() method so it would redraw itself after updating.

    Now everything is running smooooooothly.