Is there an easy way to add a border to the top and bottom of an Android View?
Solution 1
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.
Solution 2
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>
Solution 3
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.
Solution 4
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 View
s above and below it like this:
<View android:background="#000" android:layout_width="match_parent" android:layout_height="1px"/>
Solution 5
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
emmby
Author of Android Application Development for Dummies. Author of RoboGuice, as well as the OpenTable, TripIt, and Digg Android applications. bebop Mobile at Google http://about.me/michaelburton
Updated on August 20, 2022Comments
-
emmby almost 2 years
I have a TextView and I'd like to add a black border along its top and bottom borders. I tried adding
android:drawableTop
andandroid: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?
-
emmby over 13 yearsAlso see this solution, which also works for TextViews, if you want a border all around: stackoverflow.com/questions/3263611/…
-
Matt Briançon almost 13 yearsTry using
android:color="@null"
to avoid opaque background problem. -
Chetan about 12 years@emmby : when testing this code on tablet , it takes time to render on screen, after 1 sec borders get displayed when I scroll
-
Nikhil Dinesh about 12 yearsYes, It will Work, I have checked. Button button= (Button) findViewById(R.id.button); button.setBackgroundResource(R.layout.border);
-
Nikhil Dinesh about 12 yearsI 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>
-
Emile over 11 years9 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.
-
Tom over 11 years@Emile 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).
-
Emile over 11 yearsYou 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.
-
Jeff about 11 yearsThis worked great for me, with a few tweaks to make the line a bit thinner.
-
Max about 11 yearsVery nice trick, although it could be nicer if we don't have to trick the computer in order to get things done.
-
asakura89 about 11 yearsnicely done! what you should watch is item's left, top, right, bottom should -(stroke's width)dp
-
Rick Pastoor almost 11 yearsThe 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!
-
AlikElzin-kilaka almost 11 yearsDidn't work for me. The border line was painted in the middle of the text view - horizontally.
-
AlikElzin-kilaka almost 11 yearsThis solution made a border on the left and right as well - though a thinner one.
-
AlikElzin-kilaka almost 11 yearsDidn't show any border - just made my view content look smaller :(
-
Shajeel Afzal almost 11 yearsdear! what is the value of
"@color/background_trans_light"
? -
ademar111190 almost 11 yearswhy not use @android:color/transparent instead #00000000 to get a better pattern?
-
Emile almost 11 yearsYes, you can use @android:color/transparent. I didn't just for clarity in the example code.
-
Ratata Tata over 10 yearsIn 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.
-
HumaN over 10 yearsNicely done, worked with transparent background. Tested in 2.2 and 4.4.2. Should cover all in between :)
-
MaxEcho over 10 yearsWorking without background color, great answer.
-
andrea.rinaldi over 10 yearsThat's the right one! This one also works on Android 4.0.3 and higher.
-
shanehoban about 10 yearsCheers @phreakhead, this actually works for me! No top, left, or right border. Exactly what I needed, thanks!
-
developer82 about 10 yearsThanks! I was messing around to try to do such a thing for half a day now. You just solved it to me :) much appreciated!
-
markshiz about 10 yearsThis is broken on Ice Cream Sandwich. A line shows on the right hand edge.
-
Dylan Vander Berg almost 10 years@kilaka If you changed the colors, make sure that you changed them in the bottom item too.
-
Francisco Romero almost 9 yearsPlease can you explain why when you put -2dp it dissapears and when you put -1dp it is still visible? Thanks!
-
Greg Ennis over 8 yearsThis is the best solution, as it does not create overdraw like the others
-
Hitesh Sahu almost 8 yearsHow to make inside transparent ?
-
chntgomez almost 8 years@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 here
-
Denys Kniazhev-Support Ukraine almost 8 yearsIs there a reason that negative positions are twice as big as stroke with (
-2dp
vs1dp
)? Seems to work when they are equal in amount (-1
and1
). -
Tigger almost 8 years@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). -
Denys Kniazhev-Support Ukraine almost 8 yearsInteresting. Do you know if this is a general case, for example if I use
4dp
for stroke width should I use-8dp
for positioning? -
Tigger almost 8 years@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 of4pd
. It simply needed to be a little bigger to get over the float value inaccuracy. -
Asif Mushtaq about 7 yearsWhy android didn't have the easiest solution for such things? as in other language, like HTML, CSS, or something JavaFX, WPF......
-
SMBiggs about 7 yearsPretty simple. You control the size and direction of outlines by the margins of the inner View. Thanks.
-
Kevin D. about 7 yearsThis 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.
-
Vinay Vissh almost 7 yearsUsing "Option 2: Background View (in Relative Layout)" and it is working like a charm. Thanks a lot :)
-
xarlymg89 over 6 years@emmby 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.
-
Dino Tw about 6 yearsSimple and elegant.
-
Vlad about 6 yearsAs for me
solid
is redunt -
DawnYu about 6 yearsI delete this line
<solid android:color="#00FFFFFF" />
, it also works~ -
Big McLargeHuge almost 5 yearsOption 1 sounds good but it creates borders to the left and right as well.
-
Maveňツ almost 4 years@phreakhead better if you add some explanation to this
-
gumuruh about 2 yearsaaah you are my saviour...! :D