Shree
Shree

Reputation: 1061

Android : How to create a custom textview?

Im trying to implement a textview with each character bounded in a box with a background color.
A sample is such as below
enter image description here
The text will be totally dynamic.
Im thinking of adding a list of TextViews to a LinearLayout in activity class, and customize their background colors and borders.

Is this is the better approach ?
Please suggest a good solution, if there's any.

Upvotes: 2

Views: 2572

Answers (3)

JARP
JARP

Reputation: 1249

You could use Spannable Here is a good tutorial https://blog.stylingandroid.com/introduction-to-spans/

Upvotes: 0

Jschools
Jschools

Reputation: 2758

Using separate TextViews is an expensive approach. If your text has many characters, it will cost a lot of memory and time due to the numerous TextView instances' layout and measure passes. Since this is a very specific component, I would recommend creating a custom View and drawing the contents on the canvas manually.

Upvotes: 0

rainash
rainash

Reputation: 874

here is a simple example, to do this I merely write a view extends TextView.

public class CustomText extends View {

private int borderWidthLeft = dp(4);

private int borderWidthRight = dp(4);

private int borderWidthTop = dp(4);

private int borderWidthBottom = dp(4);

private int boderColor = Color.BLACK;

private int backgroundColor = Color.BLUE;

private int textColor = Color.WHITE;

private int textSize = sp(30);

private Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);

private Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);

private int backgroundRectWidth = dp(35);

private int backgroundRectHeight = dp(35);

private Rect textBgRect = new Rect();

private String defaultText = "A";

public CustomText(Context context) {
    this(context, null);
}

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

private void init(Context context) {
    backgroundPaint.setColor(backgroundColor);
    textPaint.setColor(textColor);
    textPaint.setTextAlign(Align.CENTER);
    textPaint.setTextSize(textSize);
    textPaint.setFakeBoldText(true);
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    drawBackground(canvas);
    drawText(canvas);
}

private void drawBackground(Canvas canvas) {
    canvas.drawColor(boderColor);
    int left =  borderWidthLeft;
    int top =  borderWidthTop;
    int right = borderWidthLeft + backgroundRectWidth;
    int bottom = borderWidthTop + backgroundRectHeight;
    textBgRect.set(left, top, right, bottom);
    canvas.save();
    canvas.clipRect(textBgRect, Op.REPLACE);
    canvas.drawRect(textBgRect, backgroundPaint);
    canvas.restore();
}

private void drawText(Canvas canvas) {
    int bgCenterX = borderWidthLeft + backgroundRectWidth / 2;
    int bgCenterY = borderWidthTop + backgroundRectHeight / 2;
    FontMetrics metric = textPaint.getFontMetrics();
    int textHeight = (int) Math.ceil(metric.descent - metric.ascent);
    int x = bgCenterX;
    int y = (int) (bgCenterY + textHeight / 2 - metric.descent);
    System.out.println(textHeight);
    System.out.println(y);
    System.out.println(bgCenterY);
    canvas.drawText(defaultText, x, y, textPaint);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    setMeasuredDimension(backgroundRectWidth + borderWidthLeft + borderWidthRight, 
            backgroundRectHeight + borderWidthTop + borderWidthBottom);
}

private int dp(int value) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, getResources().getDisplayMetrics());
}

private int sp(int value) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, value, getResources().getDisplayMetrics());
}

}

Upvotes: 3

Related Questions