3

NOTE: I have ended up reporting this as a bug to the android project here: http://code.google.com/p/android/issues/detail?id=39159 Please also have a look at the accepted bounty answer, the solution is, unfortunately, to use an absolute (ie specifiying 'dp's rather than 'wrap_content' etc) layout to fix the issue.

I'm getting some VERY strange behaviour when placing a background on an image. I have simplified this down quite heavily to demonstrate the issue to you. What im doing is placing an image in a relativelayout, and also using a background. It seems that giving the relativelayout a padding is causing the background of the image to be missdrawn. Wrap_content seems to be messing up.

Firstly, here is the code that demonstrates the problem. Note that the same behaviour is seen without using a linearlayout and just giving the imageview a background, but this really demonstrates the problem better.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="60dp"
        android:padding="5dp" >
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/black_bg" >
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:adjustViewBounds="true"
                android:src="@drawable/red_rectangle" />
        </LinearLayout>
    </RelativeLayout>
</FrameLayout>

Here is the black_bg xml file:

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#FF000000"/>
</shape> 

Here is red_rectangle: red_rectangle

NOTE that this is a reference image, to demonstrate the problem. my actual image has detail, and so cannot be a .9.png

And here is a screenshot of the problem:

Rendering error

You can see that the image width is less than the linearlayout, despite the linearlayout having a width set to "wrap_content". If I set the relativelayout padding to 0dp, this problem dissapears.

This is hopefully a fairly well contained set of resource I'm providing here, so people can try it out themselves if they wish.

For reference, I am using this to provide a border around the image, so I could set the linearlayout (or the image itself) to have a padding, the problem still persists in that case.

EDIT: It appears I probably need a little more context around this, as answers are focussing round how to provide this border. Here is a screenshot of a more contextual layout. I didnt want to include this in the first place as it adds more confusion to the problem:

Screenshot

The FIRST 5dp padding you see is for the content of this entire item (the relativelayout). Then, as i said originally, the idea is that "I could set the linearlayout (or the image itself) to have a padding" in addition to the first padding you see in the relativelayout. Currently, this layout should have NO border shown.

Sam
  • 3,453
  • 1
  • 33
  • 57
  • the resolution of the image is your porblem.. Use an image which can expand.. like a Vector(`.9png` images, for eg), or simply a `shape` . – Vinay W Sep 12 '12 at 17:08
  • note, that this is a reference image, to demonstrate the problem. my actual image has detail, and so cannot be a .9.png – Sam Sep 12 '12 at 17:11
  • I can see that you are not getting the result as you expected but your requirement is not clear. What is your expected layout and how do you want to use it. – karn Sep 12 '12 at 18:16
  • the expected layout is to see no black. Then for some layouts i can set a padding on the linearlayout (or on the imageview itself, if i put the background on that) and get a border. – Sam Sep 13 '12 at 10:32

5 Answers5

4

the problem seems to be with the different stretching properties of image(in image view) and the one set as a background(in linear layout). The image set as a backgroung doesnt necessarily maintains the aspect ratio while the image in the image tends to maintain it. When you give the height of the layout to 60 dp, the image shrinks maintaining the aspect ratio leaving the black strips on the sides. This works for me:

<?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" >
    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="60dp"
        android:padding="5dp" >
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/black_bg" >
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="60dp"
                android:src="@drawable/asd"
                android:scaleType="fitXY"
                 />
        </LinearLayout>
    </RelativeLayout>
</FrameLayout>
  • 1
    android:scaleType="fitXY" attribute in the image view explicitly makes the image in the image view strech without following the aspect ratio. – iHateCoding Oct 31 '12 at 10:26
  • im afraid this didnt work. the red rectangle drawable was heavily stretched – Sam Oct 31 '12 at 21:11
  • if you take my original example and remove the background altogether, then use the graphical layout tool and click to the right of the red rectangle, you will see the linearlayout has still not wrapped the content – Sam Oct 31 '12 at 21:19
1

I dont know why its showing the extra black patch there. Have you tried running the app? The UI editor has some defects, especially when it comes to ImageView..

Now for the border around image, set the background and padding to the ImageView itself. Do not need the LinearLayout. Add the scale type attribute with "centerInside" value.

 <ImageView 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:padding="5dp"
      android:layout_centerInParent="true"
      android:adjustViewBounds="true" 
      android:src="@drawable/red_rectangle"
      android:background="#000" 
      android:scaleType="centerInside"/> 
Ron
  • 24,175
  • 8
  • 56
  • 97
  • Yes, i think i spotted this problem running on a phone. my question was pretty long, so you probably missed this bit: Firstly, here is the code that demonstrates the problem. Note that the same behaviour is seen without using a linearlayout and just giving the imageview a background, but this really demonstrates the problem better. – Sam Oct 28 '12 at 23:52
  • `android:scaleType="centerInside"` – Ron Oct 29 '12 at 17:14
1

I believe this is a good candidate of a bug!

Anyway, I understand what you intend to achieve with this layout. The problem is setting the height of your RelativeLayout. I will not ask you to wrap content! Simply, since the height is set to 60dp and padding to 5dp, take a further step and set the height of the LinearLayout to 50dp which is 60-2*5 :)

Finally, to get the border, add a padding of, say, 5dp to your LinearLayout and set the Height of the ImageView to 50dp - 2*5 = 40dp.

This will work perfectly


<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="60dp"
        android:padding="5dp" >
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:padding="5dp"
            android:background="@drawable/black_bg" >
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="40dp"
                android:adjustViewBounds="true"
                android:src="@drawable/red_rectangle" />
        </LinearLayout>
    </RelativeLayout>
</FrameLayout>

Sherif elKhatib
  • 45,786
  • 16
  • 89
  • 106
  • Agh, doing absolute layout like that is against my morals lol but I guess its the only way for this... thank you for spending the time finding a solution and having a proper read of the question, really appreciated. I am no longer working on this project, but will try and test this ASAP. I think I will be putting this in as a bug on the android project. Link will appear here soon. I found 3 layout bugs in 2 months of development, Google should hire me :-P – Sam Oct 30 '12 at 12:37
  • This answer has been awarded the bounty. thanks very much for thoroughly reading and testing out my question Sherif. it is a shame the layout has to be done this way, but at least I have a confirmation of this bug from another source. – Sam Oct 31 '12 at 21:13
  • Looks like `RelativeLayout` can be removed, its padding can be `LinearLayout` margin, and `LinearLayout` may be `FrameLayout`. – Miha_x64 Sep 26 '19 at 13:00
0

"For reference, I am using this to provide a border around the image"

Add a drawable "border.xml"

<shape xmlns:android:"http://schemas.android.com/apk/res/android" android:shape:"rectangle">
 <stroke android:width="5dp" android:color="#FF000000" />
 <padding android:left="5dp" android:top="5dp" android:right="5dp" android:bottom="5dp" />
</shape>

set your ImageView background to this drawable.

And lets simplify your layout and center the ImageView:

<?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" > 
        <ImageView 
                android:layout_width="wrap_content" 
                android:layout_height="wrap_content" 
                android:layout_centerInParent="true"
                android:adjustViewBounds="true" 
                android:src="@drawable/red_rectangle"
                android:background="@drawable/border" /> 
</RelativeLayout> 
CSmith
  • 13,318
  • 3
  • 39
  • 42
  • no, although an interesting experiment. giving the linearlayout this background yields this result: http://i.imgur.com/OxN7b.png (note, i changed to FF0000FF, so you can see this). Giving this background to the imageview, and removing the linearlayout gives this result: http://i.imgur.com/lLFZK.png – Sam Sep 12 '12 at 17:10
  • perhaps also add padding="5dp" to the ImageView. Why is your RelativeLayout set to fixed height? What is the height of your Image resource? I'll make more edits to my answer – CSmith Sep 12 '12 at 17:27
  • i added padding to the imageview, but didnt get any result. i need a specific height. this is one of many items in a list. the image resource is larger than the relativelayout, yes. – Sam Sep 12 '12 at 17:33
  • add the padding element to the drawable. Check http://stackoverflow.com/questions/3263611/border-for-an-image-view-in-android, my initial answer was close. – CSmith Sep 12 '12 at 17:35
  • the padding element is for my surrounding layout, that will contain text and such. a further pading element would then be added to the linearlayout (or the imageview) to give the border. This is a simplified layout to show the issue. – Sam Sep 13 '12 at 10:34
  • here is the result of applying a background as suggested in that thread (again i replaced colours to blue): http://i.imgur.com/4Kw2w.png as you can see, the image is being expanded strangely, this was why i originally separated out the linearlayout. – Sam Sep 13 '12 at 11:41
  • the fact is that the linearlayout isnt wrapping its content, and i cant work out why – Sam Sep 13 '12 at 22:28
0

Try this ...........

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="60dp"
        android:padding="5dp" >
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/black_bg"
            **android:padding="5dp"**
            >
            <ImageView
                **android:layout_width="fill_parent"
                android:layout_height="fill_parent"**
                android:adjustViewBounds="true"
                android:src="@drawable/red_rectangle" />
        </LinearLayout>
    </RelativeLayout>
</FrameLayout>

make your image view like this ..

<ImageView 
            android:id="@+id/imageViewMyicon"
            android:layout_width="30dp"
            android:background="@drawable/myiconbackground"
            android:layout_height="30dp"
            android:src="@drawable/myicon"
            android:contentDescription="@string/my_icon"
            />

Inside your drawable myiconbackground.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android" 
       android:shape="rectangle" 
       android:padding="10dp">
    <solid android:color="#0D95BD"/>
        <corners android:radius="5dp"/>
        <padding android:left="2dp" android:right="2dp" android:top="2dp" android:bottom="2dp"/>
</shape>

i checked this one is working for me , should do for you as well