I am making an app that displays circles randomly on the screen. The circles are either red or green. The purpose of the app is so that when someone touches a green circle something good happens, like they get points added to their score. When a red circle is clicked something bad happens like a new activity is started and the page says you failed or something. Here is my code for this app. In this code i receive no errors, nothing in logcat, everything works just fine. The circles display randomly on the screen as well as the score which is by default 0. The problem i am having with this app is that when a red or a green circle is clicked nothing happens.
public DrawingView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
RectF rectf = new RectF(0, 0, 200, 0);
private static final int w = 100;
public static int lastColor = Color.BLACK;
private final Random random = new Random();
private final Paint paint = new Paint();
private final int radius = 230;
private final Handler handler = new Handler();
public static int redColor = Color.RED;
public static int greenColor = Color.GREEN;
int randomWidth = 0;
int randomHeight = 0;
public static int addPoints = 0;
private final Runnable updateCircle = new Runnable() {
@Override
public void run() {
lastColor = random.nextInt(2) == 1 ? redColor : greenColor;
paint.setColor(lastColor);
invalidate();
handler.postDelayed(this, 1000);
}
};
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
handler.post(updateCircle);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
handler.removeCallbacks(updateCircle);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// your other stuff here
if(random == null){
randomWidth =(int) (random.nextInt(Math.abs(getWidth()-radius/2)) + radius/2f);
randomHeight = (random.nextInt((int)Math.abs((getHeight()-radius/2 + radius/2f))));
}else {
randomWidth =(int) (random.nextInt(Math.abs(getWidth()-radius/2)) + radius/2f);
randomHeight = (random.nextInt((int)Math.abs((getHeight()-radius/2 + radius/2f))));
}
canvas.drawCircle(randomWidth, randomHeight, radius, paint);
paint.setColor(Color.BLACK);
paint.setTextSize(150);
canvas.drawText("Score: " + addPoints, 120, 300, paint);
}
public boolean onTouch(View v, MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
if(isInsideCircle(x, y) == true){
//Do your things here
if(redColor == lastColor){
Intent i = new Intent(v.getContext(), YouFailed.class);
v.getContext().startActivity(i);
} else {
addPoints++;
}
}else {
}
return true;
}
public boolean isInsideCircle(int x, int y){
if ((((x - randomWidth)*(x - randomWidth)) + ((y - randomHeight)*(y - randomHeight))) < ((radius)*(radius))){
return true;
}
return false;
}
}
Your view might not be implementing the View.OnTouchListener
interface, hence it not calling the onTouch()
method.
Your view is not being set a View.OnTouchListener via the view's View.setOnTouchListener(View.OnTouchListener)
method.
Android Developer Reference - View.OnTouchListener
Either way it feels wrong to make a view implement this interface to listen to itself. Instead you may want to take a look at the View.onTouchEvent(MotionEvent event)
method; perhaps it serves your purpose (or it should in this case). Listener interfaces are supposed to be implemented by external components. Say, for example, if you wanted to make your TextView listen every time a Button or ImageView is touched, you could extend TextView/Button and make them implement the Listener interface then pass it to you view as a parameter of its setOnTouchListener(View.OnTouchListener)
.
However, all views have a method called onTouchEvent()
. This View.onTouchEvent()
method should be used if you want to listen to events within the view itself, as it is by default called whenever the view is, well touched. Should you need a reference to the view itself with this approach, you call this
since the view itself would be your current scope.
Android Developer Reference - View.onTouchEvent(MotionEvent event)
If you do it like this, all you would need to do in order to make your code work is change your onTouch()
method to an override of onTouchEvent()
like this: (Also added verification of touch action as suggested by Pooja and Tom so you don't take into account MOVE
or UP
events. Change DOWN
for UP
depending on when you want to trigger the event)
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();
if(isInsideCircle(x, y) == true) {
//Do your things here
if(redColor == lastColor){
Intent i = new Intent(v.getContext(), YouFailed.class);
this.getContext().startActivity(i);
} else {
addPoints++;
}
} else {
//Handle case not inside the circle
}
}
return true;
}