Shape drawable as background, a line at the bottom
Asked Answered
U

8

75

I am using a drawable as a background of a TextView just to have a divider line below the text. A achivied it with this drawable-xml:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item>
        <shape 
        android:shape="rectangle">
            <solid android:color="#FFDDDDDD" />
            <gradient 
                android:angle="0"
                android:startColor="#FFAAAAAA"
                android:endColor="#FFEEEEEE"
                />
        </shape>
    </item>

    <item android:bottom="2dp">
        <shape 
        android:shape="rectangle">
            <solid android:color="#FF000000" />
        </shape>
    </item>

</layer-list>

But this method draws a colored rectangle above a black rectangle. I would like to have just the line at the bottom of the shape with no black rectangle because black is not transparent. How could I achieve that?

Unpen answered 28/3, 2012 at 21:18 Comment(6)
Seems like overkill. Why not just use a colored view?Orazio
Same applies - how will I add a thin line at the bottom of that view?Unpen
That's what I meant, the view IS the line. <View android:backgroundColor="#FF000000" android:layout_height="2dp" android:layout_width="fill_parent"/>Orazio
Ah okay, so thats not a background, it is a very thin View wich will be the line itself! Will try out later. Nevertheless it would be nice to know how to bottom align something in a drawable xml.Unpen
In general, I try to mess as little as possible with backgrounds unless absolutely necessary, since doing so overrides the default background colors that have states for focused, pressed, etc.Orazio
For the lack of answers I guess there is no solution to do what I want with a drawable xml. So @Orazio just sum up you advise against it because of default background plus view and I will accept it as answer ;)Unpen
O
32

In general, I try to mess as little as possible with backgrounds unless absolutely necessary, since doing so overrides the default background colors that have states for focused, pressed, etc. I suggest just using an additional view (in a vertical LinearLayout) that is as thick as you need it to be. For example:

 <View 
       android:background="#FF000000" 
       android:layout_height="2dp" 
       android:layout_width="fill_parent"/>
Orazio answered 30/3, 2012 at 19:30 Comment(4)
hmmm I am not very convinced about your solution, for it needs an additional layout and an additional view, both are heavy objects just for an horizontal line... If you guys are allergic to backgrounds why not override onDraw() and just draw a line?Gasometer
ahahahahaha very simple, very brillant. I have tried without success do a simple bottom line background. Why i dont think this? thank youCacophonous
Yeah, no. You should use as few views as possible, adding one only for a view background is extremely inefficient and should only be used in trivial cases where there is almost nothing on the screen.Scleroma
Overriding backgrounds can be a nice solution, as long as you also use a selector to draw the most important states such as pressed or selected.Yelmene
E
223

This is how I got a line at the bottom for mine. Draw a stroke but then shift the item up and to the sides to get the top and sides to not show the stroke:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:top="-8dp" android:left="-8dp" android:right="-8dp">
        <shape> 
            <solid android:color="#2b7996"/>
            <stroke android:color="#33b5e5" android:width="6dp"/>
        </shape>
    </item>
</layer-list>
Expendable answered 2/1, 2014 at 20:20 Comment(7)
I sounded like the OP wanted to avoid having color in the solid area. It that's the case. Instead of #2b7996, the solid could be transparent with #00000000. An 8 digit hex value specifies the alpha with the first two digits.Jock
I like this solution, It is useful in RecyclerView as a divider of items, can reduce a layer of layout.Brownlee
Getting rid of the <solid android:color="#2b7996"/> gave me the desired results, with just the underline (on Galaxy S4 (Kit Kat) at least...not sure about other devices).Volauvent
<solid android:color="#2b7996"/> What if I wanted color = transparentLugo
its work fine but how to achieve radius of corners :(Tropopause
@Veronicaveronika increase negative margin to make it compatible with api 28 and above.Impressionable
@Impressionable So now we will have 2 different xml files for this solution. One for api level >= 28 and one for api level < 28Veronicaveronika
C
57

I think it's better solution:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:gravity="bottom">
        <shape>
            <size android:height="1dp" />
            <solid android:color="#000000" />
        </shape>
    </item>
</layer-list>
Cyclic answered 28/4, 2017 at 7:15 Comment(2)
This solution works for almost all devices except Samsung Lollipop ones. The whole view is drawn with the color provided in solid tag. This should not be ignored because of Samsung share of the market.Red
This solution does not work on Nexus 4 / API 22 and Emulator / API 19 too. Probably only supported since API 23.Masbate
O
32

In general, I try to mess as little as possible with backgrounds unless absolutely necessary, since doing so overrides the default background colors that have states for focused, pressed, etc. I suggest just using an additional view (in a vertical LinearLayout) that is as thick as you need it to be. For example:

 <View 
       android:background="#FF000000" 
       android:layout_height="2dp" 
       android:layout_width="fill_parent"/>
Orazio answered 30/3, 2012 at 19:30 Comment(4)
hmmm I am not very convinced about your solution, for it needs an additional layout and an additional view, both are heavy objects just for an horizontal line... If you guys are allergic to backgrounds why not override onDraw() and just draw a line?Gasometer
ahahahahaha very simple, very brillant. I have tried without success do a simple bottom line background. Why i dont think this? thank youCacophonous
Yeah, no. You should use as few views as possible, adding one only for a view background is extremely inefficient and should only be used in trivial cases where there is almost nothing on the screen.Scleroma
Overriding backgrounds can be a nice solution, as long as you also use a selector to draw the most important states such as pressed or selected.Yelmene
X
7

Usually for similar tasks - I created layer-list drawable like this one:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
    <shape android:shape="rectangle">
        <solid android:color="@color/underlineColor"/>
    </shape>
</item>
<item android:bottom="3dp">
    <shape android:shape="rectangle">
        <solid android:color="@color/buttonColor"/>
    </shape>
</item>

The idea is that first you draw the rectangle with underlineColor and then on top of this one you draw another rectangle with the actual buttonColor but applying bottomPadding. It always works.

But when I needed to have buttonColor to be transparent I couldn't use the above drawable. I found one more solution

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
    <shape android:shape="rectangle">
        <solid android:color="@android:color/transparent"/>
    </shape>
</item>

<item android:drawable="@drawable/white_box" android:gravity="bottom" android:height="2dp"/>
</layer-list>

(as you can see here the mainButtonColor is transparent and white_box is just a simple rectangle drawable with white Solid)

Xerarch answered 19/7, 2017 at 13:24 Comment(1)
android:gravity="bottom" needs min API 23 to work.Necktie
S
3

With this solution where ever you require different line you can. My requirement was underline only. Even you can give different colors to the layout. You can see in below picture, white line enter image description here

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

    <item android:top="-5dp" android:left="-5dp" android:right="-5dp">
        <shape>
            <solid android:color="@android:color/transparent"/>
            <stroke android:color="@color/white" android:width="5dp"/>
        </shape>
    </item>

    <item android:top="-5dp" android:bottom="-5dp" android:right="-5dp">
        <shape>
            <solid android:color="@android:color/transparent"/>
            <stroke android:color="@color/colorPrimaryDark" android:width="5dp"/>
        </shape>
    </item>

    <item android:bottom="-5dp" android:left="-5dp" android:right="-5dp">
        <shape>
            <solid android:color="@android:color/transparent"/>
            <stroke android:color="@color/colorPrimaryDark" android:width="5dp"/>
        </shape>
    </item>

    <item android:top="-5dp" android:left="-5dp" android:bottom="-5dp">
        <shape>
            <solid android:color="@android:color/transparent"/>
            <stroke android:color="@color/colorPrimaryDark" android:width="5dp"/>
        </shape>
    </item>

    <item android:bottom="2dp" android:left="5dp" android:right="5dp" android:top="5dp">
        <shape>
            <solid android:color="@color/colorPrimary"/>

            <corners android:bottomRightRadius="0dp"
                android:bottomLeftRadius="0dp"
                android:topLeftRadius="0dp"
                android:topRightRadius="0dp" />
        </shape>
    </item>
</layer-list>
Swampy answered 28/6, 2017 at 11:54 Comment(0)
F
2

This is a slightly lighter variant of the above.

/drawable/rect_highlight.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
    <stroke android:width="1px" android:color="@color/colorHighlight"/>
</shape>

/drawable/underline.xml

<inset xmlns:android="http://schemas.android.com/apk/res/android" android:insetLeft="-1px" android:insetRight="-1px" android:insetTop="-1px" android:drawable="@drawable/rect_highlight"/>

Usage:

<TextView ... android:background="@drawable/underline"/>

It's not mine, somebody smarter than I came up with it. If I was smarter, I would have asked who. :)

Footpoundsecond answered 14/11, 2019 at 18:51 Comment(0)
T
1

This solution worked for most of the cases that I needed something like that.

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@android:color/transparent" /> <!--background color of box-->
        </shape>
    </item>

    <item
        android:height="2dp"
        android:gravity="bottom">
        <shape>
            <solid android:color="#000000" />
        </shape>
    </item>
</layer-list>
Trev answered 21/1, 2022 at 23:48 Comment(0)
E
-1

A simple solution is extending a TextView, then override the onDraw.

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Paint paint = new Paint();
    paint.setColor(ContextCompat.getColor(getContext(),R.color.colorTextUnderLine));
    paint.setStrokeWidth(10);
    canvas.drawLine(0.0f,canvas.getHeight(),canvas.getWidth(),canvas.getHeight(),
            paint);
}
Erin answered 30/8, 2019 at 6:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.