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
Related
I want to add an ImageButton to my layout that has the effect of scaling down in order to look like it's being pressed. So I basically have the original image #drawable/scan and the pressed image which is #drawable/scanhot. Scanhot is basically the same image scaled down.
My code is the following but it doesnt seem to work.
As you can see I am using a Button as opposed to an ImageButton because a Button could at least "switch" different images. However it does not do anything with similar images like scan/scanhot
button_rescan.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:drawable="#drawable/scanhot"/>
<item
android:drawable="#drawable/scan"/>
</selector>
layout
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp"
android:background="#android:color/transparent">
<Button
android:id="#+id/fragment_radar_rescan_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/button_rescan"
android:layout_gravity="center_horizontal"
android:layout_centerHorizontal="true"/>
</RelativeLayout
It looks that drawable/scanhot are not the same size drawable/scan (in pixels). So if you want effect of "zoom" (or whatever) you should still keep image size the same for both images (i.e. 100x100) and with the same size make scanhot look smaller. If you already got images scalled as you want, just load the smaller one to Gimp or Photoshop and scale its canvas to the size of the other image (which is bigger I assume) and then save. In that case canvas for both will be the same and you avoid additional scalling from ImageView
The problem with what you are doing is that when you set a picture to a background, it automatically is blown up to fit the View. Instead, both pictures should have the same resolution, but the picture in scanhot should just look smaller.
In otherwords, both pictures should have a 132x29 resolution (or rather, they should both be the same size)
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
I am trying to create a custom drawable which includes a 9-patch background image (named custom_bg below) and a regular png image (accordion_up). The latter should not be scaled.
I tried several variations of something along the lines of:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/custom_bg"/>
<item
android:layout_width="10dp"
android:layout_height="10dp"
android:drawable="#drawable/accordion_up"
android:gravity="right" />
</layer-list>
Tried different values for layout_width/layout_height and also width/height but all I get is the accordion image is stretched to fill the entire view. I would like it to float at the top right of the view instead, scaled only to match the dpi of the device, but not expanded to fit the view. How can I do that?
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
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" />