I want to get the coordinate positions of a button in my application.I used the following method.But its not working.Please help.
public Point currentPosition(View view)
{
int[] loc = new int[2];
view.getLocationOnScreen(loc);
int x = loc[0];
int y=loc[1];
Toast.makeText(getApplicationContext(),"coordinate is"+x+","+y,Toast.LENGTH_SHORT).show();
return new Point(loc[0], loc[1]);
}
Also i used this
btn_show.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View arg0)
{
int x = (int)btn_show.getX();
int y= (int)btn_show.getY();
Toast.makeText(getApplicationContext(), "button x is......"+x,Toast.LENGTH_SHORT ).show();
Toast.makeText(getApplicationContext(), "button y is......"+y,Toast.LENGTH_SHORT ).show();
}
});
The method you use expect integer values as references of R.string.whatever. Cast the getTop() return value to String should work.
Toast.makeText(MainActivity.this, String.valueOf(button1.getTop()), Toast.LENGTH_LONG).show();
To get the x/y of the button (since API 11):
Toast.makeText(MainActivity.this, (int)button1.getX() + ":" + (int)button1.getY(), Toast.LENGTH_LONG).show();
Doc:
The visual x position of this view, in pixels.
For API below 11 you are on the right way: getTop() is the equivalent of getY() but without a possible animation/translation. getLeft() is the quivalent of getX() with the same restriction.
or
You can use View.getTop(), View.getBottom(), View.getLeft(), and View.getRight(). These will return the location of the top, bottom, left and right edge of the View relative to the parent.
or Use
View.getLocationOnScreen()
and/or
getLocationInWindow().
If you are using onTouch lister means use this one.
code for your onTouch method:
float screenX = v.getLeft() + event.getX(); // X in Screen Coordinates
float screenY = v.getTop() + event.getY(); // Y in Screen Coordinates
You have to wait until the View is measured, otherwise it will always return 0. Use an OnGlobalLayoutListener:
view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
public void onGlobalLayout() {
int x = view.getLeft();
int y = view.getTop();
}
});
There are a lot of ways to get the coordinator position.
If you want to center a floating button such as a tutorial with tourguide library.
I suggest create this method
public Rect getRectFromAView(View view){
Rect rect=new Rect(); // create a new rect
view.getGlobalRect(rect);// draw the rect
return rect;
}
If I want to get the coordinate position of x or y
Rect rect=getREctFromAView(view);
rect.exactCenterX(); //Return the position X
rect.exactCenterY(); //Return the position Y
This is the case when I try to get the center position of a view.
try :-
float x = button.getX();
float y = button.getY();
Related
I have a code where some circles are drawn automatically after passing the image to a function an some are drawn manually using drawcircle(). Now, I want to see that when the user touches a point, if there is already a circle there, then hide/remove it.
Any leads please?
If all circle are drown by you by draw circle . Then store the coordinates of all circles in a list and on then check the the clicked position by Region . If region contains the coordinate then click is inside the circle otherwise its outside somewhere on Canvas.Below is an example it returns the index of clicked circle .
private int findPointAt(int x, int y) {
if(dotsList!=null) {
if (dotsList.isEmpty()) {
return -1;
}
final int width = circleRadius * 2;
final Region r = new Region();
for (int i = 0; i < dotsList.size(); i++) {
final int pointX = dotsList.get(i).x;
final int pointY = dotsList.get(i).y;
r.set(pointX - width, pointY - width, pointX + width, pointY + width);
if (r.contains(x, y)) {
selectedPosition = i;
return i;
}
}
}
return -1;
}
if returns -1 then click is outside otherwise index of circle is returned .
What I am doing:
I am trying to create a button dynamically onTouch
What is Happening:
I am able to create the button but the button is not created exactly
in the place I touch, instead its little bit in the bottom
right(might be adjustment of button in pixel).
How can i make sure i create the button exactly in the same place i
touch
#Override
public boolean onTouch(View v, MotionEvent event) {
//Get the x & y co-ordinates from the event
float x = event.getX();
float y = event.getY();
//Convert into Integer
int mX = (int) x;
int mY = (int) y;
//Perform Event on touch of canvas
performEventOnTouchOfCanvas(event, mX, mY);
return true;
}
private void performEventOnTouchOfCanvas(MotionEvent event,int mX, int mY) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Point mPoint=new Point(mX,mY);
createButton(mPoint.x,mPoint.y);
break;
}
}
private void createButton(float x, float y) {
Button btn = new Button(ActDrawAreaTwo.this);
RelativeLayout.LayoutParams bp = new RelativeLayout.LayoutParams(40, 40);
bp.leftMargin = (int) x;
bp.topMargin = (int) y;
//Assign the Id to the button
btn.setLayoutParams(bp);
CommonFunctions.setBackgroundDrawable(btn, ActDrawAreaTwo.this, R.drawable.white_circle_dot);//Set Button Drawable
String mTag=String.valueOf((int)x )+","+ String.valueOf((int) y);
btn.setTag(mTag);
canvasLayoutId.addView(btn);
}
Note: canvasLayoutId is a relative layout
Android start drawing from views topmost left side. So when you pass coordinates, it will assume those are topmost left side of the button. If you want your button to appear in the middle of where you touch you need to change your coordinates with these:
x = x + button_width / 2
y = y + button_height / 2
In Android default padding is also same button's border, so you can find button's width and height with using this:
button_width = mButton.getPaddingRight() - mButton.getPaddingLeft();
button_height = mButton.getPaddingBottom() - mButton.getPaddingTop();
You can also use button.getWidth() and button.getHeight() assuming you are not using MATCH_PARENT or WRAP_CONTENT as your paramters.
I have a gridview that I need to implement drag and drop feature. I've been trying to find a possible solution or existing library that would fit my problem but still no luck.
Here's a before and after illustration of the drag and drop that I need to implement:
The red tiles are items wherein they cannot be dragged nor dropped on. the blue ones are draggable and can be dropped on any tile on any row, just not on the red tiles. The white tiles are just placeholders which are placed to have the red tiles on the first column.
Now, when tile A is dragged on the 3rd row, as you can see, they go side by side, not swapped, even if put on top of tile C. The number of white tiles is depending on the number of blue tiles per row, an arraylist is assigned on each row, so it'll just follow. My real problem is that all examples on gridview drag and drop is that tiles swaps or the whole grid follows the flow of items.
My plan to implement this:
When long pressed on a tile to be dragged, it will show a tile that looks like that tile, only larger and lesser opacity.
When dropped on a certain position, will compute for the row.
Adjust arraylists and notifydatasetchanged.
Here's breaking down the problem to slightly smaller problems:
How can I make a larger tile of the long pressed tile?
Is it possible to get the position where the enlarged tile is dropped?
1.How can I make a larger tile of the long pressed tile? yes,you can get the tile's view and create a new bitmap,the add the bitmap to Windows.Like this : it's a class extends GridView.
public boolean setOnItemLongClickListener(final MotionEvent ev)
{
this.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener()
{
#Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
int arg2, long arg3)
{
// onInterceptTouchEvent(ev);
// TODO Auto-generated method stub
L.l("============on Long Click=========");
L.l("============X:" + ev.getX() + " Y:" + ev.getY());
int x = (int) ev.getX();
int y = (int) ev.getY();
dragPosition = dropPosition = pointToPosition(x, y);
System.out.println(dragPosition);
if (dragPosition == AdapterView.INVALID_POSITION)
{
}
ViewGroup itemView = (ViewGroup) getChildAt(dragPosition
- getFirstVisiblePosition());
dragPointX = x - itemView.getLeft();
dragPointY = y - itemView.getTop();
dragOffsetX = (int) (ev.getRawX() - x);
dragOffsetY = (int) (ev.getRawY() - y);
itemHeight=itemView.getHeight();
L.l("========================y:" + y + " getRawY:"
+ ev.getRawY());
itemView.destroyDrawingCache();
itemView.setDrawingCacheEnabled(true);
Bitmap bm = Bitmap.createBitmap(itemView.getDrawingCache());
startDrag(bm, x, y);
return false;
};
});
return super.onInterceptTouchEvent(ev);
}
private void startDrag(Bitmap bm, int x, int y)
{
windowParams = new WindowManager.LayoutParams();
windowParams.gravity = Gravity.TOP | Gravity.LEFT;// 这个必须加
windowParams.x = x - dragPointX + dragOffsetX;
windowParams.y = y - dragPointY + dragOffsetY;
windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
windowParams.format = PixelFormat.TRANSLUCENT;
windowParams.windowAnimations = 0;
ImageView iv = new ImageView(getContext());
iv.setImageBitmap(bm);
windowManager = (WindowManager) getContext().getSystemService(
Context.WINDOW_SERVICE);// "window"
windowManager.addView(iv, windowParams);
dragImageView = iv;
}
#Override
public boolean onTouchEvent(MotionEvent ev)
{
if (dragImageView != null
&& dragPosition != AdapterView.INVALID_POSITION)
{
int x = (int) ev.getX();
int y = (int) ev.getY();
switch (ev.getAction())
{
case MotionEvent.ACTION_MOVE:
onDrag(x, y);
break;
case MotionEvent.ACTION_UP:
stopDrag();
onDrop(x, y);
break;
}
}
return super.onTouchEvent(ev);
}
private void onDrag(int x, int y)
{
if (dragImageView != null)
{
windowParams.alpha = 0.6f;
windowParams.x = x - dragPointX + dragOffsetX;
windowParams.y = y - dragPointY + dragOffsetY;
// L.l("=================windowParams.y=====000========"+windowParams.y);
windowManager.updateViewLayout(dragImageView, windowParams);
}
int tempScrollX = x - dragPointX + dragOffsetX;
int tempScrollY = y - dragPointY + dragOffsetY;
if (tempScrollY +itemHeight> 600)
{
this.scrollTo(0, tempScrollY);
}
else
if (pointToPosition(x, y) > 2)
{
this.scrollTo(0, tempScrollY - 300);
}
}
2.Is it possible to get the position where the enlarged tile is dropped?
If your class is extends GridView or AbsListView,this API `pointToPosition(x, y) will return the position of the whole view.
When you drop tile A,then you calculate where tile A is now,if above tile C,then start a Animation(C move to side and A take place position of C) and update the Adapter end of the Animation.
I ended up editting http://code.google.com/p/android-gridview-drag-and-drop/ to fit my problem.
Hello i would like to ask, how can i Display Toast near the user click point Like on image below using GraphView library:
http://android-graphview.org/
Thanks for any advice
EDIT:
I tried it using
seriesSin = new GraphViewSeries("Sinus curve", new GraphViewSeries.GraphViewSeriesStyle(Color.rgb(200, 50, 00), 3), data);
// SET ON TOUCH
graphView.setOnTouchListener(new View.OnTouchListener(){
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
int size = seriesSin.size();
float screenX = event.getX();
float screenY = event.getY();
float width_x = v.getWidth();
float viewX = screenX - v.getLeft();
float viewY = screenY - v.getTop();
float percent_x = (viewX/width_x);
int pos = (int) (size*percent_x);
System.out.println("X: " + viewX + " Y: " + viewY +" Percent = " +percent_x);
System.out.println("YVal = " +seriesSin.getY(pos));
return true;
}
return false;
}
});
But I cannot to get seriesSin.size and seriesSin.getY(pos)
You can't decide where to display the Toast. However, you could set up a custom view and show it using the coordinates (x and y) you get when detecting the touch. When you show the view, simply use those values to set up the layout params of the view, and voila.
Version 4.0.0 added an onTap() listener, that replicates your onTouch method above, it doesn't solve your Toast positioning issue, but could save you a few lines of code.
Can I get a View's x and y position relative to the root layout of my Activity in Android?
The Android API already provides a method to achieve that.
Try this:
Rect offsetViewBounds = new Rect();
//returns the visible bounds
childView.getDrawingRect(offsetViewBounds);
// calculates the relative coordinates to the parent
parentViewGroup.offsetDescendantRectToMyCoords(childView, offsetViewBounds);
int relativeTop = offsetViewBounds.top;
int relativeLeft = offsetViewBounds.left;
Here is the doc
This is one solution, though since APIs change over time and there may be other ways of doing it, make sure to check the other answers. One claims to be faster, and another claims to be easier.
private int getRelativeLeft(View myView) {
if (myView.getParent() == myView.getRootView())
return myView.getLeft();
else
return myView.getLeft() + getRelativeLeft((View) myView.getParent());
}
private int getRelativeTop(View myView) {
if (myView.getParent() == myView.getRootView())
return myView.getTop();
else
return myView.getTop() + getRelativeTop((View) myView.getParent());
}
Let me know if that works.
It should recursively just add the top and left positions from each parent container.
You could also implement it with a Point if you wanted.
Please use view.getLocationOnScreen(int[] location); (see Javadocs). The answer is in the integer array (x = location[0] and y = location[1]).
View rootLayout = view.getRootView().findViewById(android.R.id.content);
int[] viewLocation = new int[2];
view.getLocationInWindow(viewLocation);
int[] rootLocation = new int[2];
rootLayout.getLocationInWindow(rootLocation);
int relativeLeft = viewLocation[0] - rootLocation[0];
int relativeTop = viewLocation[1] - rootLocation[1];
First I get the root layout then calculate the coordinates difference with the view.
You can also use the getLocationOnScreen() instead of getLocationInWindow().
No need to calculate it manually.
Just use getGlobalVisibleRect like so:
Rect myViewRect = new Rect();
myView.getGlobalVisibleRect(myViewRect);
float x = myViewRect.left;
float y = myViewRect.top;
Also note that for the centre coordinates, rather than something like:
...
float two = (float) 2
float cx = myViewRect.left + myView.getWidth() / two;
float cy = myViewRect.top + myView.getHeight() / two;
You can just do:
float cx = myViewRect.exactCenterX();
float cy = myViewRect.exactCenterY();
You can use `
view.getLocationOnScreen(int[] location)
;` to get location of your view correctly.
But there is a catch if you use it before layout has been inflated you will get wrong position.
Solution to this problem is adding ViewTreeObserver like this :-
Declare globally the array to store x y position of your view
int[] img_coordinates = new int[2];
and then add ViewTreeObserver on your parent layout to get callback for layout inflation and only then fetch position of view otherwise you will get wrong x y coordinates
// set a global layout listener which will be called when the layout pass is completed and the view is drawn
parentViewGroup.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
//Remove the listener before proceeding
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
parentViewGroup.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
parentViewGroup.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
// measure your views here
fab.getLocationOnScreen(img_coordinates);
}
}
);
and then use it like this
xposition = img_coordinates[0];
yposition = img_coordinates[1];
I wrote myself two utility methods that seem to work in most conditions, handling scroll, translation and scaling, but not rotation. I did this after trying to use offsetDescendantRectToMyCoords() in the framework, which had inconsistent accuracy. It worked in some cases but gave wrong results in others.
"point" is a float array with two elements (the x & y coordinates), "ancestor" is a viewgroup somewhere above the "descendant" in the tree hierarchy.
First a method that goes from descendant coordinates to ancestor:
public static void transformToAncestor(float[] point, final View ancestor, final View descendant) {
final float scrollX = descendant.getScrollX();
final float scrollY = descendant.getScrollY();
final float left = descendant.getLeft();
final float top = descendant.getTop();
final float px = descendant.getPivotX();
final float py = descendant.getPivotY();
final float tx = descendant.getTranslationX();
final float ty = descendant.getTranslationY();
final float sx = descendant.getScaleX();
final float sy = descendant.getScaleY();
point[0] = left + px + (point[0] - px) * sx + tx - scrollX;
point[1] = top + py + (point[1] - py) * sy + ty - scrollY;
ViewParent parent = descendant.getParent();
if (descendant != ancestor && parent != ancestor && parent instanceof View) {
transformToAncestor(point, ancestor, (View) parent);
}
}
Next the inverse, from ancestor to descendant:
public static void transformToDescendant(float[] point, final View ancestor, final View descendant) {
ViewParent parent = descendant.getParent();
if (descendant != ancestor && parent != ancestor && parent instanceof View) {
transformToDescendant(point, ancestor, (View) parent);
}
final float scrollX = descendant.getScrollX();
final float scrollY = descendant.getScrollY();
final float left = descendant.getLeft();
final float top = descendant.getTop();
final float px = descendant.getPivotX();
final float py = descendant.getPivotY();
final float tx = descendant.getTranslationX();
final float ty = descendant.getTranslationY();
final float sx = descendant.getScaleX();
final float sy = descendant.getScaleY();
point[0] = px + (point[0] + scrollX - left - tx - px) / sx;
point[1] = py + (point[1] + scrollY - top - ty - py) / sy;
}
Incase someone is still trying to figure this out. This is how you get the center X and Y of the view.
int pos[] = new int[2];
view.getLocationOnScreen(pos);
int centerX = pos[0] + view.getMeasuredWidth() / 2;
int centerY = pos[1] + view.getMeasuredHeight() / 2;
I just found the answer here
It says:
It is possible to retrieve the location of a view by invoking the methods getLeft() and getTop(). The former returns the left, or X, coordinate of the rectangle representing the view. The latter returns the top, or Y, coordinate of the rectangle representing the view. These methods both return the location of the view relative to its parent. For instance, when getLeft() returns 20, that means the view is located 20 pixels to the right of the left edge of its direct parent.
so use:
view.getLeft(); // to get the location of X from left to right
view.getRight()+; // to get the location of Y from right to left
You can use the following the get the difference between parent and the view you interested in:
private int getRelativeTop(View view) {
final View parent = (View) view.getParent();
int[] parentLocation = new int[2];
int[] viewLocation = new int[2];
view.getLocationOnScreen(viewLocation);
parent.getLocationOnScreen(parentLocation);
return viewLocation[1] - parentLocation[1];
}
Dont forget to call it after the view is drawn:
timeIndicator.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
final int relativeTop = getRelativeTop(timeIndicator);
});