Reference Image
In above image. I want to detect that in which circle user has taped his finger.
If the user has touched black circle then a toast should be shown saying that "You are in Black circle".
If it is blue then "You are in Blue Circle".
And similarly for Red and Yellow Circles.
I know how to detect touch events DOWN, MOVE, PRESS etc and also x, y coordinates.
But don't now how to detect circles area in that image.
EDIT
Actually the above image was just to make you understand my problem. In the actual scenario I don't want to detect the colour pixels. I want to get the exact area of each circle. Because in my case my background colour and my circle colours may be same. So detecting colour pixel will not solve my real problem.
If you know where the center of your circle is (and I assume you know the width of each ring), simply calculate the distance from the center in your on touch event as follows.
#Override public boolean onTouchEvent(MotionEvent ev) {
double distanceFromCenter = Math.sqrt((CENTER_X - ev.getX())^2 + (CENTER_Y - ev.getY())^2);
//Figure out which ring it's in.
}
You could also draw a bunch of overlapping circle shapes, but that would be more complex. See this to get started.
With this you will able to get the proprotion of Red, Green, Blue:
final Bitmap bitmap = ((BitmapDrawable)imageView.getDrawable()).getBitmap();
imageView.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event){
int x = (int)event.getX();
int y = (int)event.getY();
int pixel = bitmap.getPixel(x,y);
int red = Color.red(pixel);
int blue = Color.blue(pixel);
int green = Color.green(pixel);
Log.i("color", red+","+green+","+blue);
return false;
}
});
You get the pixel color of pressed position, then detect which color it hits closest and show Toast according to that
How to get pixel color in Android?
Related
I have used 4 different colored custom shape buttons. I am trying to implement an ontouch listener by getting the pixel color as shown below
#Override
public boolean onTouch(View v, MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
return isPixelTransparent(v, x, y) || v.onTouchEvent(event);
}
private boolean isPixelTransparent(View v, int x, int y) {
Bitmap bmp = Bitmap.createBitmap(v.getDrawingCache());
int color = Color.TRANSPARENT;
try {
color = bmp.getPixel(x, y);
} catch (IllegalArgumentException e) {
// x or y exceed the bitmap's bounds.
// Reverts the View's internal state from a previously set "pressed" state.
v.setPressed(false);
}
return color == Color.TRANSPARENT;
}
However the rectangular area of the buttons overlap so the buttons underneath dont get pressed if pixel is transparent. Also please note all the buttons have large white text. I have done lots of searching but cannot figure out how to go about it, any help would be much appreciated please.
XML
<za.co.####.####.DiamondShapeButton
android:id="#+id/button_resources"
style="#style/NavigationButton"
android:layout_width="150dp"
android:layout_height="150dp"
android:text="#string/resources"
custom:diamondColor="#color/red"/>
<za.co.####.####.DiamondShapeButton
android:id="#+id/button_practise"
style="#style/NavigationButton"
android:layout_width="150dp"
android:layout_height="150dp"
android:text="#string/practise"
custom:diamondColor="#color/blue"/>
<za.co.####.####.DiamondShapeButton
android:id="#+id/button_tests_exams"
style="#style/NavigationButton"
android:layout_width="150dp"
android:layout_height="150dp"
android:text="#string/my_tests_exams"
custom:diamondColor="#color/orange_light"/>
<za.co.####.####.DiamondShapeButton
android:id="#+id/button_track_studies"
style="#style/NavigationButton"
android:layout_width="150dp"
android:layout_height="150dp"
android:text="#string/track_studies"
custom:diamondColor="#color/black"/>
</za.co.####.####.DiamondShapeLayout>
A View only knows about its own rectangular space, not that of the views that might be behind it. So if a View has a transparent pixel, it will only know that its own pixel is transparent, not anything about the views that may be behind it.
If you want to have a view bypass some event handling, it will need to know about the views behind it and if they wish to handle the event instead. You can't do this with pixel color of a single view - you will have to code this logic yourself based on the overall layout of the views.
I use Android studio and I have this image with a transparent background. Whenever i click on it it'll bring me to another Activity. But even when I click on the transparent part of the image it'll bring me to the other Activity.
Is it possible to make the nontransparent part clickable (or touchable) and the transparent part unclickable?
Yes this is possible but it becomes much more difficult than just adding an OnClickListener.
The trick is to use a Touch listener instead of click and on either a DOWN or UP event take the position and then either use some simple maths to work out whether it was a transparent area (if the design is a simple one) or, do some more complicated stuff to work out your pixel values at the centre.
new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
If (event.getAction() == MotionEvent.ACTION_DOWN) {
final int x = (int) event.getX();
final int y = (int) event.getY();
//now map the coords we got to the
//bitmap (because of scaling)
ImageView imageView = ((ImageView)v);
Bitmap bitmap =((BitmapDrawable)imageView.getDrawable()).getBitmap();
int pixel = bitmap.getPixel(x,y);
//now check alpha for transparency
int alpha = Color.alpha(pixel);
If (alpha != 0) {
//do whatever you would have done for your click event here
}
}
return true; //we've handled the event
}
}
UPDATE: please read entire question again :-)
Background:
I have created a grid of dots by creating a custom view and then adding these views to a TableLayout. The aim is for me to be able to draw a line from one of these dots to another dot in a way so that when a dot is pressed, a line is started from the center of the pressed dot to the point where the finger is currently touching. When the finger is dragged over another dot, the line then finishes at the center of that dot. The result being a line drawn from the center of the pressed dot to the center of the dot which was dragged over by the finger.
To create a line going over the TableLayout, I created a new custom view which just created a line between points with the canvas.drawLine() method. I then created a FrameLayout in which I put the TableLayout and the LineView. This meant the line view would be able to be drawn on top of the TableLayout.
Current Situation:
I have added touch listener in the DotView class so that it can have its own “touch feedback”. There is also another touch listener in the activity which I am trying to use to get the points needed to draw the line. The touch listeners are working fine as far as I can tell - they are not interfering with each other.
The problem is getting the correct coordinates to plot the line. I have tried a number of ways to get the coordinates of the center of the dot that was pressed (the starting point of the line), but I still have not managed it. This question, has more information: Get the coordinates of the center of a view . The second part is getting the correct end point of the line. For the purposes of this question, I would just like the end of the line to follow the position of the finger. I thought it was as easy as motionevent.getX() / getY() but this hasn’t worked. What happened instead was that there was a mix up between the coordinates on a scale relative to the layout of the dot and the coordinates relative to the whole layout/screen.
Simply put: the getX() and getY() values are incorrect, and this is what I am trying to solve here.
As shown in the screenshots, when I press down on a dot, the start point of the line is roughly in the right place, but the end point is way off. I can’t really explain why.
I have tried getRawX() and getRawY() and they return more much more accurate values, but they are still incorrect by the amount of padding (or something like that - I don’t 100% understand).
This shows my code
In my Activity :
LineView test;
FrameLayout fl;
float startPointX = 0;
float startPointY = 0;
// Removed
#Override
public boolean onTouch(View view, MotionEvent event) {
float eventX = event.getX();
float eventY = event.getY();
int[] loc = new int[2];
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (view instanceof DotView) {
DotView touchedDv = (DotView) view;
int dotColor = touchedDv.getColor();
test.setColor(dotColor);
float[] f = touchedDv.getDotCenterLocationOnScreen();
startPointX = f[0];
startPointY = f[1];
test.setPoints(startPointX, startPointY, eventX, eventY);
fl.addView(test);
}
vib.vibrate(35);
return false;
case MotionEvent.ACTION_MOVE:
test.setPoints(startPointX, startPointY, eventX, eventY);
break;
case MotionEvent.ACTION_UP:
fl.removeView(test);
return false;
default:
return false;
}
return true;
}
And finally the LineView:
public class LineView extends View {
public static final int LINE_WIDTH = 10;
Paint paint = new Paint();
float startingX, startingY, endingX, endingY;
public LineView(Context context) {
super(context);
paint.setColor(Color.MAGENTA);
paint.setStrokeWidth(LINE_WIDTH);
}
public void setPoints(float startX, float startY, float endX, float endY) {
startingX = startX;
startingY = startY;
endingX = endX;
endingY = endY;
invalidate();
}
#Override
public void onDraw(Canvas canvas) {
canvas.drawLine(startingX, startingY, endingX, endingY, paint);
}
NOTES:
I am calling the top left hand dot "dot 1".
The screenshots may not be entirely accurate as my finger moves
slightly when I take the screenshot, but the behaviour I described is
happening.
If any other information/code is wanted, I will happily provide it.
Thanks for taking the time to read this - sorry it is so long!
I have added touch listener in the DotView class so that it can have
its own “touch feedback”. There is also another touch listener in the
activity which I am trying to use to get the points needed to draw the
line. The touch listeners are working fine as far as I can tell - they
are not interfering with each other.
I don't quite see why you need both touch listener. To draw the line the touch listener on the TableLayout should be more than enough.
The problem with your code(or at least from what I've seen) is that you use the getLocationOnScreen(coordsArray) method without translating the returned values back to the coordinates system of the LineView. For example, you get the coordinates of a DotView which will be x and y. You then use this values in the LineView. But, the LineView when it will do its drawings will use its own(standard) coordinates system which places the top-left of the view at (0,0) and the coordinates will not match. Here's an example: suppose you touch the very first DotView which has a height of 50 and the y returned by the getLocationOnScreen() method is 100. You calculate the center of the DotView wich will come be at 125(100 + 50 / 2). Using this value in the LineView will be way off the normal position as the actual drawing will be done at 125, which in screen coordinates will visually translate to a y of 225 (100 returned by getLocationOnScreen() + 125).
Anyway I've made a small example using the getLocationOnScreen() method to do what you're trying to do(which you can find here).
I have set the onTouchListener on the blue part of the screen. It will only obtain the x,y coordinates when finger is touched on it. The white part does not do anything at all. The problem is that if at the beginning the finger is touched on the blue part and when it "moves out" to the white part, it is still continuing to obtain the x, y coordinates. Ideally I want the device to stop detecting the motion event as the finger leaves the screen. Hope you can help.
The easiest solution is to check if your finger is touching the View by simply comparing its x,y coordinates with the Views bounding rect. You can stop receiving events by returning false from dispatchTouchEvent then.
edit:
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
Rect outRect = new Rect();
getDrawingRect(outRect);
if (outRect.contains((int) event.getX(), (int) event.getY())) {
return true; // I want more events
} else {
return false; // stop events until next ACTION_DOWN on me
}
}
I am making a canvas and setting its background which is an image
I am adding text on it by canvas. Drawtext method which works perfectly alright
now I want these text to be clickable but i couldn't find any method
The other method I could think of was to add text box on canvas add write on click event of these text box but could not find any example related to this can anybody suggest what to do.
Canvas is a space where you can just draw some graphics, thus the only way to do what you want is detecting when the user click the surface the canvas is drawn on (e.g. a SurfaceView), and using the coordenates you just fire an event. Of course, you need to verify whether the click was done on the specific part you want (e.g. the area where you drew a button or something).
Use the onTouchEvent method. Here is an example I used for finding out if the user's click coordinates are in a List of rectangles (aka buttons):
#Override
public boolean onTouchEvent( MotionEvent event) {
super.onTouchEvent(event);
int x = (int)event.getX();
int y = (int)event.getY();
xStored = x; yStored=y;
if (event.getAction()==MotionEvent.ACTION_UP){
}else if(event.getAction()==MotionEvent.ACTION_DOWN){
System.out.println("Touching down!");
for(Rect rect : rectangles){
if(rect.contains(x,y)){
System.out.println("Touched Rectangle, start activity."+x+","+y);
invalidate();
}else{
}
}
}else if(event.getAction()==MotionEvent.ACTION_MOVE){
}
this.postInvalidate();
return true;
}