user1128677 user1128677 - 4 months ago 19
Android Question

android canvas ontouchevent doesn't work

I have a class for my custom view. One of methods is

@Override
public void onDraw(Canvas canvas) {
Paint paint = new Paint ();
Bitmap wrench = BitmapFactory.decodeResource(getResources(), R.drawable.wrench);
canvas.drawColor(Color .BLACK);
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4; j++) {
int left = canvas.getWidth()/2 - wrench.getWidth()*2 + j*wrench.getWidth();
int top = 0 + i*wrench.getHeight();
canvas.drawBitmap(wrench, left, top, null);

regions = new ArrayList<Region>();
Region reg = new Region(left, top, left + wrench.getWidth(), top + wrench.getHeight());
regions.add(reg);
// int right = left + wrench.getWidth();
// int bottom = top + wrench.getHeight();
// Log.d("REGION", left + "," + top + "," + right + "," + bottom);
}
}
}


There are 8 regions for my shapes. So, in the activity class

playField = (PlayGameView) findViewById(R.id.play_field_surface_view);
playField.setOnTouchListener(new View.OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {
// if(playField.getRegions().contains(210, 10)) {
ArrayList<Region> regions = playField.getRegions();
for(Region region: regions ) {
boolean condition = region.contains( (int)event.getX(), (int)event.getY());
if(condition) {
Toast.makeText(PlayGameActivity.this, (int)event.getX() + " " + (int)event.getY(), 2000).show();
}

}

return true;
}
});


but it doesn't work! When I click on the last shape toast is called twice! but on other shapes it is called some times.... help me ^_^

so this code works fine )

@Override
public void onDraw(Canvas canvas) {
Paint paint = new Paint ();
Bitmap wrench = BitmapFactory.decodeResource(getResources(), R.drawable.wrench);
canvas.drawColor(Color .BLACK);

shapeWidth = wrench.getWidth();
shapeHeight = wrench.getHeight();

for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4; j++) {
int left = canvas.getWidth()/2 - wrench.getWidth()*2 + j*wrench.getWidth();
int top = i*wrench.getHeight();
canvas.drawBitmap(wrench, left, top, null);
shapeLeft[j] = left;
shapeTop[i] = top;
}
}

}


public ArrayList<Region> getRegions() {
regions = new ArrayList<Region>();

for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4; j++) {
Region reg = new Region(shapeLeft[j], shapeTop[i], shapeLeft[j] + shapeWidth, shapeTop[i] + shapeHeight);
regions.add(reg);
// int right = left + wrench.getWidth();
// int bottom = top + wrench.getHeight();
// Log.d("REGION", left + "," + top + "," + right + "," + bottom);
}
}

return regions;
}


and

playField = (PlayGameView) findViewById(R.id.play_field_surface_view);
playField.setOnTouchListener(new View.OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {
// if(playField.getRegions().contains(210, 10)) {
ArrayList<Region> regions = playField.getRegions();
for(Region region: regions ) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
boolean condition = region.contains( (int)event.getX(), (int)event.getY());
if(condition) {
Toast.makeText(PlayGameActivity.this, (int)event.getX() + " " + (int)event.getY(), 2000).show();
}
}
}

return true;
}
});

Answer

React only on one action. Use ACTION_DOWN or ACTION_UP in your onTouch() method, otherwise it will at least be called twice if you hit a region.

Could you also please specify what on other shapes it called some times exactly means?

Edit:

You should create the regions not inside your onDraw method. Do it somewhere else (constructor?).

A small tipp: if you want to see if your regions are correct, you should draw the rects/regions on the screen at the very last, so that they overlay the playground. That should give you a visual feedback if your regions are in the right place and have the right size. Also alter the color of the regions you are drawing as it might help to see some issues.

If you have done that, could you provide a screenshot for it?