i'm having some problems with views. I created my own View (Square) and i want to move any Squares that i put on the screen. With the menu, i can put other Squares on the screen. The thing is, that when the program starts, i have one square on the screen and i can move it. But when i put other squares, i can just move the last one. How can i fix this?
public class Square extends View {
private float x, y, width, height;
private int screenW, screenH;
public boolean isInside = false;
public int id=0;
public Square(Context context, int aid, int asw, int ash, float aw, float ah) {
super(context);
id = aid;
screenH = ash;
screenW = asw;
x = asw/2;
y = ash/2;
width = aw;
height = ah;
}
protected void onDraw(Canvas canvas){
Paint paint = new Paint();
paint.setColor(Color.BLACK);
canvas.drawLine(x, y, x+width, y, paint);
canvas.drawLine(x, y, x, y+height, paint);
canvas.drawLine(x+width, y+height, x+width, y, paint);
canvas.drawLine(x+width, y+height, x, y+height, paint);
}
public void setPosition(float x, float y){
this.x = x-width/2;
this.y = y-height/2;
//invalidate();
}
public int contains(float ax, float ay){
if(ax==x || (ax<(x+width) && ax > x) || ax==(x+width))
if(ay==y || (ay<(y+height) && ay > y) || ay==(y+height))
return id;
return -1;
}
}
public class SquareBuilder extends Activity {
private int width, height;
//private RelativeLayout layout;
private FrameLayout layout;
private int id=0;
private ArrayList<Square> squareList;
Square squareTouched;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_square_builder);
Display display = null;
display = getWindowManager().getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics();
display.getMetrics(outMetrics);
width = outMetrics.widthPixels;
height = outMetrics.heightPixels;
Log.i("Display size", "Width: "+width+" Height: "+height);
Log.i("Display size", "Width: "+width/2+" Height: "+height/2);
//layout = new RelativeLayout(this);
layout = new FrameLayout(this);
squareList = new ArrayList<Square>();
Square sqr = new Square(this, id++, (int) width, (int)height,50,50);
sqr.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
Square sqr = (Square) v;
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
if(sqr.contains(event.getX(),event.getY())>=0)
sqr.isInside = true;
break;
case MotionEvent.ACTION_MOVE:
if(sqr.isInside)
sqr.setPosition(event.getX(),event.getY());
break;
case MotionEvent.ACTION_UP:
sqr.isInside = false;
break;
}
sqr.invalidate();
//return super.onTouchEvent(event);
return true;
//return false;
}
});
squareTouched = null;
squareList.add(sqr);
layout.addView(sqr);
setContentView(layout);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_square_builder, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId()){
case R.id.menu_other:
Square sqr = new Square(this, id++, (int) width, (int) height,50,50);
sqr.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
Square sqr = (Square) v;
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
if(sqr.contains(event.getX(),event.getY())>=0)
sqr.isInside = true;
break;
case MotionEvent.ACTION_MOVE:
if(sqr.isInside)
sqr.setPosition(event.getX(),event.getY());
break;
case MotionEvent.ACTION_UP:
sqr.isInside = false;
break;
}
sqr.invalidate();
//return super.onTouchEvent(event);
return true;
//return false;
}
});
squareList.add(sqr);
layout.addView(sqr);
setContentView(layout);
break;
}
return super.onOptionsItemSelected(item);
}
}
First thing, make the creation of a new square be a method in SquareBuilder:
Then replace the duplicate code for creating a square with calls to this new method. This will make your problem easier to solve because you will only have one copy of that code.
Then maybe add some logging inside each case statement to see what events are really firing where.
This may help too: Multiple Views OnTouch Events You need to return false from your event when the touch event was not on the square so that the event can be propagated to other listeners. Returning true consumes the event.