设备屏幕尺寸对缩放的ImageViews有奇怪的影响

Rob*_*ens 6 android android-layout android-imageview

更新:多个设备屏幕尺寸是一个红色鲱鱼 - 问题只是图像没有正确放大以填满屏幕 - 请参阅Ivan的回答评论.

我有一个带有一个图像的布局文件:

<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/image"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:scaleType="centerCrop" />
Run Code Online (Sandbox Code Playgroud)

然后我分配一个drawable,它很小,必须按比例放大:

setContentView(R.layout.image_story);
ImageView image = (ImageView)findViewById(R.id.image);
image.setImageDrawable(s.image);
Run Code Online (Sandbox Code Playgroud)

以下是在具有不同屏幕尺寸的两个AVD上渲染的方式.这些应该是相同的(底部的详细问题).对不起,大图像.

scaleType = centerCrop:

与centerInside

自动真空淀积:

编辑:

使用layout_height ="fill_parent"和scaleType ="centerInside"

我的2.1 AVD具有默认值,因此屏幕较小,这与预期完全一致 - 图像按比例放大以填充宽度,视图高度被包裹到缩放高度.

在具有更长屏幕的Droid Bionic和具有相同屏幕尺寸的任何AVD上,这不起作用 - 缩放图像以填充宽度,但视图被包裹到原始的预缩放图像高度,因此顶部和底部都被裁掉了.

我不知道为什么设备屏幕宽高比会对此产生影响.我已经尝试了无数的布局参数和比例类型的组合,试图让它在Bionic上运行.一切都在小屏幕上完全按预期工作,而不是在更大的屏幕上.如果我明确地设置图像高度dp,它按预期工作,但我永远不知道图像(或屏幕)的尺寸.有什么建议?

Iva*_*sov 4

这确实是一个非常好的问题。

这就是它表现得像这样的原因(来自ImageView.onMeasure(int, int) [line 661]):

// Try adjusting height to be proportional to width
if (!done && resizeHeight) {
    int newHeight = (int)((widthSize - pleft - pright)
            / desiredAspect) + ptop + pbottom;
    if (newHeight <= heightSize) { // line 661
        heightSize = newHeight;
    } // line 663
}
Run Code Online (Sandbox Code Playgroud)

它的作用是,仅当基于可绘制的宽高比的新高度和调整后的宽度(在我们的例子中,即父视图的确切宽度)小于调整后的高度(即在我们的例子中,此时只是可绘制的原始高度加上填充。如果您希望我进一步缩小这一点,请告诉我。)

我不明白的是为什么有新高度必须更小的限制。仅当我们的 heightSize 为 EXACTLY 或 AT_MOST 并且已设置为上限时才有意义。在其他情况下,没有必要这样做。

所以实际上应该有另一个调用,而不是整个 661 到 663

heightSize = resolveAdjustedSize(newHeight, mMaxHeight, heightSpec);
Run Code Online (Sandbox Code Playgroud)

确保我们只在应该限制的时候使用高度限制(即,我们在 heightSpec 中得到了 AT_MOST 限制,并且 heightSpec 中的高度值小于新高度。除非我们使用可变宽度,否则这里不会发生这种情况。)

也许,我错过了一些东西。伙计们,无论谁正在阅读本文,如果您发现其中有任何缺陷,请发表评论,特别是如果您是 Google Android 团队的一员:)

PS作为一种解决方法,我建议您实现自定义 ImageView 并重写onMeasure(int, int)以将边界设置为您的确切宽高比。如果您需要有关实际代码的帮助,请告诉我。

UPD我将写出名字来吸引 Google 的智能 Android 人员的注意(我希望这些人已经设置了 Google Alerts):Romain Guy、Roman Nurik、Reto Meier,请看一下这个讨论。