安卓中设置渐变字体和描边字体

embedded/2024/9/24 6:28:28/

1.CommonFontSpan

abstract class CommonFontSpan : ReplacementSpan() {/** 测量的文本宽度  */private var mMeasureTextWidth = 0foverride fun getSize(paint: Paint,text: CharSequence?,start: Int,end: Int,fontMetricsInt: FontMetricsInt?): Int {mMeasureTextWidth = onMeasure(paint, fontMetricsInt, text, start, end)// 这段不可以去掉,字体高度没设置,会出现 draw 方法没有被调用的问题val metrics = paint.fontMetricsIntif (fontMetricsInt != null) {fontMetricsInt.top = metrics.topfontMetricsInt.ascent = metrics.ascentfontMetricsInt.descent = metrics.descentfontMetricsInt.bottom = metrics.bottom}return mMeasureTextWidth.toInt()}override fun draw(canvas: Canvas,text: CharSequence?,start: Int,end: Int,x: Float,top: Int,y: Int,bottom: Int,paint: Paint) {val alpha = paint.alpha// 判断是否给画笔设置了透明度if (alpha != 255) {// 如果是则设置不透明paint.alpha = 255}text?.let {onDraw(canvas, paint, it, start, end, x, top, y, bottom)}// 绘制完成之后将画笔的透明度还原回去paint.alpha = alpha}private fun onMeasure(paint: Paint,fontMetricsInt: FontMetricsInt?,text: CharSequence?,@IntRange(from = 0) start: Int,@IntRange(from = 0) end: Int): Float {return paint.measureText(text, start, end)}abstract fun onDraw(canvas: Canvas,paint: Paint,text: CharSequence,@IntRange(from = 0) start: Int,@IntRange(from = 0) end: Int,x: Float,top: Int,y: Int,bottom: Int)fun getMeasureTextWidth(): Float {return mMeasureTextWidth}
}

2.MultiFontSpan

class MultiFontSpan(vararg replacementSpans: ReplacementSpan) : ReplacementSpan() {/** 测量的文本宽度  */private var mMeasureTextWidth = 0fprivate var mReplacementSpans: List<ReplacementSpan> = mutableListOf()init {mReplacementSpans = replacementSpans.toList()}override fun getSize(paint: Paint,text: CharSequence?,start: Int,end: Int,fm: Paint.FontMetricsInt?): Int {for (replacementSpan in mReplacementSpans) {val size = replacementSpan.getSize(paint, text, start, end, fm)mMeasureTextWidth = Math.max(mMeasureTextWidth, size.toFloat())}return mMeasureTextWidth.toInt()}override fun draw(canvas: Canvas,text: CharSequence?,start: Int,end: Int,x: Float,top: Int,y: Int,bottom: Int,paint: Paint) {for (replacementSpan in mReplacementSpans) {replacementSpan.draw(canvas, text, start, end, x, top, y, bottom, paint)}}override fun updateDrawState(ds: TextPaint?) {super.updateDrawState(ds)for (replacementSpan in mReplacementSpans) {replacementSpan.updateDrawState(ds)}}override fun updateMeasureState(p: TextPaint) {super.updateMeasureState(p)for (replacementSpan in mReplacementSpans) {replacementSpan.updateMeasureState(p)}}
}

3.LinearGradientFontSpan

class LinearGradientFontSpan(private val mTextGradientColor: IntArray,     /** 文字渐变颜色组 */private val mTextSize: Int? = null,     /** 文字渐变字体大小(字体大小不一致的话这里必须动态设置) */private val mTextGradientOrientation: Int? = LinearLayout.VERTICAL,    /** 文字渐变方向 */private val mTextGradientPositions: FloatArray? = null,   /** 文字渐变位置组 */
) : CommonFontSpan() {override fun onDraw(canvas: Canvas,paint: Paint,text: CharSequence,start: Int,end: Int,x: Float,top: Int,y: Int,bottom: Int) {mTextSize?.let { paint.textSize = it.sp }val linearGradient = if (mTextGradientOrientation == LinearLayout.VERTICAL) {LinearGradient(0f, 0f, 0f, bottom.toFloat(), mTextGradientColor, mTextGradientPositions, Shader.TileMode.REPEAT)} else {LinearGradient(x, 0f, x + getMeasureTextWidth(), 0f, mTextGradientColor, mTextGradientPositions, Shader.TileMode.REPEAT)}paint.shader = linearGradientcanvas.drawText(text, start, end, x, y.toFloat(), paint)}override fun getSize(paint: Paint,text: CharSequence?,start: Int,end: Int,fontMetricsInt: Paint.FontMetricsInt?): Int {mTextSize?.let { paint.textSize = it.sp }return super.getSize(paint, text, start, end, fontMetricsInt)}
}

4.StrokeFontSpan

class StrokeFontSpan(private val mTextStrokeColor: Int,private val mTextStrokeSize: Int,private val isSp: Boolean = true,
) : CommonFontSpan() {/** 描边画笔  */private val mStrokePaint = Paint()override fun onDraw(canvas: Canvas,paint: Paint,text: CharSequence,start: Int,end: Int,x: Float,top: Int,y: Int,bottom: Int) {mStrokePaint.set(paint)// 设置抗锯齿mStrokePaint.isAntiAlias = true// 设置防抖动mStrokePaint.isDither = truemStrokePaint.textSize = paint.textSize// 描边宽度mStrokePaint.strokeWidth = if (isSp) mTextStrokeSize.dp else mTextStrokeSize.toFloat()mStrokePaint.style = Paint.Style.STROKE// 设置粗体paint.isFakeBoldText = paint.typeface === Typeface.DEFAULT_BOLDmStrokePaint.color = mTextStrokeColorcanvas.drawText(text, start, end, x, y.toFloat(), mStrokePaint)canvas.drawText(text, start, end, x, y.toFloat(), paint)}
}

5.使用

SpanUtils.with(mBindView.tvAnswerBtn1).append("豆奶").setSpans(StrokeFontSpan(Color.WHITE, 1)).append("好喝").setSpans(LinearGradientFontSpan(intArrayOf(Color.RED, Color.BLUE))).append("还要").setSpans(MultiFontSpan(StrokeFontSpan(Color.GREEN, 2),LinearGradientFontSpan(intArrayOf(Color.WHITE, Color.YELLOW)))).create()

设置渐变字体 大小不同

 val colors = intArrayOf(Color.parseColor("#FDF4E9"), Color.parseColor("#FFDD63"))SpanUtils.with(mBindView.tvMaxMoney).append("30").setBold().setSpans(LinearGradientFontSpan(colors, 100)).append("元").setSpans(LinearGradientFontSpan(colors, 32)).create()

http://www.ppmy.cn/embedded/98376.html

相关文章

学习ComfyUI的一个不错网站:www.comflowy.com/basics

学习ComfyUI&#xff0c;不仅仅是照搬别人的工作流来使用&#xff0c;重要的是能自己搭建工作流&#xff0c;而要能够熟练搭建&#xff0c;离不开对工作流中节点&#xff08;特别是重要节点&#xff09;的透彻理解。比如我自己&#xff0c;原来对 Lora 就十分陌生&#xff0c;不…

SSH 隧道方式连接 MySQL 服务器

SSH 隧道方式连接 MySQL 服务器 1 安装 MySQL 客户端工具1.1 Navicat1.2 MySQL Workbench1.2.1 查看本机系统类型1.2.2 安装 Visual C 20191.2.3 安装 MySQL Workbench 2 SSH 隧道方式连接数据库2.1 Navicat2.1.1 SSH 连服务器2.1.2 本地连数据库 2.2 MySQL Workbench 本文介绍…

[数据集][目标检测]街灯检测数据集VOC+YOLO格式1893张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1893 标注数量(xml文件个数)&#xff1a;1893 标注数量(txt文件个数)&#xff1a;1893 标注…

CC攻击导致服务器卡顿的技术解析

摘要 本文将深入探讨CC&#xff08;Challenge Collapsar&#xff09;攻击的工作原理以及它们如何导致服务器性能下降乃至卡顿。我们将通过一个简单的Python脚本模拟客户端行为来说明这一过程&#xff0c;并提供一些基本的缓解策略。 1. 引言 CC攻击是一种特定类型的DDoS攻击&…

Leetcode 219. 存在重复元素 II

题目描述 给你一个整数数组 nums 和一个整数 k &#xff0c;判断数组中是否存在两个 不同的索引 i 和 j &#xff0c;满足 nums[i] nums[j] 且 abs(i - j) < k 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#x…

无人机测绘技术及应前景详解

无人机测绘技术是一种将无人机技术、遥感技术、地理信息系统&#xff08;GIS&#xff09;和计算机技术相结合&#xff0c;对自然地理要素或地表人工设施的形状、大小、空间位置及其属性等进行测定、采集并绘制成图的技术。它利用高精度传感器&#xff08;如激光雷达、航拍相机等…

GT IP中Use Channel Bonding与Use Clock Correction的关系

在高速数据传输系统中&#xff0c;如PCIE等&#xff0c;为了确保多个数据通道之间的数据能够正确同步和对齐&#xff0c;通常会使用通道绑定技术。这种技术通过特定的字符序列来标识和同步不同通道的数据流。 当你选择“使用通道绑定”这个选项时&#xff0c;系统会在接收端启用…

KRTS 高速以太网:网络模块套接字 API

高速以太网&#xff1a;网络模块套接字 API 目录 高速以太网&#xff1a;网络模块套接字 API打开套接字关闭套接字无连接发送和接收通过连接发送和接收执行套接字命令安装套接字处理器 Socket模块基于Packet模块&#xff0c;实时提供更高的协议&#xff0c;如RAW-IP、TCP 和 UD…