可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
On a layout I want to scale the background image (keeping its aspect ratio) to the space allocated when the page gets created. Anyone have any idea how to do this?
I am using layout.setBackgroundDrawable() and am using a BitmapDrawable to setGravity for clipping and filling, but don\'t see any option for scaling.
回答1:
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
回答2:
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.
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
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>
回答3:
There is an easy way to do this from the drawable:
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
.
回答4:
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!
Note this works only for images with a src
attribute, not for the background image.
回答5:
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>
回答6:
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:
// 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 bmp the Bitmap object that is to be shown and imageView is the ImageView
object
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:
...
<ImageView android:id=\"@+id/my_image_view\"
android:layout_width=\"fill_parent\"
android:layout_height=\"fill_parent\"/>
...
回答7:
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:
<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)
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:
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.
Gladly somebody has extended ImageView to support 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
Now IMHO would be perfect if somebody wrote custom Drawable which scales image like that. Then it could be used as background parameter.
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.
回答8:
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:
< 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>
回答9:
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.
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)
回答10:
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.
This definitely works with scaling down, I haven\'t tested with scaling up though.
回答11:
you\'ll have to pre-scale that drawable before you use it as a background
回答12:
You can use one of following:
android:gravity=\"fill_horizontal|clip_vertical\"
Or
android:gravity=\"fill_vertical|clip_horizontal\"