Android Text View 去掉默认的padding的实现方法

这篇具有很好参考价值的文章主要介绍了Android Text View 去掉默认的padding的实现方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

先看下最终实现效果,满意您在往下看:

Android Text View 去掉默认的padding的实现方法,android,java

TextView 绘制的时候自带一定的Padding值,要想实现去掉默认的padding值,xml文件可以设置一个属性值 :

android:includeFontPadding="false"

然后运行起来就会发现,并没有什么卵用,也不能说完全没有,但效果差点意思。我就不运行了,在编译器上也能大概看到效果,如下图,我们可以看到依然有着无法删除的padding值。

Android Text View 去掉默认的padding的实现方法,android,java

我们先来看一下绘制TextView时的几条基准线:

Android Text View 去掉默认的padding的实现方法,android,java

  • top:在给定文本大小下,字体中最高字形高于基线的最大距离,即能绘制的最高点
  • ascent:单倍行距文本的基线以上建议距离,即推荐的文字绘制上边缘线
  • base:文字绘制基准线,也就是坐标轴,X轴就是Baseline
  • decent:单间距文本低于基线的建议距离,即推荐的文字绘制下边缘线
  • bottom:能绘制的最低点

Textview绘制文字会在  ascentdecent 之间,外面的距离我们可以理解为 类似 padding一样的间隔,但又并不是我们设置的paddingTop,paddingBottom。

要解决这个这个问题,首先我们要知道textview的内容文字绘制的真实区域:

Android Text View 去掉默认的padding的实现方法,android,java

红色的区域就是内容的真实高度,蓝色的部分就是textview绘制的多余的部分,现在我们要去掉这一部分,首先可以通过 getTextBounds 来获取绘制的真实区域

textView.getPaint().getTextBounds(text, 0, text.length(), textRect);

获取到真实区域后,那么再来看textview绘制的几条基准线,你想到了什么,是的,我们只需要稍微移动一下这几条线把高度压缩到文字的展示绘制区域即可,实现用 SpannableString 来实现,SpannableString 是 android  里面专门用来实现设置 textview 文字样式的类,这个不清楚的自行查询一下,这里不赘述了,具体我们用的是  LineHeightSpan ,可以通过修改 textview 的行高来实现我们的目的。具体看下代码:

spannableString.setSpan(new LineHeightSpan() {
    @Override
    public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int lineHeight, Paint.FontMetricsInt fm) {
        Rect textRect = new Rect();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            textView.getPaint().getTextBounds(text, 0, text.length(), textRect);
        } else {
            textView.getPaint().getTextBounds(text.toString(), 0, text.length(), textRect);
        }
        // 直接把 textview 绘制区域 缩小到 文字真实大小的区域
        // 这个是有一点问题的,看下图
        fm.top = textRect.top;
        fm.bottom = textRect.bottom;
        fm.ascent = fm.top;
        fm.descent = fm.bottom;
    }
}, 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

 Paint.FontMetricsInt 里的 top bottom ascent descent 就是用来调整 绘制的时候的具体位置的,我们把textview的绘制区域直接设置到 FontMetricsInt 里面,实现的效果如下图:

Android Text View 去掉默认的padding的实现方法,android,java

看起来确实去掉了padding,而且去的干干净净,需要这种效果的可以停下来,施展CV大法。

这种实现方式原理也很简单,是使文字真实的绘制区域高度为所绘制内容中字符的最大高度,这样可能会造成排版问题,文字对不齐,那我们就需要统一下绘制内容的高度,我们知道TextView 有个属性TextSize ,它的值最终决定了Textview 的高度,然后我们略微修改一下代码:

spannableString.setSpan(new LineHeightSpan() {
    @Override
    public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int lineHeight, Paint.FontMetricsInt fm) {
        Rect textRect = new Rect();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            textView.getPaint().getTextBounds(text, 0, text.length(), textRect);
        } else {
            textView.getPaint().getTextBounds(text.toString(), 0, text.length(), textRect);
        }

        Log.e("NoPaddingText", "修改之前 " + fm.toString());
        Log.e("NoPaddingText", textRect.toString());
        Log.e("NoPaddingText", "textSize: " + textView.getTextSize());

        if (textRect.bottom - textRect.top < textView.getTextSize()) {
            // 一般我们认为字体的textview的textsize为textview的高度,当然有一定的误差
            // 当字体的高度没有字体的textsize大时,我们把大小设置成textsize,这样就可以解决文字的排版问题了
            float tempPadding = (textView.getTextSize() - (textRect.bottom - textRect.top)) / 2f;
            fm.top = (int) (textRect.top - tempPadding);
            fm.bottom = (int) (textRect.bottom + tempPadding);
        } else {
            fm.top = textRect.top;
            fm.bottom = textRect.bottom;
        }
        fm.ascent = fm.top;
        fm.descent = fm.bottom;
        Log.e("NoPaddingText", "修改之后 " + fm.toString());
    }
}, 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

我们用TextView的TextSize来约束统一绘制高度,不足TextSize 的,补充添加一个padding值补齐正常的高度,实现效果如下:

Android Text View 去掉默认的padding的实现方法,android,java

这样看着顺眼多了,继续CV大法。

完整代码如下:(两种实现形式:1、工具类; 2、自定义View形式实现)

点这里跳转项目源码地址文章来源地址https://www.toymoban.com/news/detail-805446.html

import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Build;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.LineHeightSpan;
import android.util.Log;
import android.widget.TextView;

// 工具类 实现
public class TextUtil {

    // 设置上下取消绘制的padding值 考虑textsize
    public static void setNoVerticalPaddingText(TextView textView, CharSequence text) {
        if (textView == null || text == null)
            return;
        // 如果原先上下有padding,重置为 0
        textView.setPadding(textView.getPaddingLeft(), 0, textView.getPaddingRight(), 0);
        // 利用 LineHeightSpan 快速实现去除 padding 的效果
        SpannableString spannableString = new SpannableString(text);
        spannableString.setSpan(new LineHeightSpan() {
            @Override
            public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int lineHeight, Paint.FontMetricsInt fm) {
                Rect textRect = new Rect();
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    textView.getPaint().getTextBounds(text, 0, text.length(), textRect);
                } else {
                    textView.getPaint().getTextBounds(text.toString(), 0, text.length(), textRect);
                }

                Log.e("NoPaddingText", "修改之前 " + fm.toString());
                Log.e("NoPaddingText", textRect.toString());
                Log.e("NoPaddingText", "textSize: " + textView.getTextSize());

                if (textRect.bottom - textRect.top < textView.getTextSize()) {
                    // 一般我们认为字体的textview的textsize为textview的高度,当然有一定的误差 当然也可以自定义View 形式
                    // 当字体的高度没有字体的textsize大时,我们把大小设置成textsize,这样就可以解决文字的排版问题了
                    float tempPadding = (textView.getTextSize() - (textRect.bottom - textRect.top)) / 2f;
                    fm.top = (int) (textRect.top - tempPadding);
                    fm.bottom = (int) (textRect.bottom + tempPadding);
                } else {
                    // 这么设置可以完全消除padding,但是会有问题,
                    // 同样textsize的Textview 会因为设置的内容不一样而高度不一样
                    // 如果有什么特殊需求可以考虑用一下
                    fm.top = textRect.top;
                    fm.bottom = textRect.bottom;
                }
                fm.ascent = fm.top;
                fm.descent = fm.bottom;
                Log.e("NoPaddingText", "修改之后 " + fm.toString());
            }
        }, 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        textView.setText(spannableString);
    }


    // 设置上下取消绘制的padding值 不考虑textsize
    public static void setNoVerticalPaddingText2(TextView textView, CharSequence text) {
        if (textView == null || text == null)
            return;
        // 如果原先上下有padding,重置为 0
        textView.setPadding(textView.getPaddingLeft(), 0, textView.getPaddingRight(), 0);
        // 利用 LineHeightSpan 快速实现去除 padding 的效果
        SpannableString spannableString = new SpannableString(text);
        spannableString.setSpan(new LineHeightSpan() {
            @Override
            public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int lineHeight, Paint.FontMetricsInt fm) {
                Rect textRect = new Rect();
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    textView.getPaint().getTextBounds(text, 0, text.length(), textRect);
                } else {
                    textView.getPaint().getTextBounds(text.toString(), 0, text.length(), textRect);
                }

                Log.e("NoPaddingText", "修改之前 " + fm.toString());
                Log.e("NoPaddingText", textRect.toString());
                Log.e("NoPaddingText", "textSize: " + textView.getTextSize());

                // 这么设置可以完全消除padding,但是会有问题,
                // 同样textsize的Textview 会因为设置的内容不一样而高度不一样
                // 如果有什么特殊需求可以考虑用一下
                fm.top = textRect.top;
                fm.bottom = textRect.bottom;
                fm.ascent = fm.top;
                fm.descent = fm.bottom;
                Log.e("NoPaddingText", "修改之后 " + fm.toString());
            }
        }, 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        textView.setText(spannableString);
    }

}
import android.content.Context;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Build;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.LineHeightSpan;
import android.util.AttributeSet;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;

/**
 * 自定义view 形式 实现 NoPaddingTextView 布局可以预览
 */
public class NoPaddingTextView extends AppCompatTextView {


    public NoPaddingTextView(@NonNull Context context) {
        this(context, null);
    }

    public NoPaddingTextView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    @Override
    public void setText(CharSequence text, BufferType type) {
        super.setText(getNoVerticalPaddingText(this,text), type);
    }

    // 设置上下取消绘制的padding值 考虑textsize
    public final SpannableString getNoVerticalPaddingText(TextView textView, CharSequence text) {
        if (textView == null || text == null)
            return new SpannableString("");
        // 如果原先上下有padding,重置为 0
        textView.setPadding(textView.getPaddingLeft(), 0, textView.getPaddingRight(), 0);
        // 利用 LineHeightSpan 快速实现去除 padding 的效果
        SpannableString spannableString = new SpannableString(text);
        spannableString.setSpan(new LineHeightSpan() {
            @Override
            public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int lineHeight, Paint.FontMetricsInt fm) {
                Rect textRect = new Rect();
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    textView.getPaint().getTextBounds(text, 0, text.length(), textRect);
                } else {
                    textView.getPaint().getTextBounds(text.toString(), 0, text.length(), textRect);
                }

                //Log.e("NoPaddingText", "修改之前 " + fm.toString());
                //Log.e("NoPaddingText", textRect.toString());
                //Log.e("NoPaddingText", "textSize: " + textView.getTextSize());

                if (textRect.bottom - textRect.top < textView.getTextSize()) {
                    // 一般我们认为字体的textview的textsize为textview的高度,当然有一定的误差 当然也可以自定义View 形式
                    // 当字体的高度没有字体的textsize大时,我们把大小设置成textsize,这样就可以解决文字的排版问题了
                    float tempPadding = (textView.getTextSize() - (textRect.bottom - textRect.top)) / 2f;
                    fm.top = (int) (textRect.top - tempPadding);
                    fm.bottom = (int) (textRect.bottom + tempPadding);
                } else {
                    // 这么设置可以完全消除padding,但是会有问题,
                    // 同样textsize的Textview 会因为设置的内容不一样而高度不一样
                    // 如果有什么特殊需求可以考虑用一下
                    fm.top = textRect.top;
                    fm.bottom = textRect.bottom;
                }
                fm.ascent = fm.top;
                fm.descent = fm.bottom;
                //Log.e("NoPaddingText", "修改之后 " + fm.toString());
            }
        }, 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        return spannableString;
    }
}

到了这里,关于Android Text View 去掉默认的padding的实现方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Android】自定义View onDraw()方法会调用两次

    自定义了View后,在构造函数中设置画笔颜色,发现它没起效,但是在onDraw()里设置颜色就会起效,出问题的代码如下: 我在构造函数中设置的画笔颜色是红色,但是实际画出的线是黑色的(画笔默认颜色是黑色),分析了一下发现是paint.reset()的问题,reset就是画笔重置设置嘛

    2024年01月19日
    浏览(31)
  • Android View实现滑动的方式

    实现View的滑动有三种方式 通过View本身提供的scrollTo/scrollBy方法实现滑动 通过动画给View施加平移效果来实现滑动 通过改变View LayoutParams使得View重新布局从而实现滑动 scrollTo:通过传递的参数实现绝对滑动 scrollBy:通过传递的参数实现相对滑动 scrollTo和scrollBy只能改变View内容

    2024年02月16日
    浏览(49)
  • Android 11.0 SystemUI 去掉状态栏wifi流量上下行图标功能实现

      在11.0系统定制rom开发中,在关于systemui的定制功能总,在SystemUI 状态栏上显示时钟,电池电量 wifi图标,在显示wifi图标时,网络实时更新时,但是会时不时显示上下行图标 显得很不美观,客户需求要求不显示上下行图标,所以需要去掉上下行图标功能,接下来实现相关功能开

    2024年02月04日
    浏览(54)
  • Android自定义View之游戏摇杆键盘实现(一),快手android面试经验

    public class RemoteViewBg { private Bitmap bitmapBg; public RemoteViewBg(Bitmap bitmap) { bitmapBg = bitmap; } //背景的绘图函数 public void draw(Canvas canvas, Paint paint, Rect src0 ,Rect dst0 ) { canvas.drawBitmap(bitmapBg, src0, dst0, paint); } } 重写系统的触摸时间,判断触摸点在背景范围内还是背景范围外 @Override public b

    2024年04月12日
    浏览(45)
  • Android自定义View之游戏摇杆键盘实现(一)

    public class RemoteViewBg { private Bitmap bitmapBg; public RemoteViewBg(Bitmap bitmap) { bitmapBg = bitmap; } //背景的绘图函数 public void draw(Canvas canvas, Paint paint, Rect src0 ,Rect dst0 ) { canvas.drawBitmap(bitmapBg, src0, dst0, paint); } } 重写系统的触摸时间,判断触摸点在背景范围内还是背景范围外 @Override public b

    2024年04月17日
    浏览(52)
  • Android View转换为Bitmap,实现截屏效果

            安卓设备一般都自带截图功能,但是用户体验有不好之处。就是会连带着状态栏📶、🔋、时间日期、其他不必要页面中信息,等等与用户想截屏的内容不符的信息也会被保存下来。通常,截图后用户会再次裁剪一次才能想把真正需求分享出去。         因此,咱们

    2023年04月08日
    浏览(51)
  • Android 12 内置系统默认动态壁纸(视频资源)实现

    新建APP 项目 实现 WallpaperService 实现视频播放的引擎 AndroidManifest.xml 里注册服务 其中的 intent-filter 、action 、meta-data 都是固定写法,用于系统识别,我们需要配置的是 后面的 android:resource=“@xml/magic” 资源配置 @xml/magic 在 res 目录下,新建 xml 文件夹 然后新建 xxxx.xml(如本例:

    2023年04月26日
    浏览(267)
  • Android 打包AAB+PAD(Unity篇),Android开发基础面试题

    这些部分适用于**「fast-follow」 和 「on-demand」**资产包。 检查状态 每个资产包都存储在应用程序内部存储的单独文件夹中。使用该 「isDownloaded()」 方法确定是否已下载资产包。 监控下载 查询PlayAssetBundleRequest 监控请求状态的 对象: // Download progress of request, between 0.0f 

    2024年04月14日
    浏览(45)
  • Android去掉视频声音

    【Android】使用MediaExtractor、MediaMuxer去掉视频文件中的音频数据_android 去掉视频音频_little_fat_sheep的博客-CSDN博客 选择视频文件

    2024年02月10日
    浏览(38)
  • Android终极大招之全面取代drawble文件实现View圆角背景样式的新方案

    最近一直忙于音视频SDK的开发,遇到很多问题,简单来说,就是怎么让别人接入SDK时越简单越好。相信大多数Android开发都会遇到一个场景,给TextView或Button添加背景颜色,修改圆角,描边等需求。一看到这样的实现效果,自然就是创建drawble文件,设置相关属性shap,color,ra

    2024年02月07日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包