views:

68

answers:

0

I have tried to create a simple application that draws a png graphic where the screen is touched. The problem that I have is that only every other instance of the graphic I add is actually rendered. Each time I add a new instance, the pattern alternates. I always get only 50% of the graphics rendered.

I am using android level 3 on HTC Hero.

To explain the problem a little more, this is the draw method I am calling from the surface holder callback:

 public void surfaceCreated(SurfaceHolder holder) {
  drawOK = true;
  drawIcon(100.0f, 100.0f);//line-1
  drawIcon(50.0f, 100.0f);//line-2
  drawIcon(100.0f, 50.0f);//line-3
  drawIcon(50.0f, 50.0f);//line-4
  //drawIcon(200.0f, 200.0f);//line-5
  //drawIcon(100.0f, 200.0f);//line-6
 }

When I have lines 5 & 6 commented out (as shown), I only see lines 2 & 4 rendered. When I add in line 5, I see lines 1,3 & 5 rendered. Finally when I add in line 6, I see lines 2,4 & 6 rendered.

Why would this be?

To explain the rest of the application in more detail. I have the following layout xml:

<SurfaceView android:id="@+id/SurfaceView01" android:layout_height="fill_parent" android:layout_width="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"/&gt;

I.e. I have a single surface view onto which I will draw the png graphic.

My activity implements SurfaceHolder.Callback and intialises like this:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    surfaceView = (SurfaceView) findViewById(R.id.SurfaceView01);

    // register our interest in hearing about changes to our surface
    holder = surfaceView.getHolder();
    holder.addCallback(this);
}

I.e. I chain the call, and set the content view using the R class. I then obtain a reference to the surface view and register the activity as a surface holder callback.

I have a method that draws the icon to the screen. This is it:

private void drawIcon(float x, float y) {
  if (!drawOK) return;
  Canvas canvas = holder.lockCanvas();
         // getting instance each time in case problem is related to reusing obj
         mFiringImage = getResources().getDrawable(R.drawable.icon);
         //so i can see overlapping icons, to rule out clipping issues
      mFiringImage.setAlpha(125); 
         // This mutate call is incase the bounds are shared state, which i doubt
      mFiringImage.mutate().setBounds( 
       (int)x-mFiringImage.getIntrinsicWidth()/2, 
       (int)y-mFiringImage.getIntrinsicHeight()/2, 
       (int)x+mFiringImage.getIntrinsicWidth()/2, 
       (int)y+mFiringImage.getIntrinsicHeight()/2
      );
      mFiringImage.draw(canvas);
      holder.unlockCanvasAndPost(canvas);
 }

I.e. I lock the canvas, obtain the drawable png resource, set the bounds (using mutate just in case), and ask the drawable to draw itself on the canvas. Note I don't ever draw unless the surface has been created.

I really am puzzled here.

All help appreciated.

p.s. Here is the full listing:

package com.mypackage;

import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class Toucher extends Activity implements SurfaceHolder.Callback {
 private Drawable mFiringImage;
 private SurfaceView surfaceView;
 private boolean drawOK;
 private SurfaceHolder holder;

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

  setContentView(R.layout.main);

  surfaceView = (SurfaceView) findViewById(R.id.SurfaceView01);

  // register our interest in hearing about changes to our surface
  holder = surfaceView.getHolder();
  holder.addCallback(this);
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
  float x = event.getX();
  float y = event.getY();
  Log.e(getClass().getSimpleName(), "=========================");
  Log.e(getClass().getSimpleName(), "Action="+event.getAction());
  Log.e(getClass().getSimpleName(), "History Size="+event.getHistorySize());
  Log.e(getClass().getSimpleName(), "Pressure="+event.getPressure());
  Log.e(getClass().getSimpleName(), "Raw X="+event.getRawX());
  Log.e(getClass().getSimpleName(), "Raw Y="+event.getRawY());
  Log.e(getClass().getSimpleName(), "X="+x);
  Log.e(getClass().getSimpleName(), "Y="+y);
  Log.e(getClass().getSimpleName(), "Precision X="+event.getXPrecision());
  Log.e(getClass().getSimpleName(), "Precision Y="+event.getYPrecision());
  Log.e(getClass().getSimpleName(), "Size="+event.getSize());
  Log.e(getClass().getSimpleName(), "=========================");

  drawIcon(x, y);

  return super.onTouchEvent(event);
 }

 private void drawIcon(float x, float y) {
  if (!drawOK) return;
  Canvas canvas = holder.lockCanvas();
  mFiringImage = getResources().getDrawable(R.drawable.icon);
  mFiringImage.setAlpha(125);
  mFiringImage.mutate().setBounds(
    (int)x-mFiringImage.getIntrinsicWidth()/2, 
    (int)y-mFiringImage.getIntrinsicHeight()/2, 
    (int)x+mFiringImage.getIntrinsicWidth()/2, 
    (int)y+mFiringImage.getIntrinsicHeight()/2
  );
  mFiringImage.draw(canvas);
  holder.unlockCanvasAndPost(canvas);
 }

 @Override
 public void surfaceChanged(SurfaceHolder holder, int format, int width,
   int height) {
 }

 @Override
 public void surfaceCreated(SurfaceHolder holder) {
  drawOK = true;
  drawIcon(100.0f, 100.0f);//1
  drawIcon(50.0f, 100.0f);//2
  drawIcon(100.0f, 50.0f);//3
  drawIcon(50.0f, 50.0f);//4
  //drawIcon(200.0f, 200.0f);//5
  //drawIcon(100.0f, 200.0f);//6
 }

 @Override
 public void surfaceDestroyed(SurfaceHolder holder) {
  // TODO Auto-generated method stub

 }

 @Override
 public void onWindowFocusChanged(boolean hasFocus) {
  super.onWindowFocusChanged(hasFocus);

  if (!hasFocus) drawOK = false;
 }
}