Show only left and right borders of a rectangle [duplicate] - android

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?

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.

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>

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.

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

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

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).

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

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.

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.

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"

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 -

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

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.

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>

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;

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.

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>

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

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.

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.

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>

// 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

<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>

<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

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.

Related

Different colors on a line separator in Android

I want to add three colors or more vertically on a line separator in android. It is blue as showing in the following picture but what if I want to divide it into three sections and add different colors in it. I do not want to make three separate views for this. Can I do it in android?
<View
android:background="#00bfff"
android:layout_width = "match_parent"
android:layout_height="5dp"
/>
Yes You can do it by Making one drawable file like this. And give Backgroung this drawable to view.
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="0"
android:centerColor="#5F3D5E"
android:endColor="#8F76B0"
android:startColor="#35293D"
android:type="linear" />
<corners android:radius="0dp" />
</shape>
You could use a layer-list drawable and use that as your View background.
Example:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<solid android:color="#ff0000"/>
</shape>
</item>
<item
android:bottom="5dp">
<shape>
<solid android:color="#00ff00" />
</shape>
</item>
<item
android:bottom="10dp">
<shape>
<solid android:color="#0000ff" />
</shape>
</item>
</layer-list>
Example output:
Edit:
For vertical lines, you do what #convexHull said, just replace bottom with right.
Example:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<solid android:color="#ff0000"/>
</shape>
</item>
<item
android:right="50dp">
<shape>
<solid android:color="#00ff00" />
</shape>
</item>
<item
android:right="100dp">
<shape>
<solid android:color="#0000ff" />
</shape>
</item>
</layer-list>
Example output:
Solution 1
Create 3 view and add one below another
Solution 2
Create one .png background with 3 different color and set background for your view
You need to add a gradient colour to achieve that effect. Just go into drawable directory and add a new .xml resource into it. Then nest the following:
Selector
Item
Shape
Gradient.
Within the gradient tag add startcolor, centercolor, end color, and angle tags. Then set it as your background of the view.. I don't know of any better way to do this but will update when I do
Heres another way if you want more than 3 colors:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="5dp"
android:weightSum="3">
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#color/red"/>
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#color/blue/>
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#color/green"/>
</LinearLayout>
So if you want more colors, just change the weightsum of the linearlayout and add another view.

How to add shadow using a drawable behind solid color shape in xml?

I have a .png image which is a circular shape and is just a shadow. What I have is an ImageButton which has an image for its android:src property. For its background I can have an xml file in drawable file. What I want now is to have the shadow image which is a png to go behind another solid shape -> android:shape="oval".
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/shadowimg" />
<item>
<shape android:shape="oval">
<solid
android:color="#d63a33"/>
<size
android:width="70dp"
android:height="70dp"/>
</shape>
</item>
</layer-list>
As you see in the code I am adding an item with the shadow image with the android:drawable property. However this does not let the shadow show. It simply shows the red circle shape. But I want the shadow image behind the solid red circle shape. From my tiny knowledge of layer-list the top item goes in the back and the one on bottom comes first.
UPDATE: After moving the image shadow to bottom I got the effect however the size of the solid red circle shape is too big and changing the size doesn't change the size.
UPDATED Code:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid
android:color="#d63a33"/>
<size
android:width="5dp"
android:height="5dp"/>
</shape>
</item>
<item android:drawable="#drawable/shadowimg" />
</layer-list>
**** UPDATE 2: ****
I noticed when I remove <item android:drawable="#drawable/shadowimg" /> I can change size of solid circle shape but when I add this it defaults to a bigger size.
This is what happens:
Here's the shadow image if anyone needs:
I think this should be your solution:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="oval" >
<solid android:color="#d63a33" />
<size
android:height="5dp"
android:width="5dp" />
</shape>
</item>
<item>
<bitmap android:src="#drawable/shadowimg" />
</item>
<item>
<shape android:shape="oval" >
<solid android:color="#00000000" />
<size
android:height="5dp"
android:width="5dp" />
</shape>
</item>
</layer-list>
I added another transparent layer with the desired size.
Actually the issue is in the shadow you are using, the shadow itself leaves some padding. so what we can do is, leave some space in the solid color we are filling in the first item by using stroke.
use this code:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="oval" >
<solid android:color="#d63a33" />
<stroke
android:width="7dp"
android:color="#00000000" />
</shape>
</item>
<item android:drawable="#drawable/shadowimg"/>
</layer-list>
and then use with 30dp of height and 30dp of width, like
<TextView
android:id="#+id/titleText"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_centerVertical="true"
android:layout_marginLeft="16dp"
android:background="#drawable/circle_white"
android:fontFamily="sans-serif-thin"
android:gravity="center"
android:text="Hi"
android:textColor="#FF000000"
android:textSize="16sp" />
if you want to increase the height and width of the view, simply increase the width of the stroke too..

Draw radius border to imageview or textview in one corner in Android

I need to draw a border to an imageview or a textview in my app, but I need to draw it only in one corner, like the image.
I do a shape but i get border in all 4 sides:
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:width="1px" android:color="#FF000000" />
<solid android:color="#ffffffff"/>
<padding android:left="1px" android:top="1px"
android:right="0px" android:bottom="0px" />
<corners android:topLeftRadius="8px" />
</shape>
How can I to do make it like in the image?
Thanks, Mattia
Use this code will solve it :
<?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" />
<corners android:topLeftRadius="15dp" />
</shape>
</item>
<item android:left="10dp" android:top="10dp">
<shape android:shape="rectangle">
<solid android:color="#000000" />
<corners android:topLeftRadius="15dp" />
</shape>
</item>
</layer-list>
you have to make adjustment in the ( layout Xml ) also as:
android:layout_width
android:layout_height
android:paddingTop
android:paddingLeft
this is the output :
hope this help.
This is how I achieved. Using inset drawable we can achieve this easily and more customization we can do with less code. Use this twoside_border.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- inset: It can remove border from any other side-->
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetBottom="-15dp"
android:insetRight="-15dp">
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rectangle">
<stroke
android:width="20dp"
android:color="#ED302F" />
<!--<corners
android:topLeftRadius="20dp"
/>-->
<!--<solid android:color="#f50a0a" />-->
</shape>
insetBottom & insetRight -dp values helps to hide the border where we do not need and as a output :
two side border image
to get corner curve remove the commented line in the above code
<corners android:topLeftRadius="20dp"/>
now we can see the curve bend
border with curve image
Use this xml in frame layout like below how I did & adjust the padding or margin according to your need, so that it fit inside the border image which look like a frame.
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingTop="5dp"
android:scaleType="centerCrop"
android:src="#drawable/your_image_file" />
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/twoside_border" />
</FrameLayout>

Open-sided Android stroke?

Is it possible to create an Android shape object with stroke on only certain sides?
Eg I have:
<stroke
android:width="3dip"
android:color="#000000"
android:dashWidth="10dip"
android:dashGap="6dip" />
Which is similar to this CSS:
border: 3px dashed black;
How can I set the stroke on just one side? This is how I would do it in CSS:
border-left: 3px dashed black;
How do you do this in Android XML?
I achieved a good solution with this one:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- This is the line -->
<item android:top="-1dp" android:right="-1dp" android:left="-1dp">
<shape>
<solid android:color="#android:color/transparent" />
<stroke android:width="1dp" android:color="#ffffff" />
</shape>
</item>
</layer-list>
This works well in case you need a transparent background but still an open stroke color (In my case I only needed a bottom line). If you need a background color you can add a solid shape color as in Maragues answer.
EDIT 1
Sometimes, for High Density devices, using low dip values may end in very thin or invisible strokes or distances. This may happen to you also when setting ListView dividers.
The simplest workaround is to use a distance of 1px instead of 1dp. This will make the line always visible at all densities. The best solution would be to create dimension resources for each density, to get the best size for each device.
Edit 2
Fun, but I tried to use this 6 years later and I can't get a good result on Lollipop devices.
Probably the current solution is to use 9-patch. Android should have made an easy solution for this problem after all this time.
I know this question was posted long ago, so the answer will not be used by the person who posted this question, but it may still help others.
<?xml version="1.0" encoding="UTF-8"?>
<!-- inset is used to remove border from top, it can remove border from any other side-->
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetTop="-2dp"
>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:id="#+id/rectangle">
<stroke android:width="1dp" android:color="#b7b7b7" />
<corners android:bottomRightRadius="5dp" android:bottomLeftRadius="5dp"/>
<solid android:color="#454444"/>
</shape>
</inset>
Use the inset tag and give a negative value for the side border you want to remove.
The possible values are:
android:insetTop="-1dp"
android:insetBottom="-1dp"
android:insetLeft="-1dp"
android:insetRight="-1dp"
I solved this by using a list-layer, combining two shapes, one of which with height 1dp placed at the bottom
optionscreen_bottomrectangle.xml:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- This is the line -->
<item>
<shape>
<solid android:color="#535353" />
</shape>
</item>
<!-- This is the main color -->
<item android:bottom="1dp">
<shape>
<solid android:color="#252525" />
</shape>
</item>
</layer-list>
Then, in the layout/main.xml file
<TextView
android:id="#+id/bottom_rectangle"
android:background="#drawable/optionscreen_bottomrectangle"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_below="#id/table_options"
android:layout_above="#id/exit_bar"/>
Which fills the gap between table_options and exit_bar with a background and just before exit_bar prints a 1dp line. This did the trick for me, I hope it helps someone else.
Answer edited to place layers in the correct order. Thx Alex!
Another take on the other responses using padding instead. This little snipplet makes a border on top and bottom.
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- This is the line -->
<item>
<shape>
<padding android:left="0dp" android:top="1dp" android:right="0dp" android:bottom="1dp"/>
<solid android:color="#898989" />
</shape>
</item>
<!-- This is the main color -->
<item>
<shape>
<solid android:color="#ffffff" />
</shape>
</item>
</layer-list>
#Maragues's answer is backwards, as layer-list drawables draw from top to bottom (meaning the last item in the list is drawn on top):
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- This is the line -->
<item>
<shape>
<solid android:color="#535353" />
</shape>
</item>
<!-- This is the main color -->
<item android:bottom="1dp">
<shape>
<solid android:color="#252525" />
</shape>
</item>
</layer-list>
This will effectively fill the shape with the line color, then draw the background color on top of it, leaving the last 1dp clear for the line color to show through.
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle" >
<stroke android:width="2dp"
android:color="#BBBBBB" />
<solid android:color="#android:color/transparent" />
</shape>
</item>
<item android:bottom="2dp" >
<shape android:shape="rectangle" >
<stroke android:width="2dp"
android:color="#color/main_background_color" />
<solid android:color="#android:color/transparent" />
</shape>
</item>
I've used following code.
<?xml version="1.0" encoding="UTF-8"?>
<!-- inset is used to remove border from top, it can remove border from any other side-->
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetTop="-2dp" android:insetLeft="-2dp" android:insetRight="-2dp"
>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:id="#+id/rectangle">
<stroke android:width="1dp" android:color="#color/colorPrimary" />
<solid android:color="#0000"/>
<padding android:left="2dp" android:top="2dp" android:bottom="2dp" android:right="2dp"/>
</shape>
</inset>
Simple and efficient
To have a transparent view and everything that is outside has an overlay of some color, what you can do is build the views that encapsulate the center view without the outside views stepping on the center view.
This way you avoid having a drawable external to the layout and you have more control over the distances of the views without having to perform calculations at runtime.
<androidx.constraintlayout.widget.ConstraintLayout .. >
<View
android:id="#+id/center"
android:layout_width="100dp"
android:layout_height="100dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:background="#color/transparent"/>
<View
android:id="#+id/left_overlay"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#id/center"
app:layout_constraintTop_toBottomOf="#id/top_overlay"
app:layout_constraintBottom_toTopOf="#id/bottom_overlay"
android:background="#color/black"
android:alpha="0.5"
/>
<View
android:id="#+id/right_overlay"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toRightOf="#id/center"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/top_overlay"
app:layout_constraintBottom_toTopOf="#id/bottom_overlay"
android:background="#color/black"
android:alpha="0.5"
/>
<View
android:id="#+id/top_overlay"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/center"
android:background="#color/black"
android:alpha="0.5"
/>
<View
android:id="#+id/bottom_overlay"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#id/center"
android:background="#color/black"
android:alpha="0.5"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
GL

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

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?
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.
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>
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.
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"/>
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
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).
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
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.
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.
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"
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 -
Why not just create a 1dp high view with a background color? Then it can be easily placed where you want.
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.
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>
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;
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.
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>
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" />
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.
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.
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>
// 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
<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>
<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
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.

Categories

Resources