Android开发过程中可能很多人都遇到过这样的问题,那就是TextView上下内边距的问题。使用TextView控件的时候由于其内边距导致与UI效果相差甚远。很是让不少程序猿难受,也包括我自己因为这个原因也没少和UI设计师打嘴仗。于是最近写了一个自定义的NoBroderTextView去除了TextView上下内边距。

        通过查阅Google官网的Android开发文档发现TextView中有android:includeFontPadding属性去除内边距。但是当设置该数据行为false的时候发现TextView还有一点点内边距存在,并不能让TextView控件的上下边距与文本严丝合缝。而这一点点的间距是Android框架中为TextView预留的字体边际。无法通过System API设置及修改。感兴趣的同学可以查看源码发现。无奈只能自定义实现TextView实现了,话不多少直接上代码。

package com.liming.nobroder.nopaddingtextview.views;import android.content.Context;import android.graphics.Canvas;import android.graphics.Rect;import android.support.v7.widget.AppCompatTextView;import android.text.Layout;import android.text.TextPaint;import android.text.TextUtils;import android.util.AttributeSet;import android.util.Log;/** * 无内边距TextView控件 * @author liming Create date : 2019/01/30 */public class NoPaddingTextView extends AppCompatTextView {    //日志标记    private final String TAG = NoPaddingTextView.class.getSimpleName();    //文本画笔    private TextPaint textPaint;    //绘制矩形    private Rect rect;    //默认宽度    private int layoutWidth = -1;    //获得每行数据    private String[] lineContents;    //获取行间距的额外空间    private float line_space_height = 0.0f;    //获取行间距乘法器    private float line_space_height_mult = 1.0f;    /**     * 构造方法     *     * @param context     * @param attrs     */    public NoPaddingTextView(Context context, AttributeSet attrs) {        super(context, attrs);        init(context, attrs);    }    /**     * 构造方法     *     * @param context     * @param attrs     * @param defStyleAttr     */    public NoPaddingTextView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(context, attrs);    }    /**     * 初始化方法     */    private void init(Context context, AttributeSet attrs) {        //声明画笔对象        textPaint = new TextPaint();        //声明矩形绘制对象        rect = new Rect();        //获得行间距额外数据        line_space_height = getLineSpacingExtra();        //获得行间距方法器        line_space_height_mult = getLineSpacingMultiplier();    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        Layout _layout = getLayout();        if (_layout != null) {            //获得文本内容文本内容不可以修改,平切判断当前当前内容是否为null            final String _tvContent = TextUtils.isEmpty(getText()) ? "" : getText().toString();            //获取文本长度            final int _tvLenght = _tvContent.length();            //设置文本宽度            textPaint.getTextBounds(_tvContent, 0, _tvLenght, rect);            //设置文本大小            textPaint.setTextSize(getTextSize());            //设置文本颜色            textPaint.setColor(getCurrentTextColor());            //获取行数据            getTextContentData(_layout);            //获得行高            int _lineHeight = -rect.top + rect.bottom;            //初始化布局            initLayout(_layout);            //设置布局区域            int[] _area = getWidthAndHeigt(widthMeasureSpec, heightMeasureSpec, layoutWidth, _layout.getLineCount(), _lineHeight);            //设置布局            setMeasuredDimension(_area[0], _area[1]);        }    }    /**     * 初始化化布局高度     *     * @param _layout     */    private void initLayout(Layout _layout) {        //获得布局大小        if (layoutWidth < 0) {            //获取第一次测量数据            layoutWidth = _layout.getWidth();        }    }    /**     * 获取布局数据     *     * @param pWidthMeasureSpec     * @param pHeightMeasureSpec     * @param pWidth     * @return 返回宽高数组     */    private int[] getWidthAndHeigt(int pWidthMeasureSpec, int pHeightMeasureSpec, int pWidth, int pLineCount, int pLineHeight) {        int _widthMode = MeasureSpec.getMode(pWidthMeasureSpec);   //获取宽的模式        int _heightMode = MeasureSpec.getMode(pHeightMeasureSpec); //获取高的模式        int _widthSize = MeasureSpec.getSize(pWidthMeasureSpec);   //获取宽的尺寸        int _heightSize = MeasureSpec.getSize(pHeightMeasureSpec); //获取高的尺寸        //声明控件尺寸        int _width;        int _height;        //判断模式        if (_widthMode == MeasureSpec.EXACTLY) {            //如果match_parent或者具体的值,直接赋值            _width = _widthSize;        } else {            _width = pWidth - rect.left;        }        //高度跟宽度处理方式一样        if (_heightMode == MeasureSpec.EXACTLY) {            _height = _heightSize;        } else {            if(pLineCount > 1){                _height = pLineHeight * pLineCount + (int) (line_space_height * line_space_height_mult * (pLineCount -1));            }else{                _height = pLineHeight * pLineCount;            }        }        //初始化宽高数组        int[] _area = {                _width,                _height        };        return _area;    }    /**     * 获取行数据     *     * @param _layout 文本布局对象(注:该布局其实使用的是Layout子类对象StaticLayout)     */    private void getTextContentData(Layout _layout) {        //初始化航速数据        lineContents = new String[_layout.getLineCount()];        //获得每行数据        for (int i = 0; i < _layout.getLineCount(); i++) {            int _start = _layout.getLineStart(i);            int _end = _layout.getLineEnd(i);            lineContents[i] = getText().subSequence(_start, _end).toString();        }    }    @Override    protected void onDraw(Canvas canvas) {        //行高        float _line_height = -rect.top + rect.bottom;        //行间距        float _line_space = line_space_height * line_space_height_mult;        //循环获取每行数据内容        for (int i = 0; i < lineContents.length; i++) {            //获得数据            String _drawContent = lineContents[i];            //显示日志            Log.e(TAG, "LINE[" + (i + 1) + "]=" + _drawContent);            //绘制每行数据            canvas.drawText(_drawContent, 0, -rect.top + (_line_height + _line_space) * i, textPaint);        }    }}

        其中getTextContentData()方法获取文本内容,并且获取每行数据将其缓存到lineContents数组中。

        通过getWidthAndHeight()方法获取自定义控件的宽高(其实就是当控件设置为wrap_content或者match_parent的时候实际控件的高度)获取之后重新在设置到自定义控件。

      onDraw()方法实现绘制这个就不多说了。

以下TextView中的属性依然奏效

android:lineSpacingExtra="设置行间距(默认为0.0f)"android:lineSpacingMultiplier="行间距基数(默认为1.0f)"

项目GitHub地址:https://github.com/liming870906/NoBroderTextView.git

android:lineSpacingExtra="设置行间距(默认为0.0f)"android:lineSpacingMultiplier="行间距基数(默认为1.0f)"

效果如下:

更多相关文章

  1. “罗永浩抖音首秀”销售数据的可视化大屏是怎么做出来的呢?
  2. Nginx系列教程(三)| 一文带你读懂Nginx的负载均衡
  3. 不吹不黑!GitHub 上帮助人们学习编码的 12 个资源,错过血亏...
  4. Android实现简单底部导航栏 Android仿微信滑动切换效果
  5. android wear端数据和手机端数据
  6. 五步学会Android的ListView控件
  7. Android(安卓)重要数据目录
  8. understand and use android mvc(理解及使用android mvc)
  9. android中如何美化ListView的背景

随机推荐

  1. [转]Android中的Intent详细讲解
  2. Android的static静态变量
  3. “白菜”Android全靠它——RK2818芯片全
  4. kotlin开发Android入门篇八Kotlin开发And
  5. Android逆向案例:干掉梆梆加固免费版的反
  6. Android 开源8款游戏引擎
  7. 搭建Windows下Android应用开发环境——Ec
  8. Android异步任务之AsyncTask的使用
  9. Kotlin基础(一)android studio中配置Kotlin
  10. Android中数据存储----偏好设置