Skip to main content

Implementing Underlined EditText in Android (BUG Fix)

Free2015-03-16#Android#Solution#记事本#带下划线的EditText#文字压线#光标压线

I previously wrote an example about implementing an underlined EditText and found there were still some issues, so I continue to explore it here.

I previously wrote an example about implementing an underlined EditText and found there were still some issues, so I continue to explore it here. Original link: http://www.cnblogs.com/ayqy/p/3599414.html

0. Another Bug

If you find that the line cannot be drawn, it might be a bug with the line width of the paint parameter in the canvas.drawLine method. In Android 2.3.5, a line width of 0.5 can be drawn normally, but in Android 4.2.2, a line width of 0.5 cannot be drawn. Details are as follows:

// Note the line width. In Android 2.3.5, a line width of 0.5 can be drawn normally, but in Android 4.2.2, a line width of 0.5 cannot be drawn.
lineWidth = 1.0f;// Default width is 1.0

If the line still cannot be drawn, check the starting coordinates. When drawing a line, if the starting point is not within the visible range, the entire line will be invisible. The visible area of a TextView is the rectangular area occupied by the control. Details are as follows:

// When drawing a line, if the starting point is not within the visible range, the entire line will be invisible. The visible area of a TextView is the rectangular area occupied by the control.
canvas.drawLine(padL//startX
		, baseTop + gap * i//startY
		, this.getWidth() - padR//endX
		, baseTop + gap * i//endY
		, mPaint);

1. The Problem

The previous custom EditText could only display text content whose height did not exceed the screen height. Adding more content would cause the following problem:

2. Cause Analysis

Lines are not drawn in the lower part (the part exceeding the screen height), which means not enough horizontal lines are drawn. There must be a problem with the loop control section.

3. How to Solve

1. How can we ensure there is a line below each line of text?

First, we need to get the number of lines of text using EditText.getLineCount(); then draw lines row by row.

2. How to determine the position of the horizontal line?

Y = EditText.getPaddingTop() + EditText.getLineHeight() * index;// Y coordinate = top padding inside the text box + line height * line index (which line)

The above method draws lines from top to bottom. Of course, you can also draw lines from bottom to top, which will not be detailed here.

4. Coding

package com.ayqy.app_test;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.widget.EditText;
public class myEditText extends EditText{
	private int lineColor;// Horizontal line color
	private float lineWidth;// Horizontal line width
	public myEditText(Context context) {
		super(context);
		// Set default color and horizontal line width
		lineColor = Color.BLUE;// Default blue line
		lineWidth = 0.5f;// Default width is 0.5
	}
	public myEditText(Context context,int color,float width) {
		super(context);
		// Set color and horizontal line width
		this.lineColor = color;
		this.lineWidth = width;
	}
	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.onDraw(canvas);
		// Create paint
		Paint mPaint = new Paint();
		mPaint.setStrokeWidth(lineWidth);
		mPaint.setStyle(Paint.Style.FILL);
		mPaint.setColor(lineColor);
		// Get parameters
		int padL = this.getPaddingLeft();// Get left padding inside the box
		int padR = this.getPaddingRight();// Get right padding inside the box
		int padT = this.getPaddingTop();// Get top padding inside the box
		int lines = this.getLineCount();// Get number of lines
		float size = this.getTextSize();// Get font size
		float baseTop = padT + size / 6;// Position of the first line from top to bottom
		/* What needs to be explained here is the value size/6, which was obtained through accidental testing and is approximately half of the line spacing.
		 * Why not use EditText.getLineSpacingExtra(); to get the line spacing?
		 * Because tests found that calling EditText's getLineSpacingExtra method would throw a NoSuchMethod error, the specific reason is unknown.
		 * Tests found that the line spacing value is approximately 1/3 of TextSize, which can be used instead of the getLineSpacingExtra method when line spacing is needed.
		 * */
		float gap = this.getLineHeight();// Get line height
		// Draw lines from top to bottom
		for(int i = 1;i <= lines;i++)
		{
			canvas.drawLine(padL//startX
					, baseTop + gap * i//startY
					, this.getWidth() - padR//endX
					, baseTop + gap * i//endY
					, mPaint);
		}
	}
	public int getLineColor() {
		return lineColor;
	}
	public void setLineColor(int color) {
		this.lineColor = color;
	}
	public float getLineWidth() {
		return lineWidth;
	}
	public void setLineWidth(float width) {
		this.lineWidth = width;
	}
}

P.S. The code comment above mentioned "tests found that calling EditText's getLineSpacingExtra method would throw a NoSuchMethod error". After Googling, it seems no one has encountered this problem. If any friend knows the answer, please leave a message below, thank you.

5. Screenshot of the Effect

The improved code perfectly solves the problems of "text overlapping the line" and "cursor overlapping the line". The core is that line spacing = TextSize/3. The existence of line spacing affects the view effect, adding half the line spacing is fine.

6. Summary

Discovering bugs and fixing them promptly—this is the joy of programming.

Comments

No comments yet. Be the first to share your thoughts.

Leave a comment