付出終有回報,找準方向,努力向前
一、簡介
本文章主要介紹三種方式實現Edittext下方顯示下滑線,各有利弊,可以根據情景自行選擇,其中有關字體顯示的基準線、行高相關的知識。此篇主要介紹正常模式下代碼如何去寫,這裏還有一篇是兼容行距(設置倍數或者具體數值)。
二、可收穫
如何實現Edittext顯示下劃線
根據情況如何選擇實現方式
字體的行高、基準線是什麼
三、如何實現
1)最簡單的方式
- 基本原理:Edittext可以直接獲取它繪製時的Paint,並設置下劃線屬性即可。
- 基本操作:代碼如下
EditText editText= (EditText) findViewById(R.id.test_et);
editText.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG);//設置下滑線屬性
- 結論:該方法實現簡單,兼容性強,兼容各種字體邊距等情況,但是隻能實現輸入多少行顯示多少行,不能自定義顯示行數。
2)自定義View的形式
- 基本原理:通過重寫onDraw方法,自己測算出線的位置,自己繪製下滑線。
- 基本操作:
//獲取參數
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;//神祕數字
float gap = this.getLineHeight();//行距
mPath.reset();
//從上向下劃線
for (int i = 1; i <= Math.max(lines, maxNoteLines); i++) {
mPath.moveTo(padL, baseTop + gap * i);
mPath.lineTo(this.getWidth() - padR, baseTop + gap * i);
}
canvas.drawPath(mPath, mPaint);
- 原理解析:其中
getLineCount()
是獲取當前的行數,getTextSize()
是獲取字體的大小,核心計算就是計算線的y座標,baseTop + gap * i
,這個是此處的計算方法,而正常情況下 ,padT+gap*i
應該就是線的位置,但是事實是,線總在字上,所以翻看了getLineHeight()
,它是計算行高的,但是官方文檔說會比正常的行高或低或高,但是我後面測試了一下,繪製的文字確實是按照此高度劃分行的,也就是每行的行距就是這個值。 - 爲了彌補高度的不足,
padT+size/6
正好滿足了顯示,且兼容各種字體和大小。一般情況下都會對這個數據size/6
比較疑惑,這個值是恰好測算出來的,並沒什麼依據。這個研究了許久也沒啥進展,然後以此演變出有些許理論依據的第二版本,如果此處有什麼高見可以下方留言,謝謝。 - 結論: 此方法兼容性也可以,也兼容顯示多行線,採用的path,可以設置爲虛線、實線。
3)有理有據的自定義View的形式
- 基本原理:通過重寫onDraw方法,自己測算出線的位置(測算方法不同),自己繪製下滑線。
- 基本操作:
//獲取參數
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;//神祕數字
float gap = this.getLineHeight();//行距
mPath.reset();
//從上向下劃線
for (int i = 0; i <= Math.max(lines, maxNoteLines); i++) { mPath.moveTo(padL,getBaseline()+getPaint().getFontMetrics().descent+gap*i);
mPath.lineTo(this.getWidth() -padR,baseLineY+gap*i+getPaint().getFontMetrics().descent);
}
canvas.drawPath(mPath, mPaint);
原理解析:核心代碼
getBaseline()+getPaint().getFontMetrics().descent+gap*i
,此處理解需要一定的基礎,看下圖:
我們如果想繪製線的話,首先需要知道第一個線的位置,然後剩餘的線間隔是gap,我們從途中可以知道,線的位置=baseLine+descent,所以公式:getBaseline()+getPaint().getFontMetrics().descent+gap*i
- 結論: 此方法兼容性也可以,也兼容顯示多行線,採用的path,可以設置爲虛線、實線。
四、結論
這篇文章寫的也算比較倉促,有些地方感覺自己也想的還不夠透徹。如果有疑問、更好的建議、或者糾正歡迎留言。demo下載地址:代碼地址