Is there an easy way to add a border to the top and bottom of an Android View?
Asked Answered
D

25

437

I have a TextView and I'd like to add a black border along its top and bottom borders. I tried adding android:drawableTop and android:drawableBottom to the TextView, but that only caused the entire view to become black.

<TextView
    android:background="@android:color/green"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:drawableTop="@android:color/black"
    android:drawableBottom="@android:color/black"
    android:text="la la la" />

Is there a way to easily add a top and bottom border to a View (in particular, a TextView) in Android?

Demote answered 21/10, 2009 at 0:34 Comment(3)
It's surprising nobody has mentioned dividerVertical ! This is the thing created by Android, to achieve, well, vertical dividers. COoldn't be easier and you do everything in the "Design" WYSIWYG panel in Android Studio.Minefield
note dividerVertical was implemented in API 11.Oneiric
Maybe you can show how to use dividerVertical?Comintern
O
458

In android 2.2 you could do the following.

Create an xml drawable such as /res/drawable/textlines.xml and assign this as a TextView's background property.

<TextView
android:text="My text with lines above and below"
android:background="@drawable/textlines"
/>

/res/drawable/textlines.xml

<?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:width="1dp" android:color="#FF000000" />
            <solid android:color="#FFDDDDDD" />

        </shape>
   </item>

   <item android:top="1dp" android:bottom="1dp"> 
      <shape 
        android:shape="rectangle">
            <stroke android:width="1dp" android:color="#FFDDDDDD" />
            <solid android:color="#00000000" />
        </shape>
   </item>

</layer-list>

The down side to this is that you have to specify an opaque background colour, as transparencies won't work. (At least i thought they did but i was mistaken). In the above example you can see that the solid colour of the first shape #FFdddddd is copied in the 2nd shapes stroke colour.

Osteopathy answered 30/11, 2010 at 11:43 Comment(9)
Also see this solution, which also works for TextViews, if you want a border all around: #3264111Demote
Try using android:color="@null" to avoid opaque background problem.Grouper
@Demote : when testing this code on tablet , it takes time to render on screen, after 1 sec borders get displayed when I scrollTuchun
The android:color="@null" trick didn't do the trick for me for keeping transparency and just displaying a border at one side of the view. Answer from user1051892 below did the job!Pickings
This solution made a border on the left and right as well - though a thinner one.Alkane
why not use @android:color/transparent instead #00000000 to get a better pattern?Rosarosabel
Yes, you can use @android:color/transparent. I didn't just for clarity in the example code.Osteopathy
This is broken on Ice Cream Sandwich. A line shows on the right hand edge.Complement
@kilaka If you changed the colors, make sure that you changed them in the bottom item too.Pennate
L
316

I've used a trick so that the border is displayed outside the container. With this trick only a line is drawn so the background will be shown of the underlying view.

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

            <solid android:color="#00FFFFFF" />

            <padding android:left="10dp"
                android:right="10dp"
                android:top="10dp"
                android:bottom="10dp" />
        </shape>
    </item>

</layer-list>
Legitimist answered 24/5, 2012 at 7:26 Comment(10)
This worked great for me, with a few tweaks to make the line a bit thinner.Quadrivium
Very nice trick, although it could be nicer if we don't have to trick the computer in order to get things done.Vinery
nicely done! what you should watch is item's left, top, right, bottom should -(stroke's width)dpWolfsbane
Didn't show any border - just made my view content look smaller :(Alkane
Nicely done, worked with transparent background. Tested in 2.2 and 4.4.2. Should cover all in between :)Bialy
That's the right one! This one also works on Android 4.0.3 and higher.Dundalk
Thanks! I was messing around to try to do such a thing for half a day now. You just solved it to me :) much appreciated!Eclogue
This solution works - I just don't like having to explain myself to the next dev why I added negative values. This is, after all, a hack. Nicely done though.Desdee
@Demote I suggest to select this answer as the valid one, since it doesn't add a background and it only adds a border to the bottom. Will be more easy for other people to spot the right answer.Bink
I delete this line <solid android:color="#00FFFFFF" />, it also works~Entrepreneur
L
121

To add a 1dp white border at the bottom only and to have a transparent background you can use the following which is simpler than most answers here.

For the TextView or other view add:

android:background="@drawable/borderbottom"

And in the drawable directory add the following XML, called borderbottom.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="-2dp">
        <shape android:shape="rectangle">
            <stroke android:width="1dp" android:color="#ffffffff" />
            <solid android:color="#00000000" />
        </shape>
    </item>
</layer-list>

If you want a border at the top, change the android:top="-2dp" to android:bottom="-2dp"

The colour does not need to be white and the background does not need to be transparent either.

The solid element may not be required. This will depend on your design (thanks V. Kalyuzhnyu).

Basically, this XML will create a border using the rectangle shape, but then pushes the top, right and left sides beyond the render area for the shape. This leaves just the bottom border visible.

Litre answered 23/6, 2015 at 4:37 Comment(6)
This is the best solution, as it does not create overdraw like the othersHousley
Is there a reason that negative positions are twice as big as stroke with (-2dp vs 1dp)? Seems to work when they are equal in amount (-1 and 1).Scapolite
@DenisKniazhev : When using -2dp the result was always clean. I think there was test case where the result was not clean. I can't remember if it was a low or high density screen or even an older version of Android (2.x maybe).Litre
Interesting. Do you know if this is a general case, for example if I use 4dp for stroke width should I use -8dp for positioning?Scapolite
@DenisKniazhev : (from memory) it looked like a floating point calculation that was just a little to big or small. This means a value of -5dp would be all that is needed with a width value of 4pd. It simply needed to be a little bigger to get over the float value inaccuracy.Litre
As for me solid is reduntFamine
E
102

Option 1: Shape Drawable

This is the simplest option if you want a border around a layout or view in which you can set the background. Create an XML file in the drawable folder that looks something like this:

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

    <solid android:color="#8fff93" />

    <stroke
        android:width="1px"
        android:color="#000" />

</shape>

You can remove the solid if you don't want a fill. The set background="@drawable/your_shape_drawable" on your layout/view.

Option 2: Background View

Here's a little trick I've used in a RelativeLayout. Basically you have a black square under the view you want to give a border, and then give that view some padding (not margin!) so the black square shows through at the edges.

Obviously this only works properly if the view doesn't have any transparent areas. If it does I would recommend you write a custom BorderView which only draws the border - it should only be a few dozen lines of code.

<View
    android:id="@+id/border"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignBottom="@+id/image"
    android:layout_alignLeft="@+id/image"
    android:layout_alignRight="@+id/image"
    android:layout_alignTop="@+id/main_image"
    android:background="#000" />

<ImageView
    android:id="@+id/image"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_...
    android:padding="1px"
    android:src="@drawable/..." />

If you're wondering, it does work with adjustViewBounds=true. However, it doesn't work if you want to have a background in an entire RelativeLayout, because there is a bug that stops you filling a RelativeLayout with a View. In that case I'd recommend the Shape drawable.

Option 3: 9-patch

A final option is to use a 9-patch drawable like this one:

You can use it on any view where you can set android:background="@drawable/...". And yes it does need to be 6x6 - I tried 5x5 and it didn't work.

The disadvantage of this method is you can't change the colours very easily, but if you want fancy borders (e.g. only a border at the top and bottom, as in this question) then you may not be able to do them with the Shape drawable, which isn't very powerful.

Option 4: Extra views

I forgot to mention this really simple option if you only want borders above and below your view. You can put your view in a vertical LinearLayout (if it isn't already) and then add empty Views above and below it like this:

<View android:background="#000" android:layout_width="match_parent" android:layout_height="1px"/>
Exclusive answered 17/10, 2012 at 10:56 Comment(7)
9 patch and the shape drawable are ok, but i would recommend against adding views or imageviews to solve such a problem. The reason being is that you should be removing as many such <elements> from your layouts to improve layout redrawing and animation. I would strip these out right away and implement some similar to option 1 or 2.Osteopathy
@Osteopathy That's true, but if you're using a custom ListView that doesn't support dividers a simple View is fine. The performance impact is next to nil, especially if you're sure to keep your layout depth down. It also circumvents bugs with ListView dividers across devices (I've seen some devices that ignore this property).Unreal
You can also use the efficient viewholder pattern with listviews to ensure you reduce the number of calls to findViewByID which is often the cause of poor list performance.Osteopathy
In iOS you have only one way to do that. On android you should test at least four, in my case option 4 was the way to go. Sometimes drawables as background hang to render, be aware of it.Forte
Why android didn't have the easiest solution for such things? as in other language, like HTML, CSS, or something JavaFX, WPF......Accede
Using "Option 2: Background View (in Relative Layout)" and it is working like a charm. Thanks a lot :)Versify
Option 1 sounds good but it creates borders to the left and right as well.Odelsting
M
39

The currently accepted answer doesn't work. It creates thin vertical borders on the left and right sides of the view as a result of anti-aliasing.

This version works perfectly. It also allows you to set the border widths independently, and you can also add borders on the left / right sides if you want. The only drawback is that it does NOT support transparency.

Create an xml drawable named /res/drawable/top_bottom_borders.xml with the code below and assign it as a TextView's background property.

<?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="#DDDD00" /> <!-- border color -->
        </shape>
    </item>

    <item
        android:bottom="1dp" 
        android:top="1dp">   <!-- adjust borders width here -->
        <shape android:shape="rectangle">
            <solid android:color="#FFFFFF" />  <!-- background color -->
        </shape>
    </item>
</layer-list>

Tested on Android KitKat through Marshmallow

Microfiche answered 10/6, 2016 at 0:36 Comment(2)
How to make inside transparent ?Immodest
@HiteshSahu I think the downside of this is that you would have to match the background of the layout with the background of the widget hereStaccato
H
36

So I wanted to do something slightly different: a border on the bottom ONLY, to simulate a ListView divider. I modified Piet Delport's answer and got this:

<?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/background_trans_light" />    

        </shape>
   </item>

    <!-- this mess is what we have to do to get a bottom border only. -->
   <item android:top="-2dp"
         android:left="-2dp"
         android:right="-2dp"
         android:bottom="1px"> 
      <shape 
        android:shape="rectangle">    
            <stroke android:width="1dp" android:color="@color/background_trans_mid" />
            <solid android:color="@null" />
        </shape>
   </item>

</layer-list>

Note using px instead of dp to get exactly 1 pixel divider (some phone DPIs will make a 1dp line disappear).

Hite answered 18/7, 2013 at 4:6 Comment(4)
dear! what is the value of "@color/background_trans_light"?Schilling
Cheers @phreakhead, this actually works for me! No top, left, or right border. Exactly what I needed, thanks!Restraint
Please can you explain why when you put -2dp it dissapears and when you put -1dp it is still visible? Thanks!Infertile
@Hite better if you add some explanation to thisScheld
C
12

Add file to res/drawable

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

Add link on this file to background property

Cardigan answered 11/4, 2020 at 13:32 Comment(0)
P
9

Just as @Nic Hubbard said, there is a very easy way to add a border line.

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

You can change the height and background color to whatever you want.

Pneumatometer answered 23/11, 2014 at 14:22 Comment(0)
D
8

You can also wrap the view in a FrameLayout, then set the frame's background color and padding to what you want; however, the textview, by default has a 'transparent' background, so you'd need to change the textview's background color too.

Dimissory answered 30/9, 2010 at 0:17 Comment(1)
Pretty simple. You control the size and direction of outlines by the margins of the inner View. Thanks.Abscess
J
8

My answers is based on @Emile version but I use transparent color instead of solid.
This example will draw a 2dp bottom border.

<?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:width="2dp"
                     android:color="#50C0E9" />
            <solid android:color="@android:color/transparent" />
        </shape>
    </item>
    <item  android:bottom="2dp" >
        <shape android:shape="rectangle" >
            <stroke  android:width="2dp"
                     android:color="@color/bgcolor" />
            <solid android:color="@android:color/transparent" />
        </shape>
    </item>
</layer-list>

@color/bgcolor is the color of the background on wich you draw your view with border.

If you want to change the position of the border change the offset with one of:

android:bottom="2dp"
android:top="2dp"
android:right="2dp"
android:left="2dp"

or combine them to have 2 or more borders:

android:bottom="2dp" android:top="2dp"
Johnsson answered 1/6, 2013 at 10:37 Comment(0)
M
6

Simplest way to add borders to inset the borders using InsetDrawable,following will show top border only :

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

        <solid android:color="@color/light_gray" />
        <stroke
            android:width=".5dp"
            android:color="@color/dark_gray" />
    </shape>
</inset>
Mizuki answered 7/10, 2018 at 13:49 Comment(0)
N
6

You can do this by this code snippet -

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!--Minus (-) how much dp you gave in the stroke width from left right-->
    <item android:left="-10dp" android:right="-10dp">
        <shape
            android:shape="rectangle">
            <stroke android:width="10dp" android:color="@android:color/holo_red_dark" />
           <!--This is the main background -->
            <solid android:color="#FFDDDDDD" />
        </shape>
    </item>
</layer-list>

Preview -

enter image description here

Noisette answered 9/3, 2021 at 18:56 Comment(0)
V
5

Why not just create a 1dp high view with a background color? Then it can be easily placed where you want.

Villon answered 30/9, 2013 at 20:40 Comment(0)
R
5

To change this:

<TextView
    android:text="My text"
    android:background="@drawable/top_bottom_border"/>

I prefer this approach in "drawable/top_bottom_border.xml":

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <gradient
                android:angle="270"
                android:startColor="#000"
                android:centerColor="@android:color/transparent"
                android:centerX="0.01" />
        </shape>
    </item>
    <item>
        <shape>
            <gradient
                android:angle="90"
                android:startColor="#000"
                android:centerColor="@android:color/transparent"
                android:centerX="0.01" />
        </shape>
    </item>
</layer-list>

This only makes the borders, not a rectangle that will appear if your background has a color.

Rennold answered 28/3, 2016 at 16:40 Comment(0)
A
4

First make a xml file with contents shown below and name it border.xml and place it inside the layout folder inside the res directory

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <stroke android:width="1dp" android:color="#0000" />
    <padding android:left="0dp" android:top="1dp" android:right="0dp"
        android:bottom="1dp" />
</shape>

After that inside the code use

TextView tv = (TextView)findElementById(R.id.yourTextView);
tv.setBackgroundResource(R.layout.border);

This will make a black line on top and bottom of the TextView.

Adenitis answered 13/3, 2012 at 5:28 Comment(3)
Yes, It will Work, I have checked. Button button= (Button) findViewById(R.id.button); button.setBackgroundResource(R.layout.border);Adenitis
I have used black color in the above xml file, your background color might be black, try by using some other color. It will definitely work <?xml version="1.0" encoding="UTF-8"?> <shape xmlns:android="schemas.android.com/apk/res/android"> <solid android:color="#474848" /> <stroke android:width="1dp" android:color="#ffff00" /> <padding android:left="1dp" android:top="1dp" android:right="1dp" android:bottom="1dp" /> </shape>Adenitis
Didn't work for me. The border line was painted in the middle of the text view - horizontally.Alkane
S
4

Just to add my solution to the list..

I wanted a semi transparent bottom border that extends past the original shape (So the semi-transparent border was outside the parent rectangle).

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
  <item>
    <shape android:shape="rectangle" >      
      <solid android:color="#33000000" /> <!-- Border colour -->
    </shape>
  </item>
  <item  android:bottom="2dp" >
    <shape android:shape="rectangle" >     
      <solid android:color="#164586" />
    </shape>
  </item>
</layer-list>

Which gives me;

enter image description here

Sociable answered 25/2, 2015 at 16:7 Comment(0)
S
4

Simply add Views at the top and bottom of the View

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/your_color"
        app:layout_constraintBottom_toTopOf="@+id/textView"
        app:layout_constraintEnd_toEndOf="@+id/textView"
        app:layout_constraintStart_toStartOf="@+id/textView" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:gravity="center"
        android:text="Testing"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/your_color"
        app:layout_constraintEnd_toEndOf="@+id/textView"
        app:layout_constraintStart_toStartOf="@+id/textView"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

</android.support.constraint.ConstraintLayout>
Save answered 23/1, 2019 at 23:10 Comment(0)
H
3

Write down below code

<View
    android:layout_width="wrap_content"
    android:layout_height="2dip"
    android:layout_below="@+id/topics_text"
    android:layout_marginTop="7dp"
    android:layout_margin="10dp"
    android:background="#ffffff" />
Hymenopterous answered 17/2, 2015 at 8:28 Comment(0)
C
1

Try wrapping the image with a linearlayout, and set it's background to the border color you want around the text. Then set the padding on the textview to be the thickness you want for your border.

Compete answered 20/3, 2011 at 0:22 Comment(0)
H
1

You can also use a 9-path to do your job. Create it so that colored pixel do not multiply in height but only the transparent pixel.

Hailstone answered 17/4, 2012 at 16:20 Comment(0)
S
1

Based on accepted answer of Pi Delport and Emile, I made it a little simpler

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>  <!--divider TOP and BOTTOM-->
    <shape android:shape="rectangle">
        <stroke 
            android:width="1dp"
            android:color="@color/divider" />
    </shape>
</item>

<!--background surface-->
<item
    android:top="1dp"
    android:bottom="1dp">
    <shape android:shape="rectangle">
        <solid android:color="@color/background" />
    </shape>
</item>
Sawbuck answered 9/5, 2022 at 14:31 Comment(0)
L
0
// Just simply add border around the image view or view

<ImageView
                android:id="@+id/imageView2"
                android:layout_width="90dp"
                android:layout_height="70dp"
                android:layout_centerVertical="true"
                android:layout_marginRight="10dp"
                android:layout_toLeftOf="@+id/imageView1"
                android:background="@android:color/white"
                android:padding="5dip" />

// After that dynamically put color into your view or image view object

objView.setBackgroundColor(Color.GREEN);

//VinodJ/Abhishek
Lithium answered 7/2, 2014 at 12:53 Comment(0)
I
0
<shape xmlns:android="http://schemas.android.com/apk/res/android">

<solid android:color="@color/light_grey1" />
<stroke
    android:width="1dip"
    android:color="@color/light_grey1" />

<corners
    android:bottomLeftRadius="0dp"
    android:bottomRightRadius="0dp"
    android:topLeftRadius="5dp"
    android:topRightRadius="5dp" />

    </shape>
Injury answered 15/1, 2018 at 9:25 Comment(0)
P
-1
<TextView
    android:id="@+id/textView3"
    android:layout_width="match_parent"
    android:layout_height="2dp"
    android:background="#72cdf4"
    android:text=" aa" />

Just Add this TextView below the text where you want to add the border

Piccoloist answered 20/6, 2013 at 7:31 Comment(0)
S
-1

Just to enforce @phreakhead ´s and user1051892 ´s answers, <item android:bottom|android:left|android:right|android:top> if negative, must to be greater than <stroke android:width>. If not, item´s painting will be mixed with stroke´s painting and you may think these values are not working.

Sundog answered 7/9, 2018 at 14:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.