Android:缩放 Drawable 或背景图像?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1400782/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android: Scale a Drawable or background image?
提问by
On a layout I want to scale the background image (keeping its aspect ratio) to the space allocated when the page gets created. Does anyone have an idea how to do this?
在布局上,我想将背景图像(保持其纵横比)缩放到创建页面时分配的空间。有谁知道如何做到这一点?
I am using layout.setBackgroundDrawable()
and a BitmapDrawable()
to set gravity
for clipping and filling, but don't see any option for scaling.
我正在使用layout.setBackgroundDrawable()
和 aBitmapDrawable()
来设置gravity
剪切和填充,但没有看到任何缩放选项。
回答by Aleks N.
To customize background image scaling create a resource like this:
要自定义背景图像缩放,请创建如下资源:
<?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" />
Then it will be centered in the view if used as background. There are also other flags: http://developer.android.com/guide/topics/resources/drawable-resource.html
如果用作背景,它将在视图中居中。还有其他标志:http: //developer.android.com/guide/topics/resources/drawable-resource.html
回答by dweebo
Haven't tried to do exactly what you want, but you can scale an ImageView using android:scaleType="fitXY"
and it will be sized to fit into whatever size you give the ImageView.
还没有尝试完全按照您的意愿去做,但是您可以使用缩放 ImageView,android:scaleType="fitXY"
并且它的大小将适合您给 ImageView 提供的任何大小。
So you could create a FrameLayout for your layout, put the ImageView inside it, and then whatever other content you need in the FrameLayout as well w/ a transparent background.
因此,您可以为您的布局创建一个 FrameLayout,将 ImageView 放入其中,然后在 FrameLayout 中添加您需要的任何其他内容以及带有透明背景的内容。
<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>
回答by Ionut Negru
There is an easy way to do this from the drawable:
有一种简单的方法可以从 drawable 中做到这一点:
your_drawable.xml
your_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>
The only downside is that if there is not enough space, your image won't be fully shown, but it will be clipped, I couldn't find an way to do this directly from a drawable. But from the tests I did it works pretty well, and it doesn't clip that much of the image. You could play more with the gravity options.
唯一的缺点是,如果没有足够的空间,您的图像将无法完全显示,但会被剪裁,我找不到直接从可绘制对象执行此操作的方法。但是从我所做的测试来看,它运行得很好,而且它并没有剪掉那么多的图像。您可以更多地使用重力选项。
Another way will be to just create an layout, where you will use an ImageView
and set the scaleType
to fitCenter
.
另一种方法是创建一个布局,您将在其中使用ImageView
并将 设置scaleType
为fitCenter
。
回答by Konstantin Konopko
Use image as background sized to layout:
使用图像作为背景大小来布局:
<?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>
回答by Anke
To keep the aspect ratio you have to use android:scaleType=fitCenter
or fitStart
etc. Using fitXY
will not keep the original aspect ratio of the image!
为了让你有宽高比使用android:scaleType=fitCenter
或fitStart
等使用fitXY
不会保留图像的原始宽高比!
Note this works only for images with a src
attribute, not for the background image.
请注意,这仅适用于具有src
属性的图像,不适用于背景图像。
回答by maddob
When you set the Drawable of an ImageView by using the setBackgroundDrawable
method, the image will always be scaled. Parameters as adjustViewBounds
or different ScaleTypes
will just be ignored. The only solution to keep the aspect ratio I found, is to resize the ImageView
after loading your drawable. Here is the code snippet I used:
当您使用该setBackgroundDrawable
方法设置 ImageView 的 Drawable 时,图像将始终被缩放。参数 asadjustViewBounds
或 differentScaleTypes
将被忽略。保持我发现的纵横比的唯一解决方案是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);
In the code snippet above is bmpthe Bitmap object that is to be shown and imageViewis the ImageView
object
在上面的代码片段中,bmp是要显示的 Bitmap 对象,而imageView是ImageView
对象
An important thing to note is the change of the layout parameters. This is necessary because setMaxHeight
and setMaxWidth
will only make a difference if the width and height are defined to wrap the content, not to fill the parent. Fill parent on the other hand is the desired setting at the beginning, because otherwise containerWidth
and containerHeight
will both have values equal to 0.
So, in your layout file you will have something like this for your ImageView:
需要注意的重要一点是布局参数的更改。这是必要的,因为setMaxHeight
并且setMaxWidth
只有在定义宽度和高度以包装内容而不是填充父项时才会有所作为。另一方面,填充父级是开始时所需的设置,因为否则containerWidth
和containerHeight
都将具有等于 0 的值。因此,在您的布局文件中,您的 ImageView 将具有如下内容:
...
<ImageView android:id="@+id/my_image_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
...
回答by Malachiasz
This is not the most performant solution, but as somebody suggested instead of background you can create FrameLayout or RelativeLayout and use ImageView as pseudo background - other elements will be position simply above it:
这不是最高效的解决方案,但正如有人建议的那样,您可以创建 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>
The problem with ImageView is that only scaleTypes available are: CENTER, CENTER_CROP, CENTER_INSIDE, FIT_CENTER,FIT_END, FIT_START, FIT_XY, MATRIX (http://etcodehome.blogspot.de/2011/05/android-imageview-scaletype-samples.html)
ImageView 的问题是只有 scaleTypes 可用:CENTER、CENTER_CROP、CENTER_INSIDE、FIT_CENTER、FIT_END、FIT_START、FIT_XY、MATRIX(http://etcodehome.blogspot.de/2011/05/android-imageview-scaletype-samples.html)
and to "scale the background image (keeping its aspect ratio)" in some cases, when you want an image to fill the whole screen (for example background image) and aspect ratio of the screen is different than image's, the necessary scaleType is kind of TOP_CROP, because:
并在某些情况下“缩放背景图像(保持其纵横比)”,当您希望图像填满整个屏幕(例如背景图像)并且屏幕的纵横比与图像的纵横比不同时,必要的 scaleType 是 kind TOP_CROP,因为:
CENTER_CROP centers the scaled image instead of aligning the top edge to the top edge of the image view and FIT_START fits the screen height and not fill the width. And as user Anke noticed FIT_XY doesn't keep aspect ratio.
CENTER_CROP 将缩放图像居中,而不是将顶部边缘与图像视图的顶部边缘对齐,并且 FIT_START 适合屏幕高度而不是填充宽度。正如用户 Anke 注意到 FIT_XY 没有保持纵横比。
Gladly somebody has extended ImageView to support TOP_CROP
很高兴有人扩展了 ImageView 以支持 TOP_CROP
public class ImageViewScaleTypeTopCrop extends ImageView {
public ImageViewScaleTypeTopCrop(Context context) {
super(context);
setup();
}
public ImageViewScaleTypeTopCrop(Context context, AttributeSet attrs) {
super(context, attrs);
setup();
}
public ImageViewScaleTypeTopCrop(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setup();
}
private void setup() {
setScaleType(ScaleType.MATRIX);
}
@Override
protected boolean setFrame(int frameLeft, int frameTop, int frameRight, int frameBottom) {
float frameWidth = frameRight - frameLeft;
float frameHeight = frameBottom - frameTop;
if (getDrawable() != null) {
Matrix matrix = getImageMatrix();
float scaleFactor, scaleFactorWidth, scaleFactorHeight;
scaleFactorWidth = (float) frameWidth / (float) getDrawable().getIntrinsicWidth();
scaleFactorHeight = (float) frameHeight / (float) getDrawable().getIntrinsicHeight();
if (scaleFactorHeight > scaleFactorWidth) {
scaleFactor = scaleFactorHeight;
} else {
scaleFactor = scaleFactorWidth;
}
matrix.setScale(scaleFactor, scaleFactor, 0, 0);
setImageMatrix(matrix);
}
return super.setFrame(frameLeft, frameTop, frameRight, frameBottom);
}
}
https://stackoverflow.com/a/14815588/2075875
https://stackoverflow.com/a/14815588/2075875
Now IMHO would be perfect if somebody wrote custom Drawable which scales image like that. Then it could be used as background parameter.
现在恕我直言,如果有人编写自定义 Drawable 来缩放图像,那将是完美的。然后它可以用作背景参数。
Reflog suggests to prescale drawable before using it. Here is instruction how to do it: Java (Android): How to scale a drawable without Bitmap?Although it has disadvantage, that upscaled drawable/bitmap will use more RAM, while scaling on the fly used by ImageView doesn't require more memory. Advantage could be less processor load.
Reflog 建议在使用之前预先缩放 drawable。这是如何做到这一点的说明: Java(Android):如何在没有位图的情况下缩放可绘制对象?虽然它有缺点,但放大的可绘制/位图将使用更多的 RAM,而 ImageView 使用的动态缩放不需要更多内存。优势可能是更少的处理器负载。
回答by Naresh Sharma
The Below code make the bitmap perfectly with same size of the imageview. Get the bitmap image height and width and then calculate the new height and width with the help of imageview's parameters. That give you required image with best aspect ratio.
下面的代码使位图与图像视图的大小相同。获取位图图像的高度和宽度,然后借助 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)
回答by Yar
What Dweebo proposed works. But in my humble opinion it is unnecessary. A background drawable scales well by itself. The view should have fixed width and height, like in the following example:
Dweebo 建议的工作。但以我的拙见,这是不必要的。背景可绘制对象本身可以很好地缩放。视图应该具有固定的宽度和高度,如下例所示:
< 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>
回答by Sababado
One option to try is to put the image in the drawable-nodpi
folder and set background of a layout to the drawable resource id.
尝试的一种选择是将图像放在drawable-nodpi
文件夹中并将布局的背景设置为可绘制资源 ID。
This definitely works with scaling down, I haven't tested with scaling up though.
这绝对适用于缩小规模,不过我还没有测试过扩大规模。