Android:缩放可绘制图像还是背景图像?

Android:缩放可绘制图像还是背景图像?,android,Android,在布局上,我想将背景图像(保持其纵横比)缩放到创建页面时分配的空间。有人知道怎么做吗 我正在使用layout.setBackgroundDrawable()和BitmapDrawable()设置重力,用于剪裁和填充,但看不到任何缩放选项。在将该可绘制文件用作背景之前,必须对其进行预缩放,但是您可以使用android:scaleType=“fitXY” 它的大小将适合您提供的ImageView的任何大小 因此,您可以为布局创建框架布局,将ImageView放入其中,然后在框架布局中添加您需要的任何

在布局上,我想将背景图像(保持其纵横比)缩放到创建页面时分配的空间。有人知道怎么做吗


我正在使用
layout.setBackgroundDrawable()
BitmapDrawable()
设置
重力
,用于剪裁和填充,但看不到任何缩放选项。

在将该可绘制文件用作背景之前,必须对其进行预缩放,但是您可以使用android:scaleType=“fitXY”
它的大小将适合您提供的ImageView的任何大小

因此,您可以为布局创建框架布局,将ImageView放入其中,然后在框架布局中添加您需要的任何其他内容以及透明背景

<FrameLayout  
android:layout_width="fill_parent" android:layout_height="fill_parent">

  <ImageView 
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:src="@drawable/back" android:scaleType="fitXY" />

  <LinearLayout>your views</LinearLayout>
</FrameLayout>

你的观点

要保持纵横比,必须使用android:scaleType=fitCenter或
fitStart
等。使用
fitXY
将不会保持图像的原始纵横比


注意:这仅适用于具有
src
属性的图像,而不适用于背景图像。

要自定义背景图像缩放,请创建如下资源:

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:gravity="center"
    android:src="@drawable/list_bkgnd" />


如果用作背景,则它将在视图中居中。还有其他标志:

当您使用
setBackgroundDrawable
方法设置图像视图的可绘制性时,图像将始终被缩放。参数如
adjustViewBounds
或不同的
scaleType
将被忽略。我找到的保持纵横比的唯一解决方案是在加载可绘制图像后调整
ImageView
。以下是我使用的代码片段:

// bmp is your Bitmap object
int imgHeight = bmp.getHeight();
int imgWidth = bmp.getWidth();
int containerHeight = imageView.getHeight();
int containerWidth = imageView.getWidth();
boolean ch2cw = containerHeight > containerWidth;
float h2w = (float) imgHeight / (float) imgWidth;
float newContainerHeight, newContainerWidth;

if (h2w > 1) {
    // height is greater than width
    if (ch2cw) {
        newContainerWidth = (float) containerWidth;
        newContainerHeight = newContainerWidth * h2w;
    } else {
        newContainerHeight = (float) containerHeight;
        newContainerWidth = newContainerHeight / h2w;
    }
} else {
    // width is greater than height
    if (ch2cw) {
        newContainerWidth = (float) containerWidth;
        newContainerHeight = newContainerWidth / h2w; 
    } else {
        newContainerWidth = (float) containerHeight;
        newContainerHeight = newContainerWidth * h2w;       
    }
}
Bitmap copy = Bitmap.createScaledBitmap(bmp, (int) newContainerWidth, (int) newContainerHeight, false);
imageView.setBackgroundDrawable(new BitmapDrawable(copy));
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
imageView.setLayoutParams(params);
imageView.setMaxHeight((int) newContainerHeight);
imageView.setMaxWidth((int) newContainerWidth);
在上面的代码片段中,bmp是要显示的位图对象,imageView
imageView
对象

需要注意的一点是布局参数的更改。这是必要的,因为
setMaxHeight
setMaxWidth
仅在宽度和高度定义为包装内容而不是填充父内容时才会产生差异。另一方面,填充父项是开始时所需的设置,因为否则
containerWidth
containerHeight
的值都将等于0。 因此,在布局文件中,您的ImageView有如下内容:

...
<ImageView android:id="@+id/my_image_view"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"/>
...
。。。
...

德维博提出的方案有效。但依我拙见,这是不必要的。 背景可自行绘制。视图应具有固定的宽度和高度,如以下示例所示:

 < RelativeLayout 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@android:color/black">

    <LinearLayout
        android:layout_width="500dip"
        android:layout_height="450dip"
        android:layout_centerInParent="true"
        android:background="@drawable/my_drawable"
        android:orientation="vertical"
        android:padding="30dip"
        >
        ...
     </LinearLayout>
 < / RelativeLayout>

...


尝试的一个选项是将图像放在
可绘制nodpi
文件夹中,并将布局的背景设置为可绘制资源id


这当然适用于缩小,但我还没有测试过放大。

这不是最有效的解决方案,但正如有人建议的那样,您可以创建FrameLayout或RelativeLayout,并使用ImageView作为伪背景-其他元素将仅位于其上方:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

    <ImageView
        android:id="@+id/ivBackground"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:scaleType="fitStart"
        android:src="@drawable/menu_icon_exit" />

    <Button
        android:id="@+id/bSomeButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="61dp"
        android:layout_marginTop="122dp"
        android:text="Button" />

</RelativeLayout>

现在,如果有人写一个定制的绘图工具,可以像这样缩放图像,IMHO将是完美的。然后可以将其用作背景参数


Reflog建议在使用drawable之前对其进行预缩放。以下是操作说明:
尽管它有缺点,但放大的可绘制/位图将使用更多RAM,而ImageView使用的动态缩放不需要更多内存。优点是处理器负载更少。

下面的代码使位图与imageview的大小完全相同。获取位图图像的高度和宽度,然后借助imageview的参数计算新的高度和宽度。这将为您提供具有最佳纵横比的所需图像

int bwidth=bitMap1.getWidth();
int bheight=bitMap1.getHeight();
int swidth=imageView_location.getWidth();
int sheight=imageView_location.getHeight();
new_width=swidth;
new_height = (int) Math.floor((double) bheight *( (double) new_width / (double) bwidth));
Bitmap newbitMap = Bitmap.createScaledBitmap(bitMap1,new_width,new_height, true);
imageView_location.setImageBitmap(newbitMap)

有一种简单的方法可以从可绘制的图形中执行此操作:

您的_drawable.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <item android:drawable="@color/bg_color"/>
    <item>
        <bitmap
            android:gravity="center|bottom|clip_vertical"
            android:src="@drawable/your_image" />
    </item>

</layer-list>

唯一的缺点是,如果没有足够的空间,您的图像将无法完全显示,但它将被剪裁,我无法找到一种直接从绘图板上执行此操作的方法。但是从我做的测试来看,它工作得很好,并且没有剪辑太多的图像。你可以更多地使用重力选项


另一种方法是只创建一个布局,您将使用
并将
设置为
fitCenter

使用图像作为布局的背景大小:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <ImageView
        android:id="@+id/imgPlaylistItemBg"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:adjustViewBounds="true"
        android:maxHeight="0dp"
        android:scaleType="fitXY"
        android:src="@drawable/img_dsh" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >


    </LinearLayout>

</FrameLayout>

您可以使用以下选项之一:

android:gravity=“水平填充|垂直剪裁”

android:gravity=“fill_vertical | clip_horizontal”

Kotlin:

如果需要在视图中绘制位图,请缩放以适合

在bm宽高比小于容器宽高比的情况下,您可以进行适当的计算,将bm高度设置为容器的高度,并调整宽度,或者在相反的情况下调整宽度

图像:

// binding.fragPhotoEditDrawCont is the RelativeLayout where is your view
// bm is the Bitmap
val ch = binding.fragPhotoEditDrawCont.height
val cw = binding.fragPhotoEditDrawCont.width
val bh = bm.height
val bw = bm.width
val rc = cw.toFloat() / ch.toFloat()
val rb = bw.toFloat() / bh.toFloat()

if (rb < rc) {
    // Bitmap Width to Height ratio is less than Container ratio
    // Means, bitmap should pin top and bottom, and have some space on sides.
    //              _____          ___
    // container = |_____|   bm = |___| 
    val bmHeight = ch - 4 //4 for container border
    val bmWidth = rb * bmHeight //new width is bm_ratio * bm_height
    binding.fragPhotoEditDraw.layoutParams = RelativeLayout.LayoutParams(bmWidth.toInt(), bmHeight)
}
else {
    val bmWidth = cw - 4 //4 for container border
    val bmHeight = 1f/rb * cw
    binding.fragPhotoEditDraw.layoutParams = RelativeLayout.LayoutParams(bmWidth, bmHeight.toInt())
}

//binding.fragPhotoEditDrawCont是相对位置,视图在哪里
//bm是位图
val ch=binding.fragPhotoEditDrawCont.height
val cw=binding.fragPhotoEditDrawCont.width
val bh=bm高度
val bw=bm.width
val rc=cw.toFloat()/ch.toFloat()
val rb=bw.toFloat()/bh.toFloat()
if(rb// binding.fragPhotoEditDrawCont is the RelativeLayout where is your view
// bm is the Bitmap
val ch = binding.fragPhotoEditDrawCont.height
val cw = binding.fragPhotoEditDrawCont.width
val bh = bm.height
val bw = bm.width
val rc = cw.toFloat() / ch.toFloat()
val rb = bw.toFloat() / bh.toFloat()

if (rb < rc) {
    // Bitmap Width to Height ratio is less than Container ratio
    // Means, bitmap should pin top and bottom, and have some space on sides.
    //              _____          ___
    // container = |_____|   bm = |___| 
    val bmHeight = ch - 4 //4 for container border
    val bmWidth = rb * bmHeight //new width is bm_ratio * bm_height
    binding.fragPhotoEditDraw.layoutParams = RelativeLayout.LayoutParams(bmWidth.toInt(), bmHeight)
}
else {
    val bmWidth = cw - 4 //4 for container border
    val bmHeight = 1f/rb * cw
    binding.fragPhotoEditDraw.layoutParams = RelativeLayout.LayoutParams(bmWidth, bmHeight.toInt())
}