当容器视图以centerInside方式缩放时,查找Android ImageView中位图的位置

5

我有一个RelativeLayout布局,其中包含一个自定义的ImageView,其scaleType属性为"centerInside",我加载了一张位图(通常比imageView小)。如何获取位图绘制的左上角位置?我需要能够在相对于位图位置的顶部/左侧添加视图。

解决方案:可以使用ImageView的getImageMatrix()方法获取绘制位图的矩阵,然后通过Matrix的mapRect方法将ImageView中的矩形映射到位图坐标系中,从而得到位图的位置信息。

   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);`

布局文件 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>
4个回答

3

这个方法返回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;
}

3

您需要使用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;

首先,我们计算View中未被图像占用的空间。然后,由于它居中,额外的空间会在图像前后平均分布,因此将其绘制到View的一半长度。

这些数字是相对于视图位置的,但如果需要,可以添加视图的X和Y。

它不工作了,伙计 :( 我在test.getdrable().getBounds()上得到了空指针异常。 - Ahmad Arslan
@ArslanAhmad 我认为你遇到的错误超出了这个问题的范围。我建议你开一个新的问题来确定为什么那是空的。在此之前,我建议你实际确定该命令的哪一部分为空(是test == null还是test.getDrawable() == null)。 - Fr33dan

1

更新2:如果您使用未指定宽度和高度(例如wrap_content),则getX和getY将返回0。请用此问题的答案替换iv.getX()iv.getY()Getting View's coordinates relative to the root layout,然后将图像的边界添加到这些值中。

您可以通过将ImageView的位置添加到内部可绘制对象的左上边界来实现此目的。类似于以下内容:

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;

更新:对于缩放的图像,您需要将顶部和左侧坐标乘以图像比例以获得更准确的定位。您可以按照以下方式执行:

Matrix m = iv.getImageMatrix();
float[] values = new float[9];
m.getValues(values);
float scaleX = values[Matrix.MSCALE_X];
float scaleY = values[Matrix.MSCALE_Y];

然后你需要将顶部乘以scaleY,左侧乘以scaleX。


没有起作用。我认为此时我的ViewGroup还没有完成膨胀,因此“top”和“left”值都为零。 - user1603721
查看更新后的答案,获取视图顶部和左侧坐标的更好方法。 - Michael Celey
您的回答假设边界将具有与它们相对于View绘制的位置相匹配的上部和左部值。然而,事实并非如此。它们始终为0。 - Fr33dan
它们并不总是对所有情况都为0。我在ImageView中使用图像的顶部和左侧边界来限制捏合缩放中的图像平移。可以在此处找到可行的代码:https://dev59.com/j-o6XIcBkEYKwwoYTS1D#11615173在这种情况下,可能还没有调用onLayout,因此边界为0。如果是这种情况,请延迟获取位置,直到调用onLayout之后再获取。 - Michael Celey
Fr33dan是正确的,顶部/左侧仍然为零。我正在加载“base_page”,希望将其覆盖在上面。MCeley我可以等到onLayout被调用,但我怎么知道这是什么时候发生的? - user1603721
显示剩余2条评论

0

最终采用了两部分的解决方案,基于反馈和一些重试。

我创建了子视图并将它们添加到RelativeLayout中的“近似”位置,但是作为View.INVISIBLE。

我对RelativeLayout ViewGroup进行了超类处理,在onLayout中遍历了子视图列表,并将它们放置在“正确”的位置上,因为现在RelativeLayout已经意识到其扩展大小。

看起来有点笨重,但它确实有效。

感谢所有人的建议,我的解决方案是采纳了每个人的建议。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接