In android application development, in some situations you will need to add or draw a border around android textview so knowing how to add or draw a border around android textview can make a difference.
Just like most things in programming, one single task can be achieved in different ways.
Android textview border is no exception. A simple google search on this topic will reveal different examples on how to achieve it.
Majority of these solutions create a shape drawable and set it as the background resource of a textview.
Shape drawable will indefinitely do the job in most scenarios but what if we want to change the thickness or color of the border at run-time then using a drawable background resource will not work.
Welcome to another solution. We can also solve the same problem by creating a custom textview with a border. This border is achieved by overriding the Textview class onDraw() method.
Depending on what you planned to accomplish, it is possible to expose methods that can be used to change the border width or color at run-time.
We will look into some of these options with a simple code example. You are free to choose whatever options that suits your project requirement.
APP DEMO SCREENSHOT
1. CREATE A NEW ANDROID PROJECT
- Open Android Studio
- Go to file menu
- Select new
- Enter project name
- Enter activity name
- Keep other default settings
- Click on finish button to create a new android project
2. OPEN DEFAULT ACTIVITY_MAIN.XML FILE
We are going to add a TextView in our layout file. Drag and drop a TextView widget or you can as well write it in code.
At this point you only see the text content of the Textview. In order to add a border to the TextView, we are going to create a shape drawable.
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text Border "
android:textColor="@color/colorPrimaryDark"
android:textSize="20sp"
android:padding="30dp"
android:layout_marginBottom="24dp"
android:background="@drawable/border"
android:layout_gravity="center"/>
You will notice a red mark that shows our layout file has an error. This is because android studio could not found the value of the TextView background property we declare.
Next, we need to create the missing border.xml file.
3. CREATE A SHAPE DRAWABLE
Go to res folder > drawable folder and right click. In the open file dialog, enter the name of your resource file. I used border.xml but free feel to choose a name of your choice.
Open the created file and add the code below to it
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<solid android:color="#ffffff" />
<stroke android:width="2dp" android:color="#4fa5d5"/>
</shape>
The code above is self explanatory. Feel to customize it to suit your project requirements.
If everything works for you, you will see a border around the TextView
4. ADD TEXT BORDER WITH SHAPE DRAWABLE
There are situations we might need to change the thickness, width or color of a TextView border at runtime.
We can achieve this by create a custom TextView. If you have not created a custom view in android before I will suggest you reach my post on how to create Android Custom Calendar View with Events
To create a custom TextView we will create a new Java file.
5. CREATE A NEW JAVA FILE
Go to your project package folder and right click, select New > Java class. Add the new of the class. I naxtBorderView.
Open the java file and let the class inherits from the android TextView widget.
I did two experiments. The first one is to use Android Paint class‘ getTextBounds() method to get the rectangular coordinates of the text.
In order to get the perfect position of the text, the padding values was factored in.
The second border is using the canvas coordinates to draw a border around the text since the text content leaves in the canvas.
Decide which option is best for your scenario.
Add the code below to TextBorderView.
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import com.inducesmile.textborder.R;
public class TextBorderView extends android.support.v7.widget.AppCompatTextView {
private static final String TAG = TextBorderView.class.getSimpleName();
private Context context;
private Rect textBoundingRect;
private String userText;
private int thickness = 5;
private Paint rectPaint;
private float initialXPosition;
private float initialYPosition;
private float finalXPosition;
private float finalYPosition;
private int rectLeft;
private int rectRight;
private int rectTop;
private int rectBottom;
public TextBorderView(Context context) {
super(context);
initCustomView(context);
}
public TextBorderView(Context context, AttributeSet attrs) {
super(context, attrs);
initCustomView(context);
}
public TextBorderView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initCustomView(context);
}
private void initCustomView(Context context) {
this.context = context;
textBoundingRect = new Rect();
rectPaint = new Paint();
rectPaint.setAntiAlias(true);
rectPaint.setStrokeWidth(thickness);
rectPaint.setStyle(Paint.Style.STROKE);
rectPaint.setTypeface(Typeface.DEFAULT);
rectPaint.setTextSize(20);
rectPaint.setColor(getResources().getColor(R.color.colorAccent));
getRectBoundingSize();
}
private void getRectBoundingSize() {
rectPaint.getTextBounds(getText().toString(), 0, getText().toString().length(), textBoundingRect);
int pLeft = getPaddingLeft();
int pRight = getPaddingRight();
int pTop = getPaddingTop();
int pBottom = getPaddingBottom();
rectLeft = (int)convertDpToPixel(textBoundingRect.left, context) + pLeft;
rectRight = (int)convertDpToPixel(textBoundingRect.right, context) + pRight;
rectTop = getTop() + pTop + thickness;
rectBottom = (int)(convertDpToPixel(textBoundingRect.bottom, context) + pBottom + getTextSize()) + thickness;
}
private boolean viewHasText() {
if (getText().toString().equals("")) {
return false;
}
return true;
}
private void drawRectangleTextBorder(Canvas canvas, Paint paint) {
Rect rectToDraw = new Rect(rectLeft, rectTop, rectRight, rectBottom);
canvas.drawRect(rectToDraw, paint);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(0, 0, getWidth(), getHeight(), rectPaint);
if (viewHasText()) {
drawRectangleTextBorder(canvas, rectPaint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int touchAction = event.getAction();
switch (touchAction){
case MotionEvent.ACTION_DOWN:
actionToPerformOnDown(event);
return true;
case MotionEvent.ACTION_UP:
initialXPosition = finalXPosition;
initialYPosition = finalYPosition;
return true;
case MotionEvent.ACTION_MOVE:
finalXPosition = event.getX();
int changeInXPosition = (int)(finalXPosition - initialXPosition);
finalYPosition = event.getY();
int changeInYPosition = (int)(finalYPosition - initialYPosition);
moveTextHorizontally(changeInXPosition, changeInYPosition);
return true;
}
return false;
}
private void actionToPerformOnDown(MotionEvent event){
initialXPosition = event.getX();
initialYPosition = event.getY();
Log.d(TAG, "Action down has been called");
}
private void moveTextHorizontally(int left, int top){
rectLeft = rectLeft + left;
rectRight = rectLeft + 300;
rectTop = rectTop + top;
rectBottom = rectTop + 40;
this.setX(rectLeft);
this.setY(rectTop);
}
public void setUserText(String userText) {
this.userText = userText;
invalidate();
}
public float convertDpToPixel(float dp, Context context){
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
return dp * ((float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}
}
6. ADD THE CUSTOM TEXTBORDERVIEW IN XML LAYOUT FILE
Open our activity layout file and add the code below.
<com.inducesmile.textborder.custom.TextBorderView
android:id="@+id/text_in_center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textSize="20sp"
android:padding="30dp"
android:gravity="center"
android:textColor="@color/colorPrimaryDark"
android:text="Custom Textview With Border"/>
We have come to the end of this tutorial. If everything work for you, you will get a similar screen like the demo screenshot above.
Free feel to download the source code from our Github account.
If you have questions or suggestions kindly use the comment box below.