Android: Stretch bitmap to fill entire screen - android

I'm using a bitmap as a background for activity. The code of the custom background is:
<item>
<bitmap android:src="#drawable/fog"
android:layout_width="match_parent"
android:adjustViewBounds="true"
/>
</item>
However it sits in the middle and doesn't occupy the entire screen space.
How can I make it fill all the available space?
I tried setting width and height to fill_parent.
Thanks

try adding:
android:layout_width="match_parent"
android:layout_height="match_parent"

I agree with the #androidz post. To avoid distortion, you can use the setAdjustViewBounds function (see here).

android:scaleType="fitXY" is what i use to fill imageviews, i never had bitmap as item, theres cropping ones too

Related

Stretching a one-pixel wide gradient image in a drawable, or otherwise

I have a PNG file which is a one-pixel-wide, 283-pixel-tall gradient image, which I need to stretch across the background of an ImageView, stretching only horizontally. I attempted to set the asset as a background to an ImageView like this:
<ImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/gradient_tile"
android:layout_gravity="bottom|center"
android:scaleType="matrix"/>
but that just creates a one-pixel line in the middle of the parent view.
Is there a way to do this, or do I need to request a wider image, and use a 9-patch?
Thanks in advance.
UPDATE:
I ended up having to set minimum height properties in the XML as follows:
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="119dp"
android:background="#drawable/gradient_tile_drawable"
android:id="#+id/tiledGradientBackground"
android:layout_gravity="bottom|center"
android:scaleType="matrix"/>
...and then set minimumWidth to the width of the parent view in code. Not sure why this solved it, but it did...
int width = holder.container.getResolvedWidth();
holder.tiledGradientBackground.setMinimumWidth(width);
Try this (tiling instead of stretching):
Put in your drawable folder a file called bg.xml:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/your_1px_wide_image"
android:tileMode="repeat"
/>
and set it as your layout background
android:background="#drawable/bg"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
I tested it and it works fine.
This image
is giving this result.
Note that I put some extra padding - this screen is 320*480 wide, so the gradient is approx 1/3rd the total screen height (including title and status bars + the extra padding)
scaletype effects the src image of ImageView and not the background, if the image view is used only for background set the image as src and used fitXY scaletype.
You should create a drawable like Klaus66 & CommonsWare suggested and set it as a background.
Actually if you have a 1px gradient you probably can just create a GradientDrawable xml, will look better across different devices.
http://developer.android.com/reference/android/graphics/drawable/GradientDrawable.html
You shouldn't use an extra ImageView just set it as the background of your top layout or even the background of your theme, see my answer here: Android SplashScreen

Android: how to prevent dynamic background drawable from stretching

I need to set the layout's background dynamically by calling myView.setBackgroundDrawable(BitmapDrawable bdb), but I want to crop the image rather than stretching it in the layout, is there a way doing it?
I was trying to create the drawable as below to set the gravity, but the challenge is I can't hardcode the android:src to a static drawable since the image source has to be dynamic.
<bitmap android:src="#drawable/background" android:gravity="center" />
Any suggestion would be really appreciated!
I believe the android:gravity attributes you are looking for are clip_vertical and clip_horizontal, but a word of advice. These attributes may not behave the way you think they should. You cannot use them to clip an image in both directions, only one. The following code:
<bitmap
android:src="#drawable/background"
android:gravity="clip_vertical|clip_horizontal" />
does not allow the image to be cropped in both directions...it actually fits the image inside the view as if you had not set either one. It also can be confusing that setting a clip parameter essentially sets that direction to fit the view, with the other direction being cropped out. A few examples:
<!-- Force fit top/bottom, crop left/right with image centered -->
<bitmap
android:src="#drawable/background"
android:gravity="clip_vertical" />
<!-- Force fit top/bottom, align image left and crop right edge -->
<bitmap
android:src="#drawable/background"
android:gravity="left|clip_vertical" />
<!-- Force fit left/right, crop top/bottom with image centered -->
<bitmap
android:src="#drawable/background"
android:gravity="clip_horizontal" />
<!-- Force fit left/right, align top and crop bottom egde -->
<bitmap
android:src="#drawable/background"
android:gravity="top|clip_horizontal" />
Notice that these settings allow an image larger than the view to be cropped, but if the image is smaller than the view, its contents will still be stretched to fit. In order to govern how an image will behave in a <bitmap> tag when it is smaller than the view, look at tileMode. Note that tileMode and gravity cannot be used together; gravity will be ignored if both are included.
If you need more dynamic control of how the image scales in addition to this, and you do not want to use an ImageView, you could also wrap the resulting Drawable in a ScaleDrawable and configure the x/y scale percentages in Java code based on the measured view sizes.
You want to use ImageView.ScaleType.CENTER_CROP

Replacing existing drwable in imageview is wrong scaled on some devices

The Situation:
I have a imageview with a layer list of two drwables.
The frame drwable is 800x400px and the cover drawable is 800x380px.
Both images reside in the folder drawable
<ImageView
android:id="#+id/preview_img_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="0.9"
android:adjustViewBounds="true"
android:src="#drawable/result_preview"/>
The Drwable layer list in drawable/result_preview
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/cover">
<bitmap
android:gravity="left|top"
android:src="#drawable/cover" />
</item>
<item
android:id="#+id/frame">
<bitmap
android:gravity="left|top"
android:src="#drawable/frame" />
</item>
</layer-list>
This setup works as expected the cover is displayed framed on all devices. Now the user can replace the sample cover with another cover of the same size.
Replacing the cover in the layer list and leave the frame as is.
LayerDrawable layer = (LayerDrawable) getResources().getDrawable(R.drawable.result_preview);
InputStream coverIs = getContentResolver().openInputStream(Uri.parse(coverUri));
this.drwCover = (BitmapDrawable) BitmapDrawable.createFromStream(coverIs, coverUri);
drwCover.setGravity(Gravity.LEFT | Gravity.TOP);
//drwCover.getBitmap().setDensity(160);
layer.setDrawableByLayerId(R.id.cover, drwCover);
imageView.setImageDrawable(layer);
The Problem:
Replacing the current cover with a new one (same dimensions as old) produces different results depending on the Device used.
On a device with a 3.2 screen and a 480x320 resolution the cover replaced fits in the frame. On a device with a 3.7 and a 800x480 resolution the replaced cover is displayed smaller then the old one.
What I found out is that the drwable in the imageview on the small device has a intrinsic height of 800x400 same as the dimensions of the drawable.
On the bigger screen the intrinsic height of the drawable is 30% bigger.
I know the the intrinsic values may differ from screen to screen.
What I was expecting is that the drawable that replaces the old one should will be scaled up the same way the old one was to +30%. But this did not happen.
Question:
Is there a option to tell the imageview or the layer list to Adpt itself? I think there should be a way to do so because the system did it already at the beginning.
First, I'd suggest doing the cover/frame differently:
make your frame a nine-patch drawable, so you can define in the nine-patch the padding that will remain visible when the cover is drawn on top of it.
put the frame drawable as a background
set the cover as the src of the image, and not the layer list
don't forget to set a scaleType for your ImageView, play with the different options, so suit your needs.
<ImageView
android:id="#+id/preview_img_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="0.9"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:background="#drawable/frame"
android:src="#drawable/cover"/>
For other having the same problem. 9patch png is a solution to a problem I don't have.
So far the only thing that came close to solve the problem was to put my resources into the folder drawable-nodpi. Here is the reference to the docs

How to implement an android:background that doesn't stretch?

I found this great thread describing how to "eat the cake and have it too", i.e. use image for a Button instead of ImageButton (which doesn't allow SetText(), resizing, etc.).
This is achieved by using the View attribute:
android:background="#drawable/bgimage"
The only problem with this is that it stretches the image to fit the button size.
Short of hard-coding a fixed button size (in pixels!), is there a way to tell Android not to stretch the background image at all and either crop or pad it?
You can create an xml bitmap and use it as background for the view. To prevent stretching you can specify android:gravity attribute.
for example:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/dvdr"
android:tileMode="disabled" android:gravity="top" >
</bitmap>
There are a lot of options you can use to customize the rendering of the image
http://developer.android.com/guide/topics/resources/drawable-resource.html#Bitmap
You should use ImageView if you don't want it to stretch.
Background images will always stretch to fit the view.
You need to set it as a Drawable to force the image aspect to the object.
Otherwise, if you are sticking with the Button idea, then you will need to force the scaling in the button to prevent the image from stretching.
Code:
onCreate(Bundle bundle) {
// Set content layout, etc up here
// Now adjust button sizes
Button b = (Button) findViewById(R.id.somebutton);
int someDimension = 50; //50pixels
b.setWidth(someDimension);
b.setHeight(someDimension);
}
Simply using ImageButton instead of Button fixes the problem.
<ImageButton android:layout_width="30dp"
android:layout_height="30dp"
android:src="#drawable/bgimage" />
and you can set
android:background="#null"
to remove button background if you want.
Quick Fix !! :-)
I am using an ImageView in an RelativeLayout that overlays with my normal layout. No code required.
It sizes the image to the full height of the screen (or any other layout you use) and then crops the picture left and right to fit the width. In my case, if the user turns the screen, the picture may be a tiny bit too small. Therefore I use match_parent, which will make the image stretch in width if too small.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/main_backgroundImage"
android:layout_width="match_parent"
//comment: Stretches picture in the width if too small. Use "wrap_content" does not stretch, but leaves space
android:layout_height="match_parent"
//in my case I always want the height filled
android:layout_alignParentTop="true"
android:scaleType="centerCrop"
//will crop picture left and right, so it fits in height and keeps aspect ratio
android:contentDescription="#string/image"
android:src="#drawable/your_image" />
<LinearLayout
android:id="#+id/main_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</LinearLayout>
</RelativeLayout>
I had the same problem: you should only use a 9-patch image (.9.png) instead of your original picture.
Serge
Use draw9patch... included within Android Studio's SDK tools. You can define the stretchable areas of your image. Important parts are constrained and the image doesn't look all warped. A good demo on dra9patch is HERE
Use draw9patch to change your existing splash.png into new_splash.9.png,
drag new_splash.9.png into the drawable-hdpi project folder
ensure the AndroidManifest and styles.xml are proper as below:
AndroidManifest.xml:
<application
...
android:theme="#style/splashScreenStyle"
>
styles.xml:
<style name="splashScreenStyle" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:windowBackground">#drawable/new_splash</item>
</style>
I had a background image, not big in size, but with weird dimensions - therefore the stretching and bad performance. I made a method with parameters Context, a View and a drawable ID(int) that will match the device screen size. Use this in e.g a Fragments onCreateView to set the background.
public void setBackground(Context context, View view, int drawableId){
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),drawableId);
bitmap = Bitmap.createScaledBitmap(bitmap, Resources.getSystem().
getDisplayMetrics().widthPixels,
Resources.getSystem().getDisplayMetrics().heightPixels,
true);
BitmapDrawable bitmapDrawable = new BitmapDrawable(context.getResources(),
bitmap);
view.setBackground(bitmapDrawable);
}
Here's a version of Santosh's answer for programmatically-created buttons, without the need for a separate XML configuration:
Button button = new Button(getContext());
Bitmap backgroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.my_button);
BitmapDrawable backgroundDrawable = new BitmapDrawable(getResources(), backgroundBitmap);
backgroundDrawable.setGravity(Gravity.CENTER); // also LEFT, CENTER_VERTICAL, etc.
backgroundDrawable.setColorFilter(new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC_ATOP));
button.setBackground(backgroundDrawable);
I included the ColorFilter line since that works a little differently from buttons with a normal background image.
You can use a FrameLayout with an ImageView as the first child, then your normal layout as the second child:
<?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="match_parent">
<ImageView
android:id="#+id/background_image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#drawable/your_drawable"/>
<LinearLayout
android:id="#+id/your_actual_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
</FrameLayout>
The key is to set the drawable as the image of the button, not as a background. Like this:
rb.setButtonDrawable(R.drawable.whatever_drawable);
One can use a plain ImageView in his xml and make it clickable
(android:clickable="true")?
You only have to use as src an image that has been shaped like a button i.e round corners.

Android ignores scrollbarsize

I'm trying to modify a ListView scrollbar's width without success
<ListView
android:id="#+id/android:list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:choiceMode="singleChoice"
android:scrollbars="vertical"
android:scrollbarTrackVertical="#drawable/scrollbar_vertical_track"
android:scrollbarThumbVertical="#drawable/scrollbar_vertical_thumb"
android:scrollbarSize="4px"
android:clickable="true"/>
First I tried using a drawable image 4px wide, but the .png was resized. Then I tried using a shape extracted from SamplesApi, without success.
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40px">
<gradient android:startColor="#505050" android:endColor="#C0C0C0"
android:angle="0"/>
<corners android:radius="0dp" />
I've tried with and without the android:width attribute.
There's a question on the same topic (Width of a scroll bar in android), but it doesn't try anything different that what I'm already trying. As far as I know, creating my own theme shouldn't change the output.
There's an example in SamplesApi (Views/ScrollBars). I tried modifying the scrollbarSize attribute without result.
I know about ninepatch images, but there's an attribute which should do what I want.
Any hint? Thanks in advance.
By my experience, Android ignores scrollbarSize, and computes size of both scrollbars from height of horizontal scroll track drawable (PNG image) which is set by android:scrollbarTrackHorizontal.
Did you tried
android:scrollbarSize="wrap_content"
and then just putting the size thru shape? I had kind of the same problem like this and I solved it in that way

Categories

Resources