【问题标题】:Setting ImageView ScaleType to "center" is not working as I expect it将 ImageView ScaleType 设置为“中心”无法正常工作
【发布时间】:2011-12-10 02:57:46
【问题描述】:

我的ImageView 有以下布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:descendantFocusability="blocksDescendants">
    <ImageView
        android:id="@+id/imageview_icon"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:scaleType="fitCenter" />
    (...)
</LinearLayout>

48dp 分别等于 ldpimdpihdpi 中的 36px、48px 和 72px。这个ImageView 中将使用的所有图像基本上都是图标,我在网上找到了我想要的应用程序(免费许可)。但不幸的是,它没有提供大于 48px 的图像,并且使用不同的图像是不可能的。所以我需要一个新的解决方案...

目前我在 ldpimdpi 文件夹中分别有 36 像素和 48 像素的图像。但是我遇到了hdpi 的问题。对于在hdpi 上运行的设备,我想要的是让他们使用mdpi 图像(可用的更大的图像)并按原样使用它,而无需缩放。基本上,hdpiImageView 是 72px,所以我希望 48px 的图像位于 72px 的中间,没有缩放。为此,我只是尝试将上面ImageView 中的scaleType 更改为center,但无论如何图像都会被缩放。

我在这里的最终问题是,解决上述问题的正确方法是什么?我怎样才能让ldpimdpi 图像以各自的密度使用,但让运行hdpi 的设备拾取可​​用的最大图像(即mdpi 图像)并防止任何缩放,只适合图像在ImageView的中心?

编辑:
我自己回答了这个问题,但这可能是其他来到这里的人正在寻找的答案。但我确实提供了一些关于真正发生的事情和潜在问题的见解。如果可以,请查看并提供解决方法/修复。我敢你:)

【问题讨论】:

  • 是的,尝试了最合乎逻辑的可能性。没有任何效果:(
  • 请问您为什么需要这个?通常人们希望比在普通屏幕上,五个 64dp 图标应该始终占据整个屏幕宽度(即 320dp),无论设备分辨率如何,都应该看起来相同,包括图标两侧总是接触(可选的与设备无关的填充)
  • 我不明白你的问题...
  • 我正在使用一个库来为我的项目工作做可撤回的(使背景变圆),但是当我将它更改为 ImageView 时它工作得很好!

标签: android imageview scaling


【解决方案1】:

这个问题原来是一个非问题,我向任何发现它的人道歉,希望接受的答案是他们正在寻找的答案,而事实并非如此。

为了清楚起见,scaleType=centerInside 正在按预期工作。也就是说,如果您的图像小于ImageView 本身,则该图像不会缩放到ImageView 的边界,它将保持在中心且未缩放。

但要使上述内容按预期工作,drawable 必须放在nodpi 文件夹中。我知道这并不总是可以接受的。因此,当必须将该可绘制对象放入其中一个密度文件夹而不是 nodpi 文件夹时,scaleType 属性仅在特定情况下有效。

何时生效:

  • 您正在使用Xdpi 密度和 Xdpi密度文件夹中有一个drawable(这里X表示, lmh 甚至 xh)。
  • 您正在运行应用设备/模拟器, 例如,具有hdpi 密度,但在 hdpi 文件夹,系统从 nodpi 文件夹(并不总是知道它会选择哪个文件夹 来自)。

当它不起作用时:

  • 您正在运行应用程序设备/模拟器,例如,hdpi 密度,但hdpi 文件夹中没有可绘制对象,并且 系统从任何其他密度中选择替代可绘制对象 文件夹(不是nodpi 文件夹),drawable 将缩放到 ImageView bounds 和 scaleType 属性不起作用 任何东西。

总之,我的问题没有“正确”答案,这实际上取决于您要达到的目标。 my 问题的答案,我只需要做两件事:a) 将 ImageView scaleType 设置为 centerInside 和 b) 将 mdpi 文件夹中的所有可绘制对象复制到 @ 987654346@ 文件夹(如上所述,scaleType=centerInside 将使其工作)。

当然,复制drawables不是最佳的,但我找不到任何其他解决方案,到目前为止,也没有其他人可以......所以,我暂时将这个标记为已接受。

那么最佳答案/解决方案是什么?
在我看来,如果设备/模拟器在hdpi 中运行并且hdpi 文件夹中没有匹配的drawable,则应该从mdpi 文件夹中选择drawable 而无需缩放它,允许scaleType属性做它的事情。或者,如果系统在相应的密度文件夹中找不到匹配的可绘制对象,可能会强制系统转到 nodpi 文件夹,这也可能是一个解决方案。

因此,如果任何人都可以为此问题提供解决方法/解决方案,那将是真正正确的答案。如果真的发生这种情况,我会更改接受状态。

【讨论】:

    【解决方案2】:

    就我而言,我将图像设置为android:background。当我将其设置为android:src 时,它起作用了!

    【讨论】:

      【解决方案3】:

      我是这样解决的:

      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="horizontal"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content">
          <!-- Here is where the money is -->
          <LinearLayout
              android:orientation="vertical"
              android:layout_width="wrap_content"
              android:layout_height="fill_parent"
              android:gravity="center_horizontal|center_vertical">
              <ImageView
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"/>
          </LinearLayout>
          <LinearLayout
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content">
              ...
          </LinearLayout>
      </LinearLayout>
      

      【讨论】:

        【解决方案4】:

        尝试将其从 hdpi 文件夹中删除,并将其放在 drawable-nodpi 文件夹中。我不确定层次结构是什么(nodpi 是否会覆盖 ldpi 和 mdpi 文件夹),但这将是我的第一次尝试。

        【讨论】:

        • 我在hdpi 文件夹中从来没有任何东西。我在mdpi 文件夹中只有 48 像素的图像,在 ldpi 文件夹中只有 36 像素的图像。我相信hdpi 设备获取的图像是mdpi 文件夹中的图像。问题是图像正在被缩放,而它不应该被缩放,因为我明确告诉它不要这样做 (scaleType = center)。
        • 用nodpi文件夹中的48px图片试试吧。
        • 如果我将 mdpi 文件夹中的所有 48px 图像复制到 nodpi 文件夹中,它仍然不起作用。我不知道在hdpi 设备中使用的图像是从哪个文件夹中提取的,但它仍然可以缩放到ImageView 大小。 scaleType=centerscaleType=centerInside 都没有工作,但它们都应该工作。
        • 嗯......一个糟糕的解决方案是将 android:anydensity="false" 添加到您的清单中,在&lt;supports-screens&gt; 下。然后,您必须自己管理任何必要的扩展。图像是否足够大以至于将 mdpi 图像复制到 hdpi 文件夹中会是一个问题?
        • 现在我尝试将所有 48px 图像移动nodpi 文件夹,这意味着 hdpimdpi 文件夹都是空的,ldpi 文件夹有36 像素的图像。使用scaleType=centerInsidehdpi 设备工作正常,但在mdpi 设备上,似乎正在使用较小的图像(来自ldpi 文件夹)并且图像被缩放。我真的不明白发生了什么......
        【解决方案5】:

        试试这个:

        <FrameLayout android:layout_width="48dp" android:layout_height="48dp">
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
        
            android:maxWidth="48px"
            android:maxHeight="48px"
            android:adjustViewBounds="true"
            android:src="..."
            />
        </FrameLayout>
        

        并将图片正常放在ldpi/mdpi文件夹中。

        虽然我不推荐使用像素值。

        【讨论】:

        • 这不是我想要的。我需要ImageView 有72px(相当于hdpi 上的48dp),但我根本不希望图像被缩放以适应该尺寸,如果它恰好更小(这就是scaleType=center 应该去做)。这就是问题所在,我不想要固定尺寸。
        • 然后将 ImageView 包裹在 &lt;FrameLayout android:layout_width="48dp" android:layout_height="48dp"&gt; 中。您多久需要一次?我不认为 ImageView 的设计目的是部分独立于密度的 ldpi-mdpi 工作,部分不在 hdpi 中。
        • 您能否用最后一个建议的完整示例编辑您的答案?
        • 已编辑。虽然对所有图标都这样做有点过分。
        • 不是我所期望的,你仍然强制图像不超过 48px,我不希望这样。如果它们真的是 48px,我希望它们是 48px,但是如果它们更小,我希望它们更小,如果它们更大,我希望它们更大(但不大于 48dp,hdpi 中的 72px)。也许我没有正确解释自己,但我不确定如何做得更好。作为记录,我还尝试了一个与 FrameLayout 想法类似的示例,但没有“max”参数,图像仍然被缩放到 FrameLayout 的完整大小。
        【解决方案6】:

        创建自定义 ImageView:

        package x;
        
        public class MaxMDPIImageView extends ImageView {
        
            public MaxMDPIImageView(Context context, AttributeSet attrs) {
                super(context, attrs);
            }
        
            @Override
            protected void onDraw(Canvas canvas) {
                float density = getResources().getDisplayMetrics().density;
                if (density>1) {
                    canvas.translate(getWidth()/2-getWidth()/density/2, getHeight()/2-getHeight()/density/2);
                    canvas.scale(1/density, 1/density);
                }
                super.onDraw(canvas);
            }
        
        }
        

        简单地用作:

        <x.MaxMDPIImageView
            android:src="@drawable/icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
            />
        

        【讨论】:

        • 如果我正确理解了你的代码,我想你仍然不明白我在做什么。该代码(再次,如果我理解正确的话)将改变 每个 图像大小,我不希望这样。无论哪种方式,这个问题不再相关,准备好我的长答案。
        【解决方案7】:

        试试

        imageview.setAdjustViewBounds(false);
        

        【讨论】:

          猜你喜欢
          • 2015-06-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-01-19
          • 1970-01-01
          • 2017-08-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多