0

我的应用程序有一个显示图像按钮垂直滚动列表的活动。我希望(A)的每个按钮图像来自资产文件夹,并且(B)在缩放时保留它的纵横比。不幸的是,当图像来自资产文件夹时,我的 ImageButton 大小不正确。

从drawable设置的ImageButton src

第一个屏幕截图是我的测试应用程序,其中所有图像都来自我的应用程序可绘制对象。那是该图像的“正确”纵横比,这是我想要保留的(所有图像按钮都被赋予了 scaleType "fitXY" "centerCrop")。

从可绘制对象中获取的图像

从资产设置的 ImageButton src

第二个屏幕截图是我的测试应用程序,其中所有图像都来自我的应用程序“assets”文件夹——如您所见,图像根据需要拉伸到屏幕的整个宽度,但原始纵横比已丢失:

从资产中获取的图像

活动代码(MainActivity.java)

LinearLayout buttons = (LinearLayout) findViewById(R.id.buttons);
View button = layoutInflater.inflate(R.layout.snippet_imagebutton, null);
ImageButton imageButton = (ImageButton) button.findViewById(R.id.imageButton);
if (GET_IMAGE_FROM_ASSETS) {
    InputStream s = assetManager.open("image.png");
    Bitmap bmp = BitmapFactory.decodeStream(s);
    imageButton.setImageBitmap(bmp);
} else {
    imageButton.setImageResource(R.drawable.image);
}
TextView buttonText = (TextView) button.findViewById(R.id.textView);
buttonText.setText("Button text!");
buttons.addView(button,
    new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));

按钮布局 (snippet_imagebutton.xml)

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="8dp">
    <ImageButton
        android:id="@+id/imageButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scaleType="centerCrop"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" />
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:gravity="center"
        android:textColor="#FFF"
        android:background="#88000000"
        android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>

狡猾的黑客

我发现了一个狡猾的 hack,它实现了我想要的并说明了问题——ImageButton 将正确调整大小以匹配资源中的放大图像,但它不会正确调整大小以匹配资产中的放大图像。如果有的话,我更喜欢“真正的”解决方案而不是狡猾的黑客。:)

// to start with, scale the ImageButton based on an image in our
// resources that has the same dimensions as the image in our assets
imageButton.setImageResource(R.drawable.image);
// when we eventually render (we don't have width / height yet)...
imageButton.post(new Runnable() {
    public void run() {
        int height = imageButton.getHeight();
        int width = imageButton.getWidth();
        // replace our "resource" image with our "asset" image
        imageButton.setImageBitmap(bmp);
        // and force the ImageButton to keep the same scale as previously
        imageButton.setLayoutParams(
            new RelativeLayout.LayoutParams(width, height));
    }
});

概括

我想从我的应用程序“资产”文件夹中获取这些按钮的图像。如何修复我的应用程序以使按钮图像全部正确缩放(即保留其原始纵横比)?

我假设这与框架在将 ImageButton 渲染到屏幕之前实际上不知道图像的宽度/高度有关 - 那么我该如何解决呢?我尝试在 RelativeLayout 和 ImageButton 本身上将 adjustViewBounds 设置为“true”,但这似乎没有任何效果。

4

2 回答 2

2

当您将比例类型属性指定为“fitXY”时,不会保留纵横比。根据您的需要尝试“center”、“center_crop”或“center_inside”。还要检查ImageViewScaleType

于 2013-02-19T09:27:48.290 回答
1

据我所知,AdjustViewBounds 实际上是提供您需要的确切功能的方法。但是,正如 Roman Nurik在这里解释的那样,AdjustViewBounds 不会将 ViewBounds 增加到超出可绘制对象的自然尺寸。

在没有看到您如何分配资源/资产的情况下,我怀疑这就是为什么您在从资源加载和从资产加载时看到差异的原因。您的资源文件 - 大概 - 在加载时被放大(因为这是资源的默认行为),因此从 /res 返回的可绘制对象的实际大小明显大于从 /assets 解码的位图。

覆盖 ImageButton (正如 Nurik 建议的那样),当然是一种选择,但可能是矫枉过正。

假设我对这个问题是正确的,您应该能够通过在加载资产文件时正确设置 BitmapFactory.options 来解决它。您需要根据您的设备正确设置 inDensity 和 inTargetDensity(获取 DisplayMetrics),并将 inScaled 设置为 true。

或者,您始终可以在将位图加载到 ImageButton 之前手动重新缩放位图。只需抓住屏幕宽度来确定你需要做多大。

附言

自动缩放显然是一个优雅的解决方案,但它确实有一个弱点(这同样适用于资源和资产) - 如果你的显示宽度 > 放大时的位图宽度,你可能仍然会弄乱纵横比. 您可以通过转到横向模式并查看资源文件是否仍然产生正确的纵横比来轻松检查这一点。如果您有足够大的基本图像(或根据屏幕尺寸/方向使用不同的布局),那么这应该不是问题。只是要记住的事情。

于 2013-02-28T10:57:27.937 回答