Android 如何使ImageButton正确调整资产图像的大小?

Android 如何使ImageButton正确调整资产图像的大小?,android,android-layout,Android,Android Layout,我的应用程序有一个活动,显示垂直滚动的图像按钮列表。我希望每个按钮图像(A)来自assets文件夹,并且(B)在缩放时保留其纵横比。不幸的是,当我的ImageButton的图像来自assets文件夹时,它的大小不正确 ImageButton src从可绘图 第一个屏幕截图是我的测试应用程序,其中的图像都来自我的应用程序drawables。这是该图像的“正确”纵横比,这是我想要保留的(所有图像按钮都被赋予了scaleType“fitXY”“centerCrop”) 来自资源的ImageButto

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

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

来自资源的ImageButton src集 第二个屏幕截图是我的测试应用程序,其中所有图像都来自我的应用程序“资产”文件夹-如您所见,图像会根据需要伸展到屏幕的全宽,但原始纵横比已丢失:

活动代码(MainActivity.java) 按钮布局(snippet_imagebutton.xml) 总结 我想从我的应用程序“资产”文件夹中获取这些按钮的图像。如何修复我的应用程序,使按钮图像都能正确缩放(即保留其原始纵横比)


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

当您将scale type属性设置为“fitXY”时,纵横比不会保持不变。根据您的需要尝试“中心”、“中心裁剪”或“中心内”。也请检查。

当您将“比例类型”属性设置为“fitXY”时,纵横比不会保持不变。根据您的需要尝试“中心”、“中心裁剪”或“中心内”。也请检查。

根据我收集的信息,AdjustViewBounds实际上是提供您所需确切功能的方法。但是,正如Roman Nurik所解释的,AdjustViewBounds不会将ViewBounds增加到可绘制图形的自然尺寸之外

如果不了解如何分配资源/资产,我的怀疑是,这就是为什么从资源加载和从资产加载时会看到不同。您的资源文件在加载时(因为这是资源的默认行为)可能会被放大,因此从/res返回的可绘制文件的实际大小明显大于从/assets解码的位图

覆盖ImageButton(正如Nurik所建议的那样)当然是一种选择,但可能有点过头了

假设我对这个问题的看法是正确的,那么在加载资产文件时只需正确设置BitmapFactory.options,就可以解决这个问题。您需要根据设备正确设置inDensity和inTargetDensity(获取DisplayMetrics),并将inScaled设置为true

或者,在将位图加载到ImageButton上之前,始终可以手动重新缩放位图。只需抓取屏幕宽度即可确定需要制作多大屏幕

附言


自动缩放显然是一个优雅的解决方案,但它确实有一个弱点(这同样适用于资源和资产)-如果放大时显示的宽度>位图,则可能仍然会弄乱纵横比。您可以很容易地检查这一点,方法是转到横向模式,并查看资源文件是否仍然具有正确的纵横比。如果您有足够大的基础图像(或者根据屏幕大小/方向使用不同的布局),那么这应该不是问题。需要记住的是。

根据我收集的信息,AdjustViewBounds实际上是提供您所需确切功能的方法。但是,正如Roman Nurik所解释的,AdjustViewBounds不会将ViewBounds增加到可绘制图形的自然尺寸之外

如果不了解如何分配资源/资产,我的怀疑是,这就是为什么从资源加载和从资产加载时会看到不同。您的资源文件在加载时(因为这是资源的默认行为)可能会被放大,因此从/res返回的可绘制文件的实际大小明显大于从/assets解码的位图

覆盖ImageButton(正如Nurik所建议的那样)当然是一种选择,但可能有点过头了

假设我对这个问题的看法是正确的,那么在加载资产文件时只需正确设置BitmapFactory.options,就可以解决这个问题。您需要根据设备正确设置inDensity和inTargetDensity(获取DisplayMetrics),并将inScaled设置为true

或者,在将位图加载到ImageButton上之前,始终可以手动重新缩放位图。只需抓取屏幕宽度即可确定需要制作多大屏幕

附言


自动缩放显然是一个优雅的解决方案,但它确实有一个弱点(这同样适用于资源和资产)-如果放大时显示的宽度>位图,则可能仍然会弄乱纵横比。您可以很容易地检查这一点,方法是转到横向模式,并查看资源文件是否仍然具有正确的纵横比。如果您有足够大的基础图像(或者根据屏幕大小/方向使用不同的布局),那么这应该不是问题。只是需要记住一些东西。

将getImageBitmapFromAssets()放在心上;代码也…@George您是否尝试将
android:adjustViewBounds=“true”
添加到您的ImageButton?+您可能应该使用fitXY来保持纵横比。@SherifelKhatib:是的,RelativeLayout和ImageButton上的adjustViewBounds都为true。fitXY也不是我想要的:fitXY在缩放图像时不会保持图像的纵横比。使用ImageView时会遇到同样的问题吗?(看起来你没有使用任何ImageButton专长
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));
<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>
// 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));
    }
});