How to put a border around an Android TextView?
Asked Answered
E

23

823

Is it possible to draw a border around an Android TextView?

Emelia answered 16/8, 2010 at 18:50 Comment(3)
I posted one dirty solution here: https://mcmap.net/q/55082/-how-can-i-create-a-table-with-borders-in-androidSalta
Check out my one-liner answer below.Oxcart
With the MaterialComponents just use a MaterialShapeDrawable : #18782402Undergo
S
1409

You can set a shape drawable (a rectangle) as background for the view.

<TextView android:text="Some text" android:background="@drawable/back"/>

And rectangle drawable back.xml (put into res/drawable folder):

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
   <solid android:color="@android:color/white" />
   <stroke android:width="1dip" android:color="#4fa5d5"/>
</shape>

You can use @android:color/transparent for the solid color to have a transparent background. You can also use padding to separate the text from the border. for more information see: http://developer.android.com/guide/topics/resources/drawable-resource.html

Saenz answered 16/8, 2010 at 18:56 Comment(11)
What if I just want the top border?Questioning
@whyoz His method adds unneeded complexity to view hierarchy. You will need two additional views (A layout container and the border view) to use his method. Thus if you have many views you need to add border to, your view tree will grow unmanagable.Saenz
@whyoz yet this method might be applied via styles an themes, while YongGu's method can't be used this way.Saenz
Instead of a separate file in drawable, can we just add the code to the style.xml file?Sonnie
For top border only, see this question.Heidiheidie
You can use this tool http://shapes.softartstudio.com to generate drawables.Fortify
This solution will kill ripple touch feedback!Bacchae
Maybe it's only possible since recent versions, but I have a one-liner answer.Oxcart
I can't belive that now days it still must be so difficult to do such banal things on android layoutsObsolesce
@KonstantinBurov - I need border for all the labels but bg color needed different for each labels. How can I achieve that ?Hire
Is there a reason why rectangle is used to draw circle instead of ring?Pergrim
E
226

Let me summarize a few different (non-programmatic) methods.

Using a shape drawable

Save the following as an XML file in your drawable folder (for example, my_border.xml):

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

    <!-- View background color -->
    <solid
        android:color="@color/background_color" >
    </solid>

    <!-- View border color and width -->
    <stroke
        android:width="1dp"
        android:color="@color/border_color" >
    </stroke>

    <!-- The radius makes the corners rounded -->
    <corners
        android:radius="2dp"   >
    </corners>

</shape>

Then just set it as the background to your TextView:

<TextView
    android:id="@+id/textview1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/my_border" />

More help:

Using a 9-patch

A 9-patch is a stretchable background image. If you make an image with a border then it will give your TextView a border. All you need to do is make the image and then set it to the background in your TextView.

<TextView
    android:id="@+id/textview1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/my_ninepatch_image" />

Here are some links that will show how to make a 9-patch image:

What if I just want the top border?

Using a layer-list

You can use a layer list to stack two rectangles on top of each other. By making the second rectangle just a little smaller than the first rectangle, you can make a border effect. The first (lower) rectangle is the border color and the second rectangle is the background color.

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

    <!-- Lower rectangle (border color) -->
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/border_color" />
        </shape>
    </item>

    <!-- Upper rectangle (background color) -->
    <item android:top="2dp">
        <shape android:shape="rectangle">
            <solid android:color="@color/background_color" />
        </shape>
    </item>
</layer-list>

Setting android:top="2dp" offsets the top (makes it smaller) by 2dp. This allows the first (lower) rectangle to show through, giving a border effect. You can apply this to the TextView background the same way that the shape drawable was done above.

Here are some more links about layer lists:

Using a 9-patch

You can just make a 9-patch image with a single border. Everything else is the same as discussed above.

Using a View

This is kind of a trick but it works well if you need to add a seperator between two views or a border to a single TextView.

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textview1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <!-- This adds a border between the TextViews -->
    <View
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="@android:color/black" />

    <TextView
        android:id="@+id/textview2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

Here are some more links:

Evitaevitable answered 4/4, 2015 at 10:2 Comment(3)
Jeez man, a border: 1px solid #999; is not supposed to be this complicated.Fawcette
What if I want border of textview, which is having shadow and ripple effect too?Prog
@AkashDubey, Sorry, I haven't done that before. I suggest you try each one separately and then combine them. If you get stuck, ask a new question on Stack Overflow.Evitaevitable
O
52

The simple way is to add a view for your TextView. Example for the bottom border line:

<LinearLayout android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent">
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="10dp"
        android:text="@string/title"
        android:id="@+id/title_label"
        android:gravity="center_vertical"/>
    <View
        android:layout_width="fill_parent"
        android:layout_height="0.2dp"
        android:id="@+id/separator"
        android:visibility="visible"
        android:background="@android:color/darker_gray"/>

</LinearLayout>

For the other direction borders, please adjust the location of the separator view.

Olga answered 22/11, 2012 at 1:59 Comment(3)
For my experience this solution, on old devices, has a quiet visible impact on the app performance.Cromorne
This is a horrible solution from a view inflation perspective. You create 3 new view elements and add one more level in view hierarchy depthThisbe
Worst solution because of the view inflation perspective as philipp said. Do you know that textView have specific xml tag to just do that: define a picture to be draw left/right/top/bottom aroud your TextView, and they are known as android:drawable****Contrariwise
F
34

I have solved this issue by extending the textview and drawing a border manually. I even added so you can select if a border is dotted or dashed.

public class BorderedTextView extends TextView {
        private Paint paint = new Paint();
        public static final int BORDER_TOP = 0x00000001;
        public static final int BORDER_RIGHT = 0x00000002;
        public static final int BORDER_BOTTOM = 0x00000004;
        public static final int BORDER_LEFT = 0x00000008;

        private Border[] borders;

        public BorderedTextView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init();
        }

        public BorderedTextView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }

        public BorderedTextView(Context context) {
            super(context);
            init();
        }
        private void init(){
            paint.setStyle(Paint.Style.STROKE);
            paint.setColor(Color.BLACK);
            paint.setStrokeWidth(4);        
        }
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            if(borders == null) return;

            for(Border border : borders){
                paint.setColor(border.getColor());
                paint.setStrokeWidth(border.getWidth());

                if(border.getStyle() == BORDER_TOP){
                    canvas.drawLine(0, 0, getWidth(), 0, paint);                
                } else
                if(border.getStyle() == BORDER_RIGHT){
                    canvas.drawLine(getWidth(), 0, getWidth(), getHeight(), paint);
                } else
                if(border.getStyle() == BORDER_BOTTOM){
                    canvas.drawLine(0, getHeight(), getWidth(), getHeight(), paint);
                } else
                if(border.getStyle() == BORDER_LEFT){
                    canvas.drawLine(0, 0, 0, getHeight(), paint);
                }
            }
        }

        public Border[] getBorders() {
            return borders;
        }

        public void setBorders(Border[] borders) {
            this.borders = borders;
        }
}

And the border class:

public class Border {
    private int orientation;
    private int width;
    private int color = Color.BLACK;
    private int style;
    public int getWidth() {
        return width;
    }
    public void setWidth(int width) {
        this.width = width;
    }
    public int getColor() {
        return color;
    }
    public void setColor(int color) {
        this.color = color;
    }
    public int getStyle() {
        return style;
    }
    public void setStyle(int style) {
        this.style = style;
    }
    public int getOrientation() {
        return orientation;
    }
    public void setOrientation(int orientation) {
        this.orientation = orientation;
    }
    public Border(int Style) {
        this.style = Style;
    }
}

Hope this helps someone :)

Finedrawn answered 17/7, 2013 at 20:25 Comment(2)
How to initialize borders?Lophobranch
It can't work correctly, as the code shows it draws the borders at the half size of the defined valueKirima
O
31

Simplest solution I've found (and which actually works):

<TextView
    ...
    android:background="@android:drawable/editbox_background" />
Oxcart answered 4/4, 2018 at 20:47 Comment(3)
Is it possible to apply this to all textviews from one place?Agrestic
Nice for a quickie. But depending on the version of the running device, this can have very unusual effects. This is because Google keeps changing how EditTexts look (you gotta keep in fashion!)Huebner
Not sure if this will support dark modeCano
S
16

You can set the border by two methods. One is by drawable and the second is programmatic.

Using Drawable

<shape>
    <solid android:color="@color/txt_white"/>
    <stroke android:width="1dip" android:color="@color/border_gray"/>
    <corners android:bottomLeftRadius="10dp"
             android:bottomRightRadius="0dp"
             android:topLeftRadius="10dp"
             android:topRightRadius="0dp"/>
    <padding android:bottom="0dip"
             android:left="0dip"
             android:right="0dip"
             android:top="0dip"/>
</shape>

Programmatic


public static GradientDrawable backgroundWithoutBorder(int color) {

    GradientDrawable gdDefault = new GradientDrawable();
    gdDefault.setColor(color);
    gdDefault.setCornerRadii(new float[] { radius, radius, 0, 0, 0, 0,
                                           radius, radius });
    return gdDefault;
}
Spermiogenesis answered 11/9, 2015 at 19:19 Comment(1)
How would that shape XML relate to the textView?Fizzy
U
16

With the Material Components Library you can use the MaterialShapeDrawable.

    <TextView
        android:id="@+id/textview"
        .../>

Then you can programmatically apply a MaterialShapeDrawable:

    TextView textView = findViewById(R.id.textview);
    MaterialShapeDrawable shapeDrawable = new MaterialShapeDrawable();
    shapeDrawable.setFillColor(ContextCompat.getColorStateList(this,android.R.color.transparent));
    shapeDrawable.setStroke(1.0f, ContextCompat.getColor(this,R.color....));
    ViewCompat.setBackground(textView,shapeDrawable);

enter image description here

Undergo answered 3/7, 2020 at 17:44 Comment(0)
M
15

I was just looking at a similar answer-- it's able to be done with a Stroke and the following override:

@Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {

Paint strokePaint = new Paint();
strokePaint.setARGB(255, 0, 0, 0);
strokePaint.setTextAlign(Paint.Align.CENTER);
strokePaint.setTextSize(16);
strokePaint.setTypeface(Typeface.DEFAULT_BOLD);
strokePaint.setStyle(Paint.Style.STROKE);
strokePaint.setStrokeWidth(2);

Paint textPaint = new Paint();
textPaint.setARGB(255, 255, 255, 255);
textPaint.setTextAlign(Paint.Align.CENTER);
textPaint.setTextSize(16);
textPaint.setTypeface(Typeface.DEFAULT_BOLD);

canvas.drawText("Some Text", 100, 100, strokePaint);
canvas.drawText("Some Text", 100, 100, textPaint);

super.draw(canvas, mapView, shadow); 
}
Minsk answered 16/8, 2010 at 18:56 Comment(2)
Great! My only concern is that the stroke is ugly at the corners when I use drawRoundRect, both on phone and in the emulator.Gotten
@Gotten Maybe Paint StrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG); will solve "ugly at the corners" issueIchthyoid
T
12

You can add something like this in your code:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle" >
    <solid android:color="#ffffff" />
    <stroke android:width="1dip" android:color="#4fa5d5"/>
</shape>
Thamos answered 13/5, 2014 at 4:39 Comment(2)
Why is stroke necessary?Overweening
@IgorGanapolsky, stroke create the actual border?Jola
K
12

You can set a shape drawable (a rectangle with corners) as background for the view.

<TextView android:background="@drawable/frame"/>

And rectangle drawable frame.xml (put into res/drawable folder):

<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >
    <solid android:color="@android:color/white" />
    <stroke android:width="1dip"
     android:color="#3d4caf"/>
    <corners android:radius="50dp"/>
</shape>
Kadner answered 29/7, 2021 at 19:50 Comment(0)
L
11

I found a better way to put a border around a TextView.

Use a nine-patch image for the background. It's pretty simple, the SDK comes with a tool to make the 9-patch image, and it involves absolutely no coding.

The link is http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch.

Lobel answered 25/2, 2012 at 4:28 Comment(7)
Useful, yes, but how is this better?Humectant
Using a shape as the accepted answer says is better than a 9-patch, an XML file is more flexible than a graphic assetWoollen
Sure, if you want to be limited to creating the graphics you want programmatically, then it is more flexible.Lobel
The shape-approach is useless.Perhaps I am the only one experiencing,that the tag "solid" always gets processed,no matter if set to transparent or not.And If I want to create a BORDER,I mean, a BORDER and not a rectangle with coloured inner and otherwise coloured borderlines. And it is NEVER transparent solid. It always disturbes the colour. Also,an class,which inherits from another,should also have all features, because it is inherited. really cannot understand,why elementary OO-design-guidelines are broken by android. For example, I inherited from button. All features gone. Why ?Famine
Also using 9patch is visibly slower because its much heavier to load.Wernher
@Jeremie Visibly slower? How do you observe it?Overweening
“Limited” and “programmatically” don’t belong in the same sentence.Lifesaving
I
10

Check the link below to make rounded corners http://androidcookbook.com/Recipe.seam?recipeId=2318

The drawable folder, under res, in an Android project is not restricted to bitmaps (PNG or JPG files), but it can also hold shapes defined in XML files.

These shapes can then be reused in the project. A shape can be used to put a border around a layout. This example shows a rectangular border with curved corners. A new file called customborder.xml is created in the drawable folder (in Eclipse use the File menu and select New then File, with the drawable folder selected type in the file name and click Finish).

The XML defining the border shape is entered:

<?xml version="1.0" encoding="UTF-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
    <corners android:radius="20dp"/>
    <padding android:left="10dp" android:right="10dp" android:top="10dp" android:bottom="10dp"/>
    <solid android:color="#CCCCCC"/>
</shape>

The attribute android:shape is set to rectangle (shape files also support oval, line, and ring). Rectangle is the default value, so this attribute could be left out if it is a rectangle being defined. See the Android documentation on shapes at http://developer.android.com/guide/topics/resources/drawable-resource.html#Shape for detailed information on a shape file.

The element corners sets the rectangle corners to be rounded. It is possible to set a different radius on each corner (see the Android reference).

The padding attributes are used to move the contents of the View to which the shape is applied, to prevent the contents overlapping the border.

The border color here is set to a light gray (CCCCCC hexadecimal RGB value).

Shapes also support gradients, but that is not being used here. Again, see the Android resources to see how a gradient is defined. The shape is applied to the laypout using android:background="@drawable/customborder".

Within the layout other views can be added as normal. In this example, a single TextView has been added, and the text is white (FFFFFF hexadecimal RGB). The background is set to blue, plus some transparency to reduce the brightness (A00000FF hexadecimal alpha RGB value). Finally the layout is offset from the screen edge by placing it into another layout with a small amount of padding. The full layout file is thus:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:padding="5dp">
    <LinearLayout android:orientation="vertical"
                  android:layout_width="fill_parent"
                  android:layout_height="fill_parent"
                  android:background="@drawable/customborder">
        <TextView android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:text="Text View"
                android:textSize="20dp"
                android:textColor="#FFFFFF"
                android:gravity="center_horizontal"
                android:background="#A00000FF" />
    </LinearLayout>
</LinearLayout>
Improvise answered 6/4, 2014 at 18:13 Comment(1)
Link only answers are highly discouraged, as the links tend to break at some point in the future. Pull relevant portions of your link into this answer so that the information remains available, even if the link does not.Mathes
K
10

I have a way to do it very simply, and I'd like to share it.

When I want to square mi TextViews, I just put them in a LinearLayout. I set the background color of my LinearLayout, and I add a margin to my TextView. The result is exactly as if you square the TextView.

Kellby answered 14/8, 2015 at 18:13 Comment(0)
S
10

You can create custom background for your text view. Steps

  1. Go to your project.
  2. Go to resources and right click to drawable.
  3. Click on New -> Drawable Resource File
  4. Give name to you file
  5. Paste following code in the file
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <stroke
        android:width="1dp"
        android:color="@color/colorBlack" />
    <padding
        android:bottom="1dp"
        android:left="1dp"
        android:right="1dp"
        android:top="1dp" />
    <corners android:radius="6dp" />
    <solid android:color="#ffffffff" />
</shape>
  1. For your text view where you want to use it as backgroud,

    android:background="@drawable/your_fileName"

Swenson answered 9/9, 2019 at 11:49 Comment(0)
B
2

Changing Konstantin Burov answer because not work in my case:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@android:color/white" />
            <stroke android:width="2dip" android:color="#4fa5d5"/>
            <corners android:radius="7dp"/>
        </shape>
    </item>
</selector>

compileSdkVersion 26 (Android 8.0), minSdkVersion 21 (Android 5.0), targetSdkVersion 26, implementation 'com.android.support:appcompat-v7:26.1.0', gradle:4.1

Burstone answered 15/5, 2018 at 22:5 Comment(0)
S
1

Here is my 'simple' helper class which returns an ImageView with the border. Just drop this in your utils folder, and call it like this:

ImageView selectionBorder = BorderDrawer.generateBorderImageView(context, borderWidth, borderHeight, thickness, Color.Blue);

Here is the code.

/**
 * Because creating a border is Rocket Science in Android.
 */
public class BorderDrawer
{
    public static ImageView generateBorderImageView(Context context, int borderWidth, int borderHeight, int borderThickness, int color)
    {
        ImageView mask = new ImageView(context);

        // Create the square to serve as the mask
        Bitmap squareMask = Bitmap.createBitmap(borderWidth - (borderThickness*2), borderHeight - (borderThickness*2), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(squareMask);

        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(color);
        canvas.drawRect(0.0f, 0.0f, (float)borderWidth, (float)borderHeight, paint);

        // Create the darkness bitmap
        Bitmap solidColor = Bitmap.createBitmap(borderWidth, borderHeight, Bitmap.Config.ARGB_8888);
        canvas = new Canvas(solidColor);

        paint.setStyle(Paint.Style.FILL);
        paint.setColor(color);
        canvas.drawRect(0.0f, 0.0f, borderWidth, borderHeight, paint);

        // Create the masked version of the darknessView
        Bitmap borderBitmap = Bitmap.createBitmap(borderWidth, borderHeight, Bitmap.Config.ARGB_8888);
        canvas = new Canvas(borderBitmap);

        Paint clearPaint = new Paint();
        clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

        canvas.drawBitmap(solidColor, 0, 0, null);
        canvas.drawBitmap(squareMask, borderThickness, borderThickness, clearPaint);

        clearPaint.setXfermode(null);

        ImageView borderView = new ImageView(context);
        borderView.setImageBitmap(borderBitmap);

        return borderView;
    }
}
Shrift answered 18/8, 2015 at 18:26 Comment(2)
How do I use selectionBorder?Jola
@TashPemhiwa Button.setBackgroundDrawable();Bernstein
T
1

There are a lot of ways to add a border to a textView. The simplest one is by creating a custom drawable and setting it as android:background="@drawable/textview_bg" for your textView.

The textview_bg.xml will go under Drawables and can be something like this. You can have a solid or a gradient background (or nothing if not required), corners to add a corner radius and stroke to add border.

textview_bg.xml

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

        <corners
            android:radius="@dimen/dp_10"/>

        <gradient
            android:angle="225"
            android:endColor="#FFFFFF"
            android:startColor="#E0E0E0" />

        <stroke
            android:width="2dp"
            android:color="#000000"/>

    </shape>
Teratoid answered 12/8, 2019 at 9:0 Comment(0)
B
0

This may help you.

<RelativeLayout
    android:id="@+id/textbox"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:background="@android:color/darker_gray" >

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:layout_margin="3dp"
        android:background="@android:color/white"
        android:gravity="center"
        android:text="@string/app_name"
        android:textSize="20dp" />

</RelativeLayout
Biscuit answered 21/6, 2014 at 18:17 Comment(0)
S
0

Create a border view with the background color as the color of the border and size of your text view. set border view padding as the width of the border. Set text view background color as the color you want for the text view. Now add your text view inside the border view.

Steeple answered 10/1, 2018 at 9:25 Comment(0)
A
0

Try this:

<shape>
    <solid android:color="@color/txt_white"/>
    <stroke android:width="1dip" android:color="@color/border_black"/>
</shape>
Agulhas answered 16/2, 2019 at 5:11 Comment(0)
F
0
  <View
    android:layout_width="match_parent"
    android:layout_height="2dp"
    android:background="@android:color/black" />

this code enough you can place wherever you want

Flotilla answered 14/1, 2020 at 7:16 Comment(0)
N
0

setBackground on your xml textview,

add rounded_textview.xml file into your drawable directory.

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
   <solid android:color="@android:color/white" />
   <stroke android:width="2dip" android:color="#4f5g52"/>
</shape>

set drawable file in textView background.

Nally answered 10/2, 2020 at 9:9 Comment(0)
L
-2

Actually, it is very simple. If you want a simple black rectangle behind the Textview, just add android:background="@android:color/black" within the TextView tags. Like this:

<TextView
    android:textSize="15pt" android:textColor="#ffa7ff04"
    android:layout_alignBottom="@+id/webView1"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"
    android:background="@android:color/black"/>
Lindyline answered 14/7, 2014 at 13:39 Comment(1)
he ask for border not full background.Giavani

© 2022 - 2024 — McMap. All rights reserved.