Android實現Edittext顯示下滑線的三種方法

付出終有回報,找準方向,努力向前

一、簡介

本文章主要介紹三種方式實現Edittext下方顯示下滑線,各有利弊,可以根據情景自行選擇,其中有關字體顯示的基準線、行高相關的知識。此篇主要介紹正常模式下代碼如何去寫,這裏還有一篇是兼容行距(設置倍數或者具體數值)。


二、可收穫

  1. 如何實現Edittext顯示下劃線

  2. 根據情況如何選擇實現方式

  3. 字體的行高、基準線是什麼


三、如何實現

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下載地址:代碼地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章