How to draw border on just one side of a linear layout?
Asked Answered
A

11

220

I'm able to draw border to a linear layout, but it is getting drawn on all sides. I want to restrict it to right side only, like you do in CSS (border-right:1px solid red;).

I've tried this, but it still draws on all sides:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
    <shape android:shape="rectangle" >
        <stroke
            android:height="2dp"
            android:width="2dp"
            android:color="#FF0000" />

        <solid android:color="#000000" />

        <padding
            android:bottom="0dp"
            android:left="0dp"
            android:right="1dp"
            android:top="0dp" />

        <corners
            android:bottomLeftRadius="0dp"
            android:bottomRightRadius="5dp"
            android:radius="1dp"
            android:topLeftRadius="5dp"
            android:topRightRadius="0dp" />
    </shape>
</item>

Any suggestions on how to accomplish this?

BTW, I do not want to use the hack of putting a view of width 1dp on the required side.

Anterior answered 9/2, 2012 at 12:54 Comment(1)
you can use drawableLeft in your layoutLaggard
W
391

You can use this to get border on one side

<?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="#FF0000" />
    </shape>
</item>
<item android:left="5dp">
    <shape android:shape="rectangle">
        <solid android:color="#000000" />
    </shape>
</item>
</layer-list>

EDITED

As many including me wanted to have a one side border with transparent background, I have implemented a BorderDrawable which could give me borders with different size and color in the same way as we use css. But this could not be used via xml. For supporting XML, I have added a BorderFrameLayout in which your layout can be wrapped.

See my github for the complete source.

Waxman answered 9/2, 2012 at 14:24 Comment(4)
what if you want a solid alpha based color with a bottom border? I have been thinking at a solution to that with the Android Drawable XML api but i can't figure it out.Madaih
This didn't work for me -- oddly did the inverse of what i wanted a darker color on the inside, with the grey gradient I overlayed for the boarders. Been thinking about making a rectangle drawable at a certain size to put as a drawableLeft on the item. This doesn't seem as streamlined.Roque
@jbenowitz: The order of the item in layer-list is more important. If u reverse then you will get those result.Waxman
I've fixed this by adding a stroke the border color and the shape remaining the button color. That did the trick.Roque
L
268

Easy as pie, allowing a transparent bg:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <gradient
        android:angle="0"
        android:startColor="#f00"
        android:centerColor="@android:color/transparent"
        android:centerX="0.01" />
</shape>

Change the angle to change border location:

  • 0 = left
  • 90 = bottom
  • 180 = right
  • 270 = top
Latrena answered 20/5, 2014 at 8:12 Comment(13)
This is by far the best answer here, too bad it's not upvotedLou
Nice, however I certainly wouldn't describe it as "easy as pie".Incarnate
This doesn't work if you need a thicker border or if you need borders on multiple sides.Confection
How can you set the height of this shape?Tivoli
@Tivoli - use this as a background to your view, then it will inherit its height.Latrena
But my view is a tab within a FragmentTabHost, and I want the height of the border to be like 70% less than the height of the tab and centered vertically.Tivoli
@WhereDatApp.com, how to use your solutions in a android layout? Sorry, I am new in Android.Christan
@GeisonSantos: this xml should actually go into a drawable, then use that drawable as a background to the view you want to have a one-sided border.Latrena
This is the best answerMccown
I tryed to create a View with customizable border in XML (like border="top|right". I used LayerDrawable to combine each single border programmatically. The single borders used inset which resulted in one border overdrawing the other (even with transparent background). With this solution it seems to work fine :) Thank youHenleyonthames
@WhereDatApp.com It seems like the border does not update, when height of View changes. So it possible draws the border in the middle of the view. Is there a workaround for this?Henleyonthames
how to adjust stroke or border width?Viand
Top and bottom borders look thicker than left and right ones in Android Studio Preview.Fat
L
114

it is also possible to implement what you want using a single layer

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

    <item
        android:bottom="-5dp"
        android:right="-5dp"
        android:top="-5dp">
        <shape android:shape="rectangle" >
            <solid android:color="@color/color_of_the_background" />

            <stroke
                android:width="5dp"
                android:color="@color/color_of_the_border" />
        </shape>
    </item>

</layer-list>

this way only left border is visible but you can achieve any combination you want by playing with bottom, left, right and top attributes of the item element

Liability answered 15/1, 2014 at 19:36 Comment(5)
This is definitely useful when you have other background color and you want to overlay this drawable bg with border. (y)Peregrinate
Exactly what I need, but is it right to use negative paddings?Bumpy
This is the best solution. I am bothering what does -5dp do there.Centrifugal
Negative padding is common in HTML/CSS. It simply nudges things the other direction. In my experience, it seems perfectly valid in Android as well.Golgotha
Implementations using negative margins don't work well if your layout has clipChildren=false or clipToPadding=false. If this is the case, you can use the solution with two overlapped rectangles, like the proposed by Vivek KhandelwalHappily
B
107

To get a border on just one side of a drawable, apply a negative inset to the other 3 sides (causing those borders to be drawn off-screen).

<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:insetTop="-2dp" 
    android:insetBottom="-2dp"
    android:insetLeft="-2dp">

    <shape android:shape="rectangle">
        <stroke android:width="2dp" android:color="#FF0000" />
        <solid android:color="#000000" />
    </shape>

</inset>

enter image description here

This approach is similar to naykah's answer, but without the use of a layer-list.

Balboa answered 3/1, 2015 at 23:0 Comment(7)
very good answer, I just need to change the width and inset to 10dp :) And more, I need border on left, so I change android:insetLeft to android:insetRight. So simple! Keeping Material button click :DCovenantor
Exactly what I needed, change insertX at the top to decide what borders to show and what not.Confectionery
I can even have a solid color of @null and then this method causes no overdraw. Genius. Thank you!Abduce
@user4050065 just change insetLeft to insetRight :)Scottyscotus
Used this to show just left and right. Nice solution!!Neaten
Attention: This will shift the content of your view and will also resize it. Use with care.Notify
This is the best answer, as it allows a transparent background and allows dp to be specified instead of resorting to the hack of compressing a gradient into a line.Matriculation
K
33

An other great example example

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<inset xmlns:android="http://schemas.android.com/apk/res/android"
     android:insetRight="-2dp">
     
     <shape android:shape="rectangle">
         <corners
             android:bottomLeftRadius="4dp"
             android:bottomRightRadius="0dp"
             android:topLeftRadius="4dp"
             android:topRightRadius="0dp" />
         <stroke
             android:width="1dp"
             android:color="#70b23f" />
         <solid android:color="@android:color/transparent" />
     </shape>
     
</inset>
Knut answered 10/12, 2019 at 8:4 Comment(2)
so far the best for meBenne
This is the most reliable answer that i've ever seen. Thank you –Foreground
A
9

As an alternative (if you don't want to use background), you can easily do it by making a view as follows:

<View
    android:layout_width="2dp"
    android:layout_height="match_parent"
    android:background="#000000" />

For having a right border only, place this after the layout (where you want to have the border):

<View
    android:layout_width="2dp"
    android:layout_height="match_parent"
    android:background="#000000" />

For having a left border only, place this before the layout (where you want to have the border):

Worked for me...Hope its of some help....

Adair answered 13/8, 2015 at 5:57 Comment(0)
D
7

I was able to achieve the effect with the following code

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

You can adjust to your needs for border position by changing the direction of displacement

Diffidence answered 15/7, 2017 at 18:16 Comment(0)
D
5
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" >
        <shape>
            <solid
                android:color="#f28b24" />
            <stroke
                android:width="1dp"
                android:color="#f28b24" />
            <corners
                android:radius="0dp"/>
            <padding
                android:left="0dp"
                android:top="0dp"
                android:right="0dp"
                android:bottom="0dp" />
        </shape>
    </item>
    <item>
        <shape>
            <gradient
                android:startColor="#f28b24"
                android:endColor="#f28b24"
                android:angle="270" />
            <stroke
                android:width="0dp"
                android:color="#f28b24" />
            <corners
                android:bottomLeftRadius="8dp"
                android:bottomRightRadius="0dp"
                android:topLeftRadius="0dp"
                android:topRightRadius="0dp"/>
            <padding
                android:left="10dp"
                android:top="10dp"
                android:right="10dp"
                android:bottom="10dp" />
        </shape>
    </item>
</selector>
Dispense answered 9/2, 2012 at 13:1 Comment(0)
A
2

There is no mention about nine-patch files here. Yes, you have to create the file, however it's quite easy job and it's really "cross-version and transparency supporting" solution. If the file is placed to the drawable-nodpi directory, it works px based, and in the drawable-mdpi works approximately as dp base (thanks to resample).

Example file for the original question (border-right:1px solid red;) is here:

http://ge.tt/517ZIFC2/v/3?c

Just place it to the drawable-nodpi directory.

Alexina answered 30/3, 2015 at 17:4 Comment(0)
H
2

Borders of different colors. I used 3 items.

<?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="@color/colorAccent" />
        </shape>
    </item>
    <item android:top="3dp">
        <shape android:shape="rectangle">
            <solid android:color="@color/light_grey" />
        </shape>
    </item>
    <item
        android:bottom="1dp"
        android:left="1dp"
        android:right="1dp"
        android:top="3dp">
        <shape android:shape="rectangle">
            <solid android:color="@color/colorPrimary" />
        </shape>
    </item>
</layer-list>
Hirudin answered 22/12, 2016 at 5:58 Comment(0)
M
0

You can wrap into container and define margins for start left bottom top. Suppose you want to provide margin for left side you can do this

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@color/light_blue"
    >
    <TextView
        android:marginStart="2dp" // This is Your border
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/white"
        android:padding="16dp"
        android:text="a"
        android:textColor="@color/light_blue"
        android:textSize="25dp" />
</RelativeLayout>
Misapprehend answered 17/6, 2021 at 13:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.