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下载地址:代码地址

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