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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值