付出终有回报,找准方向,努力向前
一、简介
本文章主要介绍三种方式实现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下载地址:代码地址