【问题标题】:Device screen dimension has weird effect on scaled ImageViews设备屏幕尺寸对缩放的 ImageView 有奇怪的影响
【发布时间】:2012-02-10 19:00:40
【问题描述】:

更新: 多设备屏幕尺寸是一个红鲱鱼 - 问题只是图像没有正确放大以填充屏幕 - 请参阅伊万回答中的 cmets。

我有一个包含一张图片的布局文件:

<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" />

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

setContentView(R.layout.image_story);
ImageView image = (ImageView)findViewById(R.id.image);
image.setImageDrawable(s.image);

这是它在两个具有不同屏幕尺寸的 AVD 上的呈现方式。这些应该是相同的(底部的详细问题)。抱歉,图片太大了。

使用 scaleType=centerCrop:

居中

AVD:

编辑:

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

我有一个带有默认值的 2.1 AVD,所以屏幕更小,这完全符合预期 - 图像被放大以填充宽度,视图高度被包裹到缩放高度。

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

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

【问题讨论】:

  • 屏幕截图可能会有所帮助,因为我不太确定我在描绘正确的东西。
  • 添加了屏幕截图 - 这有帮助吗?较小的屏幕在放大图像时给出了预期的结果。较大的是使用未缩放的大小来调整 ImageView 的大小。
  • 您确定要 layout_height=wrap_content 吗?
  • 我希望ImageView 的高度不大于缩放后的图像,因为最终版本将在图像下方有更多视图,所以我相信是的。我已经用 height=fill_parent 的截图更新了这个问题,因为它也不能正常工作。
  • 问题是什么?请写在你的文章末尾

标签: android android-layout android-imageview


【解决方案1】:

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

这就是它表现得那样的原因(来自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
}

它的作用是仅当基于可绘制对象的纵横比和调整后的宽度(在我们的例子中,即父视图的确切宽度)的新高度小于 时,它才会调整视图的高度 比调整后的高度(在我们的例子中,这只是 drawable 的本机高度加上填充。如果你想让我进一步降低这一点,请告诉我。)

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

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

heightSize = resolveAdjustedSize(newHeight, mMaxHeight, heightSpec);

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

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

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

UPD 我要写出一些名字来吸引 Google 的聪明 android 人的注意(我希望这些人设置了 Google 警报):Romain Guy、Roman Nurik、Reto Meier ,请看一下这个讨论。

【讨论】:

  • 事实上,只有newHeight小于heightSize才有意义,否则(如果更大)我们会通过代码调整宽度这是之前的几行。
  • 对不起,我不明白。上面有一个部分调整宽度,但它只调整newWidth,在我发布的文章中没有使用,所以它不会补偿newHeight大于高度大小。此外,该部分实际上取决于宽度受 layout_width 属性约束的方式。如果 layout_with="fill_parent",宽度调整部分将永远不会被执行,因为 resizeWidth 将始终为 false。尽管如此,我们仍然需要调整高度,我不明白为什么只有在 newHeight 小于 heightSize 的情况下。我错过了什么吗?
  • This part of code 确实调整了widthSize。请注意,如果done 设置为true,则不会执行高度调整。
  • 是的,没错。但是只有当resizeWidthtrue 时才会执行该部分,而在我们的例子中它不是 - 因为android:layout_width="fill_parent" resizeWidth 在line 608 上设置为false。所以,done 没有设置为trueresolveAdjustedSize()widthSize 设置为widthMeasureSpec 中的内容(在我们的例子中是屏幕的宽度)。因此,newHeight 获得屏幕宽度除以图像纵横比的值,但由于第 661 行的 if 子句而没有设置
  • 这里唯一的薄弱环节是fill_parent 导致widthMeasureSpec 的模式为EXACTLY。我不是百分百确定。
【解决方案2】:

据我了解,您需要缩放图像以保持其纵横比。 scaleType="fitCenter" 应该会给你想要的行为:

<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="fitCenter" />

如果没有帮助,请尝试将其添加到清单文件中:

<supports-screens
    android:resizeable="true"
    android:smallScreens="true"
    android:normalScreens="true"
    android:largeScreens="true"
    android:anyDensity="true" />

【讨论】:

  • fitCenter 不会放大图像,只是以原始尺寸显示在屏幕顶部(如大的“fill_parent”和 scaleType="centerInside",但在顶部屏幕)。在清单中添加supports-screens 似乎没有效果。
  • 您是否尝试过将您的ImageView 包装到某个布局中(例如LinearLayout),然后为此布局调用setContentView(..)?我会尝试不同的布局和布局参数组合。
  • 是的,还没有找到合适的组合。否则我在布局文件上使用setContentView,只有ImageView 用于测试,这似乎与带有单个子元素的LinearLayout 相同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-25
相关资源
最近更新 更多