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

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.mzph.cn/diannao/52317.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习辅助复合材料预测,性能管理优化创新材料,这种王炸般的组合,还真是大开眼界!

在人工智能与复合材料技术融合的背景下&#xff0c;复合材料的研究和应用正迅速发展&#xff0c;创新解决方案层出不穷。从复合材料性能的精确预测到复杂材料结构的智能设计&#xff0c;从数据驱动的材料结构优化到多尺度分析&#xff0c;人工智能技术正以其强大的数据处理能力…

Eureka 原理与实践全攻略

一、Eureka 概述 Eureka 在微服务架构中具有举足轻重的地位。它作为服务注册与发现的核心组件&#xff0c;为分布式系统中的服务管理提供了关键支持。 Eureka 的主要功能包括服务注册、服务发现、服务健康监测和自我保护机制。服务注册功能使得服务提供者能够在启动时将自身的…

git-版本管理工具基本操作-创建仓库-拉取-推送-暂存库-版本库

1、创建仓库和版本说明 2、克隆仓库到本地&#xff08;首次拉取需要输入用户名和密码&#xff0c;用户名用邮箱&#xff0c;密码用登录gitee的密码&#xff0c;后面配置密钥后可以直接clone&#xff09; 在命令行输出两行指令配置git才能克隆&#xff1a; username&#xff1…

JUnit 断言验证

assertEquals(expected, actual)&#xff1a; 检查 actual 是否等于 expected。示例&#xff1a; assertEquals(5, myMethod(2, 3)); // 检查 2 3 是否等于 5 assertTrue(condition)&#xff1a; 检查 condition 是否为 true。示例&#xff1a; assertTrue(myMethod(1) > …

求数组中出现次数超过一半的数字

一、题目 数组中有一个数字出现的次数超过数组长度的一半&#xff0c;请找出这个数字。 假设数组非空&#xff0c;并且一定存在满足条件的数字。 思考题&#xff1a; 假设要求只能使用 O(n)的时间和额外 O(1)的空间&#xff0c;该怎么做呢&#xff1f; 数据范围 数组长度…

《Web项目跨域请求后端Api设置Cookie失败问题?》

问题描述&#xff1a; 在web项目中跨域请求api时&#xff0c;api登录成功后需要向域名中设置cookie实现在两个域名下共享&#xff0c;但是登录接口返回成功&#xff0c;响应头中也有set-cookie&#xff0c;实际却无法设置到cookie中… web项目访问时的域名https://b.com/ api所…

解锁Spring Boot、Prometheus与Grafana三合一:打造你的专属自定义指标炫酷大屏!

1. 集成Prometheus到Spring Boot 需要在Spring Boot应用中集成Prometheus。可以通过micrometer库来实现。micrometer是一个应用程序监控库&#xff0c;它支持多种监控系统&#xff0c;包括Prometheus。 一招制胜&#xff01;Spring Boot、Prometheus和Grafana三剑合璧&#x…

一、react-hooks(useState、useRef、forwardRef)

一、useState 注意事项&#xff1a; 1.setState的方法并不像函数式组件会自动合并&#xff0c;所以需要我们通过展开运算符手动合并。 // 更新方式1&#xff1a;展开运算符// const info{...userInfo,...data}// setUserInfo(info)// 方式2&#xff1a;setUserInfo(Object.as…

roscpp 实现深度图像与RGB图像的对齐

目录 通用内容通用可视化函数topic订阅版可视化深度图像的callback直接读取rosbag版通用内容 放到代码最上面 #include <ros/ros.h> #include <sensor_msgs/Image.h> #include <cv_bridge/cv_bridge.h> #include <opencv2/opencv.hpp> //#include &l…

银河麒麟服务器操作系统Kylin-Server-V10-SP3-2403-Release-20240426-x86_64安装步骤

银河麒麟服务器操作系统 Kylin-Server-V10-SP3-2403-Release-20240426-x86_64安装步骤 一、准备工作1. 下载ISO镜像2. 制作安装介质3. 设置BIOS 二、安装过程1. 启动系统2. 选择安装语言3. 选择安装配置4. 配置root密码与创建用户5. 开始安装6. 重启系统7. 同意许可协议 三、系…

【sql】加密所有的存储程式

因项目管理规定&#xff0c;所有的存储程式&#xff08;SP&#xff09;都需要加密。 如何批量加密所有的SP呢&#xff1f; 在网上找到了参考的代码&#xff0c;然后发现除SP外连同View,Trigger,Function等也可以一并处理&#xff01; 参考资料&#xff1a; https://download.…

【Redis】基本全局命令

Redis的基本全局命令 keysexistsdelexpirettltype Redis 有 5 种数据结构&#xff0c;但它们都是键值对种的值&#xff0c;对于键来说有⼀些通⽤的命令。 keys 返回所有满足样式 &#xff08;pattern&#xff09;的key。支持如下统配样式。 h?llo 匹配 hello , hallo 和 hxl…

七、SPA单页面实现SEO优化之SSR服务器渲染

文章目录 一、前言&#xff1a;二、SSR基本操作步骤 一、前言&#xff1a; 关于SPA和SEO优化、SSR服务器渲染的介绍可以参考这里&#xff1a; 六、什么是SEO优化&#xff08;搜索引擎优化&#xff09;&#xff1f;SPA单页面应用如何实现SEO优化&#xff1f; 通过上一篇文章可…

2024 实训室建设:1+X 老年生活照护实训室

摘要&#xff1a;本文探讨了 2024 年 1X 老年生活照护实训室的建设意义、设计理念、功能布局以及对老年照护人才培养的积极作用&#xff0c;旨在为提升老年生活照护水平提供有力的实践教学支持。 随着我国老龄化进程的加速&#xff0c;对高质量老年生活照护的需求日益增长。202…

JAVA红黑树TreeMap/TreeSet详解

Java中的红黑树是一种自平衡的二叉查找树&#xff0c;它通过特定的旋转和重新着色操作来确保树的高度大致保持在对数级别&#xff0c;从而在平均和最坏情况下都能保证查找、插入、删除等操作的时间复杂度为O(log n)。红黑树通过遵循一系列的性质来维持其平衡&#xff1a; 红黑…

培训班和科班出生有什么区别

IT业的萌新来啦 每到毕业季 总有大量萌新走进职场 IT圈子的程序员 有的是科班出生 比如 计算机科学与技术、软件工程、大数据技术 有的是相关专业出生的 比如 信息安全、网络工程、物联网工程等等 除此之外 还有各种其他专业转行过来的 文理不限、专业不限 科班出生…

【在Linux世界中追寻伟大的One Piece】IO基础

目录 1 -> 回顾 1.1 -> 回顾C文件接口 1.2 -> 总结 2 -> 系统文件I/O 3 -> 接口介绍 3.1 -> open 3.2 -> open函数返回值 3.3 -> 文件描述符fd 4 -> 0 & 1 & 2 5 -> 文件描述符的分配规则 6 -> 重定向 7 -> 使用dup2系…

运维开发——局域网SSH访问服务器与应用

摘要 本博文主要介绍局域网SSH访问登陆虚拟机和及其应用相关配置操作。 1. 局域网SSH访问登陆虚拟机 目标&#xff1a;在局域网内A电脑使用SSH登陆B电脑上虚拟机的服务器。 前提条件:B电脑为宿主机&#xff0c;可以正常使用ssh访问虚拟机服务器&#xff0c;虚拟机网络连接方…

WPS宏实现表格合并功能

把文件夹中N个表格Sheet1页的数据合并成一个新的表格 function 合并表格() { //合并文件为C盘下面名为test的文件夹 var folderPath "C:\\test"; var fileName Dir(folderPath "\\*.*"); if(fileName ""){ ale…

不同关键字的原子性、可见性、有序性之间的比较

一、多线程中有三个非常重要的特性 1. 原子性 在一次或者多次操作时&#xff0c;要么所有操作都被执行&#xff0c;要么所有操作都不执行 2. 有序性 程序执行的顺序按照代码的先后顺序执行&#xff0c;没有进行优化和顺序调整。 为了提高程序的运行效率&#xff0c;Java可能在…