Reputation: 186
I have an RelativeLayout that contains a custom ImageView, the scaleType="centerInside", I load in a bitmap (usually smaller than the imageView). How can I get the top/left position of where the bitmap was drawn? I need to be able addView's on top a positions relative to the bitmap.
RelativeLayout view = (RelativeLayout) inflater.inflate(R.layout.scroll_scaled, container, false);
ContentImageView image = (ContentImageView) view.findViewById(R.id.base_page);
Bitmap bm = mInterfaceActivity.getPageImage(mPageNumber);
image.setImageBitmap(bm);`
The layout file scrolled_scaled
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:scaleType="centerInside"
android:id="@+id/base_page"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ff00ff00"
android:contentDescription="@string/product_page"
android:src="@android:drawable/ic_menu_report_image" >
</ImageView>
</RelativeLayout>
Upvotes: 5
Views: 8182
Reputation: 16429
This method returns the bounds of image inside imageView.
/**
* Helper method to get the bounds of image inside the imageView.
*
* @param imageView the imageView.
* @return bounding rectangle of the image.
*/
public static RectF getImageBounds(ImageView imageView) {
RectF bounds = new RectF();
Drawable drawable = imageView.getDrawable();
if (drawable != null) {
imageView.getImageMatrix().mapRect(bounds, new RectF(drawable.getBounds()));
}
return bounds;
}
Upvotes: 3
Reputation: 186
Ended up with a two part solution, based on the feedback and a bit of retry.
I created the subviews an added them to the RelativeLayout in "approximate" position, but as View.INVISIBLE.
I super-classed the RelativeLayout ViewGroup and in the onLayout I walked the list of child views and put them in the "proper" place as I now had the RelativeLayout self-aware of its expanded size.
Seems clunky, but it works.
Thanks to all for the suggestions, my solution was taking pieces of everyones advice.
Upvotes: 0
Reputation: 12745
UPDATE 2: getX and getY will return 0 if you're using unspecified width and height (e.g. wrap_content). Instead of iv.getX()
and iv.getY()
replace that with the answer to this question: Getting View's coordinates relative to the root layout then add the bounds of the image to those values.
You can do this by adding the ImageView's position to the top left bound of the drawable inside. Something like this:
ImageView iv = (ImageView)findViewById(R.id.image_view);
Drawable d = iv.getDrawable();
Rect bounds = d.getBounds();
int top = iv.getY() + bounds.top;
int left = iv.getX() + bounds.left;
UPDATE: For images that are scaled, you'll have to multiply the top and left coords by the image scale to get more accurate positioning. You can do that like this:
Matrix m = iv.getImageMatrix();
float[] values = new float[9];
m.getValues(values);
float scaleX = values[Matrix.MSCALE_X];
float scaleY = values[Matrix.MSCALE_Y];
Then you'd have to multiply top by scaleY and the left by scaleX.
Upvotes: 1
Reputation: 4337
You'll need to do the math yourself using the bounds of the Drawable.
ImageView test = (ImageView) findViewById(R.id.base_page);
Rect bounds = test.getDrawable().getBounds();
int x = (test.getWidth() - bounds.right) / 2;
int y = (test.getHeight() - bounds.bottom) / 2;
First we calculate the space in the View that is not being used by the image. Then since it is centered the extra space is evenly distributed before and after the image so it is draw half of that length into the View
.
These numbers are relative to the location of the View but you can add the views X and Y if you need you.
Upvotes: 3