views:

62

answers:

2

Hi. I have been trying to place a view in an arbitrary location.

My aim: To overlay some rectangle of a JPG/PNG, given coordinates that relate to the JPG/PNG, with some other view, say, Gallery, or some video.

I don't want to use AbsoluteLayout, as it is depricated.

Therefore, I am using RelativeLayout, defining a dummy textbox as a placeholder, and putting my view RIGHT_TO and BELOW the textbox.

+--------+
|TextView|
|        | (x,y)
+--------+-----------------------+
         |                       |
         |     My View           |
         |                       |
         +-----------------------+

My question is: Is there a more robust and elegant way to do that?

The problem with the way suggested above, is that it's very fragile: The coordinates need to be recalculated for every new screen. My view overlays something below. It needs to be accurately placed, which is pretty difficult to do.

  • I will need to layout the screen again whenever rotated or zoomed or whatever. Worse:
    • On init time, the typical time for placing the images, the coordinates of the screen are not valid. The coordinates are valid after placing the entities on screen. In order to place the entities on screen accurately, we need coordinates. Chicken and egg problem :(
    • On rotation, the coordinates include the margins rather than the width of the view itself (example: on a portrait AVD, display a portrait ImageView, then press CTRL+F12 to rotate. The left, right, top and bottom of the ImageView are totally not as expected).
    • When Scale-Animating, coordinates are scaled.

So I would like to find a better way to do that.

Thanks
    M.
+1  A: 

Not totally understanding what you're doing, it seems like you're making extra work for yourself by using RelativeLayout. What you're trying to place on screen isn't relative to anything, it's based on a specific coordinate in the image, so even if you use one of the other layouts you're still essentially placing something in absolute coordinates.

As for AbsoluteLayout being deprecated, from what I've read it's just to discourage it's use due to it's downsides relating to variable screen sizes. They have no intention of actually removing it, and even if they did you could just get the source and compile it into your project.

Matt Hall
Yes, I agree. It's more absolute than absolute. It cries out "Absolute layout". You are obviously right that it's all about software, and the worst thing to happen is adding Absolute Layout. However, I guess I am too chicken to use deprecated. I just don't want forward compatibility problems. Thanks a lot.
Meymann
A: 

The solution is pretty ugly, it's not relative, but some may say it's plausible:

Adding a FrameLayout as a container (rather than the RelativeLayout noted below). The view to display is the child of that FrameLayout. In order to place it in place, add padding.

void addViewInAnArbitraryRect( Rect rect, 
                               Context context, 
                               View subjectView, 
                               View parent ) {
    FrameLayout container = new FrameLayout( context );
    parent.addView( container );
    container.setPadding( rect.left,
                          rect.top,
                          container.getWidth() - rect.right,
                          container.getHeight() - rect.bottom );
    container.addView( subjectView );

}

Note: You may want to adjust the coordinates of the page to the coordinates on screen. Just remember:

  1. Coordinates/width/height are not ready till onSizeChanged is called.
  2. Don't manipulate Views from onSizeChanged scope, or it may crop your view. Views do have to be manipulated from the context of the thread that created them. Use Handler for that.

I hoped it helped somebody.

Meymann

Meymann