I have a custom ImageView and in the OnDraw I have added some bitmap overlays. I can capture the click event for any overlay using action up type event in the OnTouchEvent callback. The thing is for me to display a popup window I must supply a view anchor for the popup window to show but I am using the bitmaps as anchors not a particular view, so I am stuck. I cannot find any sollution on the web regarding this issue. Passing the parent ImageView and adding the overlay x-y offsets (with Gravity.NO_GRAVITY) are not producing the desired result(Also the window arrow will not point correctly).
Use PopupWindow.showAtLocation
The problem is that x/y params into that function is offset relative to Window, to which anchor view belongs. You can see it clearly from function's source, where nothing from 'parent' is used except of its window token.
public void showAtLocation(View parent, int gravity, int x, int y) {
showAtLocation(parent.getWindowToken(), gravity, x, y);
}
So to make your offsets good, you have to determine anchor's position relative to its window.
For this, use
Rect rc = new Rect();
View.getWindowVisibleDisplayFrame(rc);
int[] xy = new int[2];
View.getLocationInWindow(xy);
rc.offset(xy[0], xy[1]);
now you have
inx x = rc.left, y = rc.top;
This is point of your ImageView's left-top corner relative to its window.
Finally show your PopupWindow at location relative to this point, and it should display correctly on top of your ImageView.
You referring to the below kind of view right...I would suggest you to follow the below link and implement the same in your case as well..If found difficult post ur comment and will get back to you..MAPViewBallons
Related
I need the user to drag an arrow between two views, but all info I can find online is to make a dragshadow.
here's an exemple of the result i need.
https://imgur.com/pfQxtSK
thanks in advance.
What you want requires you to observe touch events inside of your parent ViewGroup, or custom view (whatever is drawing the light-blue grid from the image), using onTouchEvent(MotionEvent) callback. Next, you wanna determine the direction of the drag using the MotionEvent's x and y coordinates and some basic trigonometry. This will allow you to determine the angle of the drag and therefore dynamically the adjust the angle (rotation) of your arrow so that it accurately tracks the finger. Next use the same x and y coordinates you got from the MotionEvent to determine where on the canvas to draw the arrow. If the arrow is another view added as a child, you can set that view's x and y coordinates or translate the view using methods provided by the View class (you may need to play with offset's so the view doesn't get drawn off-screen after several drags/touches). If the arrow is a bitmap our drawable, you will need to adjust the draw coordinates in your view's onDraw(Canvas) method.
popupwindow_obj.showAsDropDown(clickbtn, -40, 18); // where u want show on view click event popupwindow.showAsDropDown(view, x, y);
Why is it that it is needed to specify absolute x and y co-ordinate values for pop up window object to be shown as drop down? Why does it eventhough not automatically show nearby of the control item that has been clicked enough, only for a one single time all though, once upon a time?
Thank you in advance.
From the android docs:
without cords
void showAsDropDown(View anchor) Display the content view in a popup
window anchored to the bottom-left corner of the anchor view.
with cords:
void showAsDropDown(View anchor, int xoff, int yoff) Display the
content view in a popup window anchored to the bottom-left corner of
the anchor view offset by the specified x and y coordinates.
From these 2 methods we can learn that there are 2 (actually 3) showAsDropDown methods.
The one without cords will do what you want automatically in the bottom-left corner. And the one with cords will just take some offset from the bottom-left corner. the offset will be determined by you (int xoff, int yoff), xoff stands for x offset and yoff stands for y offset.
Source
Does anyone know why when I use this code:
popupMenu.showAtLocation(containerView, Gravity.BOTTOM|Gravity.LEFT, x_offset, y_offset);
The y offset doesn't actually move the popup until it's greater than a certain number (in this case approx 120). For values under 120, nothing happens; for values over 120, the popup moves vertically up.
I'm guessing it's to do with the size of the popup, for which there doesn't seem to be a way to actually get the dimensions of to compensate for this threshold.
I'd like to know because a) there's scant information about this method, and b) I can't seem to get it to work to position my popup correctly.
Pretty old question but I would like to mention here that in case if anyone else is wondering what is the threshold for the yOffset - it is the top insets of the view you are passing to the showAtLocation() method.
In most cases this is your system bar height.
You can try to calculate the yOffset by
int desiredOffsetPx = 250;
int yOffset = desiredOffsetPx + systemWindowInsetTop
popupWindow.showAtLocation(view, Gravity.BOTTOM, 0, yOffset)
In order to get systemWindowInsetTop please check this answer
void showAtLocation (View parent,
int gravity,
int x,
int y)
Display the content view in a popup window at the specified location. If the popup window cannot fit on screen, it will be clipped. See WindowManager.LayoutParams for more information on how gravity and the x and y parameters are related. Specifying a gravity of NO_GRAVITY is similar to specifying Gravity.LEFT | Gravity.TOP.
You can find whole detail on this link : deveoper.android.com
I know I can use:
myPopup.showAtLocation(layout, Gravity.NO_GRAVITY, x, y);
// OR
myPopup.showAtLocation(layout, Gravity.TOP|Gravity.LEFT, x, y);
To open a PopupWindow that's drawn from [x, y] as the Top-Left of the PopupWindow, drawn towards to Bottom-Right.
What I want instead however, is to draw from [x, y] as the Top-Right of the PopupWindow, drawn towards the Bottom-Left.
Here is a picture to make it more clear (The dot is my [x, y] position and the rectangle is my PopupWindow. The first picture shows how it's normally done, and the second is what I want to achieve.):
So how do I correctly calculate the x and y of the second picture's gray point's location, while knowing the black point's location? I know the y can stay the same, but the x should be changed to something like:
x minus PopupWindow-width
The problem is that the PopupWindow's width and height are both set to wrap_content, so I don't know the size until after I draw it.
Does this mean I have to draw it (but make it invisible at first), then calculate the new x with the PopupWindow's MeasuredWidth in it's ViewTreeObserver's OnGlobalLayoutListener (to know when it's done rendering and the MeasuredWidth is known), then apply this new x and then make it Visible? Or is there an easier way to just let it draw at the correct position?
PS: I've also changed Gravity.NO_GRAVITY to Gravity.TOP|Gravity.RIGHT, if the PopupWindow is out of the screen it will automatically place it at the border of the Right/Top side (whichever side it's out of the screen).
You could get the size of your popup window by overriding the onMeasure method of the popup window (note that you have to subclass a View in order to do this). After that, you can calculate the offset of the x and y coordinates. Hope this helps.
I can easily use the following code to scroll the view to the left using
TouchUtils.dragViewToX(this, myView, Gravity.LEFT, -1000);
It will even just sit there for a second if it can't scroll anymore, like it's still trying to, which is the expected behavior, so the contents of the view shouldn't be the issue.
But if I do the opposite, it acts as though it's not even there.
TouchUtils.dragViewToX(this, myView, Gravity.LEFT, 1000);
It doesn't even pause for a second to simulate the dragging like the other one will no matter what. It even returns the propper pixel value for distance covered! Why will it only listen to this function when it's supplied with a negative value? Why will it not drag in the opposite direction?
It's not even a positive/negative issue, it will scroll to the left if I supply a positive value and a different Gravity (like RIGHT or END), but no matter what it won't scroll to the right.
First of all, dragViewToX will try to drag the view you specify to the X-coordinate you specify.
The Gravity field specifies which part of the view is to be dragged.
So I'd suggest you use the rect values rather that using hard coded coordinates so that the test will work independent of the device specification. Here's a sample code.
View view = sListView.findViewById(R.id.foo);
Rect rect = new Rect();
view.getHitRect(rect);
TouchUtils.dragViewToX(this, view, Gravity.CENTER, rect.left); // To drag left. Make sure the view is to the right of rect.left
TouchUtils.dragViewToX(this, view, Gravity.CENTER, rect.right); // To drag left. Make sure the view is to the left of rect.right
The only thing that is wrong with your code is that the value 1000 is already out of the screen and therefore there is no where to drag to :)