安卓开发 自定义TextView 去除默认内边距

一.搜到的大部分的解决办法

1.网上方法的效果

在xml文件中对TextView设置: includeFontPadding=false

加上以上属性之后,文本的高度明显变小了,但是没有达到我们预想的效果(文字紧贴边框),而是在上下留了一部分距离。

具体效果可以查看第二部分中的对比图

 

2.失效的原因

在了解这个原因前需要对TextView中文本的绘制有一点了解,具体查看文末参考文章中启航大佬的介绍文章。

对应下图,top和bottom之间的高度,就是默认的TextView的高度

includeFontPadding=false属性取消的是top和ascent之间bottom和descent之间的两个空白区域。

但是也看的出来,在ascent和descent中间的文字,距离两条线还是有一定距离,这也就是在设置includeFontPadding=false属性后继续留着的空白部分。

 

(图来自启航大佬的文章)

 

具体从源码中可以看出这个过程

查看TextView的源码中查找mIncludePad属性,发现都是进到一个BoringLayout

在其中查找includepad,在其init()方法中找到以下部分。

其中metrics为系统提供的用于查询top,ascent,descent,bottom四个属性的一个对象

 

 

二.自定义view实现效果

 

1.最终效果对比图

中间的为普通的TextView

 

2 自定义的思路

首先系统提供了一个用于检测包裹住的文字所需最小的矩形的方法。

 

/**
 * 获取指定字符串所对应的最小矩形,以(0,0)点所在位置为基线
 * @param text   要测量最小矩形的字符串
 * @param start  要测量起始字符在字符串中的索引
 * @param end    所要测量的字符的长度
 * @param bounds 接收测量结果
 */
public void getTextBounds(String text, int start, int end, Rect bounds);

自定义View

onMeasure

中把宽高设置为上述最小矩形的宽高

onDraw

由于宽高被重新设置了,所以canvas中原点要进行位移,才能使得文本正常显示。

 

3 具体代码

public class MyNoPaddingTextView extends android.support.v7.widget.AppCompatTextView {
    private Rect minRect;

    public MyNoPaddingTextView(Context context) {
        super(context);
    }

    public MyNoPaddingTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyNoPaddingTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (minRect == null) {
            //minRect用来获取文字显示所需要最小区域的左上角和右下角  坐标
            //该坐标是以(0,0)为基准的矩形坐标
            minRect = new Rect();
        }
        getPaint().getTextBounds(getText().toString(), 0, getText().length(), minRect);
        final int width = minRect.width();
        final int height = minRect.height();
        setMeasuredDimension(width, height);
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        final String text = getText().toString();
        final int left = minRect.left;
        final int top = minRect.top;
        Paint paint = getPaint();
        paint.setColor(getCurrentTextColor());
        /*此时文字的基线在(0,0),要达到刚好包裹文字的效果,相当于把以(0,0)为基线的minRect 移动到合适的位置
        x轴上由于左边内边距的存在,所以需要左移minRect.left距离
        y轴上相当于把mingRect的顶点向下移动minRect.top距离
        */
        canvas.drawText(text, -left, -top, paint);
    }
}

4.补充

(1)如果需要修改或者了解,一定要看参考文献中启航大佬的文章,介绍的很详细,避免走弯路。

(2)对于wrap_content的文本效果是可以满足的,如果需要指定文本大小,则需要在onMeasure中重写一下。

(3)使用本文中的代码时,xml中的padding会失效,如果有左右padding的需求,可以通过onMeasure和onDraw中getPaddingLeft()等方法判断一下,测试过是可以实现padding效果的。

(4)只测试了wrap_content的效果(效果有用了),要是有别的问题大家可以一起讨论解决。

 

 

参考文章:

启航 drawText()详解: https://blog.csdn.net/harvic880925/article/details/50423762

另一种自定义view实现效果 :https://blog.csdn.net/qq1282675628/article/details/79146859

去掉内边距(但是只去掉了上面部分):https://blog.csdn.net/Ab0510/article/details/52219464

 

 

 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要在Android自定义TextView中显示全部内容,可以使用以下两种方法: 1. 使用setEllipsize()方法 通过设置setEllipsize()方法,可以在TextView的末尾添加省略号,从而指示文本被截断。你可以使用以下代码来实现: ``` yourTextView.setEllipsize(TextUtils.TruncateAt.END); yourTextView.setSingleLine(true); ``` 上述代码将设置TextView只显示一行并在末尾添加省略号。 2. 自定义TextView 你可以从TextView类继承一个新类,并覆盖onMeasure()方法以测量控件的高度和宽度。 你可以使用以下代码实现: ``` public class CustomTextView extends TextView { public CustomTextView(Context context) { super(context); } public CustomTextView(Context context, AttributeSet attrs) { super(context, attrs); } public CustomTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //获取TextView的内容 CharSequence text = getText(); if (text != null) { //测量TextView的高度 int width = getMeasuredWidth(); int height = getMeasuredHeight(); int lineCount = getLineCount(); int lineHeight = getLineHeight(); int totalHeight = lineCount * lineHeight; if (totalHeight > height) { setMeasuredDimension(width, totalHeight); } } } } ``` 上述代码将测量TextView的高度,如果文本的高度超出了TextView的高度,则调整TextView的高度以适应文本。然后你可以使用此自定义TextView来显示你的文本。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值