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

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.

Related

Ion sets the imageView height to a wrong value

I dont know why this is happening: After loading the image with the Ion library, my image shows two white bars below and above image. I don't want to have that.
My ImageView is displayed in a listview item. My adapter code looks like this:
if (node.getImageUrl() != null) {
ivImage.setVisibility(View.VISIBLE);
Ion.with(ivImage)
.placeholder(R.drawable.anne_eli_icons_set_up_anne_eli_logo_530px)
//.error(R.drawable.error_image)
//.animateLoad(android.R.anim.cycle_interpolator)
.animateIn(android.R.anim.fade_in)
.load("http://app.anne-eli.at/" + node.getImageUrl().getUrlBig());
} else {
ivImage.setVisibility(View.GONE);
}
My imageview layout like this:
<LinearLayout ...
<ImageView
android:id="#+id/fragment_appointment_list_item_article_iv_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/anne_eli_icons_set_up_anne_eli_logo_530px"
android:background="#color/gray1" />
</LinearLayout>
Any ideas?
change your imageview layout to this one:
<LinearLayout ...
<ImageView
android:id="#+id/fragment_appointment_list_item_article_iv_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY" <!-- this line added , also your can use other value too like cropCenter ... -->
android:src="#drawable/anne_eli_icons_set_up_anne_eli_logo_530px"
android:background="#color/gray1" />
</LinearLayout>
I think it may be whatever value "gray1" is, but it looks very white because it's lighter than the image in the background. Remove the background attribute in the xml and it'll be invisible.
Likewise, without setting a scaleType on the ImageView, it's going to default to center. This will attempt to resize the image so it fits to the center of the ImageView without cropping. The ImageView is bound to the width of it's container. The image provided is much wider than that, so it shrinks the image to fit. This means the tops and bottoms will be shrunk as well, and the image becomes smaller than the height of the container. If you want the image to be near the top, you can try setting the scaleType to fitStart instead.

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

Full screen background image in an activity

I see many applications that use a full-screen image as background.
This is an example:
I want to use this in a project, the best way I've found so far to do this is to use an image with a large size, put it in a ImageView and use android: adjustViewBounds="true" to adjust the margins
The problem is that if a screen with a very high resolution, the image falls short.
Another option I thought of is to use the image in a FrameLayout, with match_parent in width and height as background... this stretches the image, but I think the result is not very good.
How would you do it?
There are several ways you can do it.
Option 1:
Create different perfect images for different dpi and place them in related drawable folder. Then set
android:background="#drawable/your_image"
Option 2:
Add a single large image. Use FrameLayout. As a first child add an ImageView. Set the following in your ImageView.
android:src="#drawable/your_image"
android:scaleType = "centerCrop"
Another option is to add a single image (not necessarily big) in the drawables (let's name it backgroung.jpg), create an ImageView iv_background at the root of your xml without a "src" attribute.
Then in the onCreate method of the corresponding activity:
/* create a full screen window */
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.your_activity);
/* adapt the image to the size of the display */
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
Bitmap bmp = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(
getResources(),R.drawable.background),size.x,size.y,true);
/* fill the background ImageView with the resized image */
ImageView iv_background = (ImageView) findViewById(R.id.iv_background);
iv_background.setImageBitmap(bmp);
No cropping, no many different sized images.
Hope it helps!
You should put the various size images into the followings folder
for more detail visit this link
ldpi
mdpi
hdpi
xhdpi
xxhdpi
and use RelativeLayout or LinearLayout background instead of using ImageView as follwoing example
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#drawable/your_image">
</RelativeLayout>
It's been a while since this was posted, but this helped me.
You can use nested layouts. Start with a RelativeLayout, and place your ImageView in that.
Set height and width to match_parent to fill the screen.
Set scaleType="centreCrop" so the image fits the screen and doesn't stretch.
Then you can put in any other layouts as you normally would, like the LinearLayout below.
You can use android:alpha to set the transparency of the image.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#drawable/image"
android:alpha="0.6"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="There"/>
</LinearLayout>
</RelativeLayout>
What about
android:background="#drawable/your_image"
on the main layout of your activity?
This way you can also have different images for different screen densities by placing them in the appropriate res/drawable-**dpi folders.
If you want your image to show BEHIND a transparent Action Bar, put the following into your Theme's style definition:
<item name="android:windowActionBarOverlay">true</item>
Enjoy!
use this
android:background="#drawable/your_image"
in your activity very first linear or relative layout.
In lines with the answer of NoToast, you would need to have multiple versions of "your_image" in your res/drawable-ldpi,mdpi, hdpi, x-hdpi (for xtra large screens), remove match_parent and keep android: adjustViewBounds="true"
Add android:background="#drawable/your_image" inside your Relativelayout/Linearlayout
Worked.
If you have bg.png as your background image then simply:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/bg"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="#string/hello_world"/>
</RelativeLayout>
Working. you should tryout this:
android:src="#drawable/img"
three step for put background
1)you should choose your like picture. for example :enter image description here
2)Then you copy this picture in drawable.
warning: you should choose types short for name picture.
enter image description here
3)you go to page xml Intended and write :
android:background="id picture"
for example my picture id is #drawable/download.
enter image description here
finish.
The easiest way:
Step 1: Open AndroidManifest.xml file
You can see the file here!
Step 2: Locate android:theme="#style/AppTheme" >
Step 3: Change to android:theme="#style/Theme.AppCompat.NoActionBar" >
Step 4: Then Add ImageView & Image
Step 4: That's it!

Android: Stretch bitmap to fill entire screen

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

Displaying a small png (drawable) in a larger ImageView

I am displaying a tiny png drawable resource in an ImageView of larger dimensions than the original image. This is normal and what I want by the way :)
When the ImageView is displayed, the image is blurry, because of the scaling method used I suppose.
I would like to achieve an effect similar to :
http://www.41post.com/4241/programming/android-disabling-anti-aliasing-for-pixel-art
where the original image is upscaled without antialiasing.
Is there a way to achieve that directly with an ImageView of certain width and height (in dips) and a drawable, without having to use an intermediate Bitmap?
<?xml version="1.0" encoding="utf-8"?>
<bitmap
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/image"
android:antialias="false" />
You need to create an drawable, copy the code above on an xml in the drawable folder, then on your layout instead of using your image as source use this xml. This way you disable the antialias for the image.
Edit: doing this in code.
BitmapDrawable draw = new BitmapDrawable(R.drawable.image);
draw.setAntiAlias(false);
imageView.setImageDrawable(draw);
Did you try turning off antialiasing in the layout?
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:antialias="false" />

Categories

Resources