How to get gravity 'bottom' working on a drawable in xml

22,552

Solution 1

I'd recommend using a nine-patch image for this - here's an example that should do the job:

Example nine-patch image

(It's only tiny but it is there!)

If you place this in your drawable folder and set your FrameLayout's background to it then you should get the desired result. The content will go in the grey area and the #010101 pixel will be stretched horizontally to form a line at the bottom. Just make sure to keep the .9.png extension to ensure it gets loaded as a nine-patch.

Hope that helps you

Solution 2

I've struggled a lot with this as well. Basically, to create a border at the bottom, you have to think in opposite direction from what you expect. You start with a rectangle with your Border color. On top of that, you draw the actual color, with an offset from the bottom. I use this:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <!-- CREATE A RECTANGLE WITH YOUR BORDER COLOR -->
    <item>
        <shape android:shape="rectangle" >
            <solid android:color="#fff"/>
        </shape>
    </item>

    <!-- NOW DEFINE THE NORMAL COLOR-->
    <item android:bottom="BOTTOM_BORDER_THICKNESS E.G. 4dp">
        <shape android:shape="rectangle" >
            <solid android:color="#ccc"/>
        </shape>
    </item>
</layer-list>

Or, as Juan Pablo Saraceno suggested :

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" > 
    <item> 
        <color android:color="YOUR_BORDER_COLOR" /> 
    </item> 
    <item android:top="YOUR_BORDER_THICKNESS"> 
        <color android:color="YOUR_BG_COLOR" /> 
    </item> 
</layer-list>

Solution 3

Unfortunately I have not found a way to get the gravity working for drawables, but I found how you can achieve what you want with pure xml:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:top="-2dp"
        android:left="-2dp"
        android:right="0dp"
        android:bottom="1dp"
        >
        <shape android:shape="rectangle">
            <solid android:color="#EEEEEE"/>
            <stroke android:width="1dp" android:color="#010101"/>
        </shape>
    </item>
</layer-list>

Good luck:)

Solution 4

This works!

<item>
      <bitmap
         android:gravity="left|bottom"
         android:src="@drawable/myDrawable" />
 </item>

Solution 5

I know it's pretty old question but given answers didn't work for me. Turns out in order to gravity property work you just need to add size tag in drawable item.

So following will work as expected:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:gravity="center">
        <shape android:shape="rectangle">
            <solid android:color="#EEEEEE" />
        </shape>
    </item>
    <item
        android:gravity="bottom">
        <shape android:shape="line">
            <size android:height="2dp"/>
            <stroke android:width="1dip" android:color="#010101"/>
        </shape>
    </item>
</layer-list>

ps. this feature added in api level 23 https://developer.android.com/reference/android/graphics/drawable/LayerDrawable#setLayerGravity%28int,%20int%29

Share:
22,552
ac_
Author by

ac_

Updated on July 09, 2022

Comments

  • ac_
    ac_ almost 2 years

    I have a simple aim. I want a light grey background on my FrameLayout with a black dividing line underneath it (only undernearth, not all around). So far I have this:

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item>
            <shape android:shape="rectangle" android:gravity="center">
                <solid android:color="#EEEEEE" />
            </shape>
        </item>
        <item>
            <shape android:shape="line" android:gravity="bottom" >
                <stroke android:width="1dip" android:color="#010101"/>
            </shape>
        </item>
    </layer-list>
    

    But it draws the line through the centre, i.e. ignores the gravity='bottom' bit. How can I fix this?

    EDIT: This question is very old. The selected answer may or may not be in-line with current APIs, etc. You are encouraged to start your own question rather than add to this one, which is no longer monitored.

  • ac_
    ac_ over 12 years
    That's a good point, I could do it that way. In fact, I will but I'd still be interested to know hot to get the gravity tag working for that line - seems a lot nicer solution to me but thanks for your suggestion.
  • kingraam
    kingraam over 12 years
    No mention of the gravity tag here. I can't see any way to achieve this using pure xml, you could create the ShapeDrawable in code and set its bounds based on the bounds of the layout?
  • Juan Pablo Saraceno
    Juan Pablo Saraceno over 10 years
    This is a really good answer and deserves to be better positioned IMHO. I think is a bit of a shame that android doesn't support gravity the proper way and forces one to do this. It worked for me even using <color> tags instead of rectangle, shapes, so even more simple. <layer-list xmlns:android="schemas.android.com/apk/res/android" > <item> <color android:color="YOUR_BORDER_COLOR" /> </item> <item android:top="YOUR_BORDER_THICKNESS"> <color android:color="YOUR_BG_COLOR" /> </item> </layer-list>
  • Marcin Koziński
    Marcin Koziński about 10 years
    The only problem is that i generates overdraw, because you are drawing a full rectangle with the color of your border only to overdraw it with the actual rectangle. Without real gravity still 9-patch wins.
  • A. Steenbergen
    A. Steenbergen over 9 years
    This wont work if you need a translucent top part and a solid bottom part. So I guess I will have to work with a nine-patch?
  • M. Usman Khan
    M. Usman Khan about 9 years
    <item> <bitmap android:gravity="left|bottom" android:src="@drawable/myDrawable" /> </item>
  • nsvir
    nsvir about 8 years
    Nop it doesn't for ShapeDrawable because it is a drawable, not a Bitmap.
  • DrGrijando
    DrGrijando about 6 years
    This solution works like a charm, because using the "put a rectangle covering the stroke of the other rectangle" solution left me sometimes with a tiny 1 pixel border on the right of the text boxes.
  • Leonid Ustenko
    Leonid Ustenko over 5 years
    Doesn't work for API 21. Bottom line just got stretched to full height
  • Andrzej Zabost
    Andrzej Zabost almost 5 years
    Just tested on API 22 and it doesn't work. Looks properly in the Android Studio Preview panel though.