跳到主要內容
黯羽輕揚每天積累一點點

Android 實作帶底線的 EditText(BUG 修正)

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

之前寫了一個關於實作 EditText 顯示底線的例子,發現仍然存在一些問題,在此繼續探索

之前寫了一個關於實作 EditText 顯示底線的例子,發現仍然存在一些問題,在此繼續探索,原文連結:http://www.cnblogs.com/ayqy/p/3599414.html

零. 另一個 bug

如果發現畫不出線,那麼可能是 canvas.drawLine 方法最後一個參數 paint 的線寬的 bug,Android 2.3.5 中線寬為 0.5 可以正常畫線,Android 4.2.2 中線寬為 0.5 無法畫線,具體如下:

//注意線寬,Android 2.3.5 中線寬為 0.5 可以正常畫線,Android 4.2.2 中線寬為 0.5 無法畫線
lineWidth = 1.0f;//預設寬度為 1.0

如果還是畫不出線,則檢查起點座標,畫線時如果起點不在可見範圍內則整條線不可見,TextView 的可見區域是控制項佔據的矩形區域,具體如下:

//畫線時如果起點不在可見範圍內則整條線不可見,TextView 的可見區域是控制項佔據的矩形區域
canvas.drawLine(padL//startX
		, baseTop + gap * i//startY
		, this.getWidth() - padR//endX
		, baseTop + gap * i//endY
		, mPaint);

一. 問題

之前的自定義 EditText 只能顯示高度不超過螢幕高度的文本內容,繼續增加內容會出現如下問題:

二. 原因分析

下部(超出螢幕高度的部分)沒有繼續畫線,也就是說橫線沒有畫夠,那麼一定是迴圈控制部分出了問題。

三. 如何解決

1. 怎麼才能做到每行文字下方都有一條線?

那麼首先需要獲取文本的行數,用 EditText.getLineCount(); 再按行畫線即可

2. 怎麼確定橫線的位置?

Y = EditText.getPaddingTop() + EditText.getLineHeight() * index;//Y 座標 = 文本框內上部留白 + 行高 * 行索引(第幾行)

上面的方法是從上往下畫線,當然也可以從下往上畫線,在此不展開敘述

四. 編碼

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;//橫線顏色
	private float lineWidth;//橫線寬度
	public myEditText(Context context) {
		super(context);
		//設置預設顏色和橫線寬度
		lineColor = Color.BLUE;//預設藍色線
		lineWidth = 0.5f;//預設寬度為 0.5
	}
	public myEditText(Context context,int color,float width) {
		super(context);
		//設置顏色和橫線寬度
		this.lineColor = color;
		this.lineWidth = width;
	}
	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.onDraw(canvas);
		//建立畫筆
		Paint mPaint = new Paint();
		mPaint.setStrokeWidth(lineWidth);
		mPaint.setStyle(Paint.Style.FILL);
		mPaint.setColor(lineColor);
		//獲取參數
		int padL = this.getPaddingLeft();//獲取框內左邊留白
		int padR = this.getPaddingRight();//獲取框內右邊留白
		int padT = this.getPaddingTop();//獲取框內頂部留白
		int lines = this.getLineCount();//獲取行數
		float size = this.getTextSize();//獲取字體大小
		float baseTop = padT + size / 6;//從上向下第一條線的位置
		/*這裡需要說明的是 size/6 這個值,是偶然測試得到的,近似於行距的一半
		 *為什麼不用 EditText.getLineSpacingExtra(); 來獲取行距?
		 *因為測試發現若呼叫 EditText 的 getLineSpacingExtra 方法會報 NoSuchMethod 錯誤,具體原因不明
		 *測試發現行距的值近似於 TextSize 的 1/3,在需要用到行距的時候可以用這個值來代替 getLineSpacingExtra 方法
		 * */
		float gap = this.getLineHeight();//獲取行高
		//從上向下劃線
		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. 上方的程式碼註釋提到了「測試發現若呼叫 EditText 的 getLineSpacingExtra 方法會報 NoSuchMethod 錯誤」,Google 之後發現好像沒人遇到過這個問題,如有朋友知道答案請在下方留言,謝謝

五. 效果截圖

改進之後的程式碼完美解決了「文字壓線」和「游標壓線」的問題,核心就是行距=TextSize/3,行距的存在影響了視圖效果,加上半行距就好

六. 總結

發現 Bug 及時修改,programming 的樂趣就在這裡了

評論

暫無評論,快來發表你的看法吧

提交評論