Android -- [SelfView] 自定义多色渐变背景板

Android – 自定义多色渐变背景板

前言:
Android 自带的 xml 文件内 gradient 设置渐变最多只有三种颜色,使用方便但范围受限,不能很好满足各种需求;
本款多色渐变背景板应运而生:* 1. 支持圆角模式,矩形模式;* 2. 支持线性、扫描和环形渐变,线性渐变支持0-180角度设置;* 3. 支持多种颜色设置;(E.g: #ff0000 #00ff00 #0000ff)

在这里插入图片描述

使用:
//三种效果:
<LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"android:layout_centerInParent="true"><com.nepalese.virgocomponent.view.VirgoGradientViewandroid:layout_width="160dp"android:layout_height="120dp"app:vgMode="mode_rect"app:vgRoundRadius="60dp"app:vgColors="#3f51b1 #5a55ae #7b5fac #8f6aae #a86aa4 #cc6b8e #f18271 #f3a469 #f7c978"app:vgGradientMode="gradient_linear"app:vgLinearAngle="15" /><com.nepalese.virgocomponent.view.VirgoGradientViewandroid:layout_marginStart="20dp"android:layout_width="160dp"android:layout_height="120dp"app:vgMode="mode_round"app:vgRoundRadius="15dp"app:vgColors="#3f51b1 #5a55ae #7b5fac #8f6aae #a86aa4 #cc6b8e #f18271 #f3a469 #f7c978"app:vgGradientMode="gradient_linear"app:vgLinearAngle="30" /><com.nepalese.virgocomponent.view.VirgoGradientViewandroid:layout_marginStart="20dp"android:layout_width="120dp"android:layout_height="120dp"app:vgMode="mode_round"app:vgRoundRadius="60dp"app:vgColors="#3f51b1 #5a55ae #7b5fac #8f6aae #a86aa4 #cc6b8e #f18271 #f3a469 #f7c978"app:vgGradientMode="gradient_linear"app:vgLinearAngle="45" /></LinearLayout>

码源:

1. attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources><declare-styleable name="VirgoGradientView"><attr name="vgMode" format="integer"><enum name="mode_round" value="1"/><enum name="mode_rect" value="2"/></attr><attr name="vgGradientMode" format="integer"><enum name="gradient_linear" value="1"/><enum name="gradient_sweep" value="2"/><enum name="gradient_radial" value="3"/></attr><attr name="vgLinearAngle" format="integer"/><attr name="vgRoundRadius" format="dimension|reference"/><attr name="vgColors" format="string"/></declare-styleable>
</resources>
2. VirgoGradientView.java
package com.nepalese.virgocomponent.view;import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;import androidx.annotation.Nullable;import com.nepalese.virgocomponent.R;/*** @author nepalese on 2024/10/10 10:10* @usage 多色渐变调板:* 1. 支持圆角模式,矩形模式;* 2. 支持线性、扫描和环形渐变,线性渐变支持0-180角度设置;* 3. 支持多种颜色设置;(E.g: #ff0000 #00ff00 #0000ff)*/
public class VirgoGradientView extends View {private static final String TAG = "VirgoGradientView";public static final int MODE_ROUND = 1;//圆角模式public static final int MODE_RECT = 2;//矩形模式(默认)public static final int GRADIENT_LINEAR = 1;//线性渐变public static final int GRADIENT_SWEEP = 2;//扫描渐变public static final int GRADIENT_RADIAL = 3;//环形渐变private Paint mPaint;//画笔private RectF mRectF;//画布矩形private Shader mShader;//渐变渲染private int mWidth, mHeight;//宽高private int mMode;//图形模式private int mGradientMode;//渐变模式private int mAngle;//线性渐变角度(从左->右:0-180)private int mRoundRadius;//圆角半径(仅圆角模式)private int[] mColors;//颜色组public VirgoGradientView(Context context) {this(context, null);}public VirgoGradientView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public VirgoGradientView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(attrs);}private void init(AttributeSet attrs) {String strColors;//颜色按顺序,以空格间开TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.VirgoGradientView);mMode = typedArray.getInt(R.styleable.VirgoGradientView_vgMode, MODE_RECT);mAngle = typedArray.getInt(R.styleable.VirgoGradientView_vgLinearAngle, 0);mGradientMode = typedArray.getInt(R.styleable.VirgoGradientView_vgGradientMode, GRADIENT_LINEAR);mRoundRadius = typedArray.getDimensionPixelSize(R.styleable.VirgoGradientView_vgRoundRadius, 20);strColors = typedArray.getString(R.styleable.VirgoGradientView_vgColors);typedArray.recycle();mPaint = new Paint();mPaint.setAntiAlias(true);mPaint.setDither(true);mPaint.setStyle(Paint.Style.FILL);//初始化默认颜色initColor(strColors);}private void initColor(String strColors) {if (TextUtils.isEmpty(strColors)) {strColors = "#69EACB #EACCF8 #6654F1";//默认}if (strColors.contains(" ")) {String[] colors = strColors.split(" ");mColors = new int[colors.length];for (int i = 0; i < colors.length; i++) {try {mColors[i] = Color.parseColor(colors[i]);} catch (Exception e) {mColors[i] = Color.WHITE;}}} else {//单色mColors = new int[1];try {mColors[0] = Color.parseColor(strColors);} catch (Exception e) {//格式异常Log.e(TAG, "格式异常!");mColors[0] = Color.WHITE;}}//        //彩虹色
//        mColors = new int[7];
//        mColors[0] = Color.rgb(255,0,0);
//        mColors[1] = Color.rgb(255,165,0);
//        mColors[2] = Color.rgb(255,255,0);
//        mColors[3] = Color.rgb(0,255,0);
//        mColors[4] = Color.rgb(0,127,255);
//        mColors[5] = Color.rgb(0,0,255);
//        mColors[6] = Color.rgb(139,0,255);}private void setShader() {switch (mGradientMode) {case GRADIENT_LINEAR://x0,y0,x1,y1是起始位置和渐变的结束位置//positions指定颜色数组的相对位置: [0…1], 如果传null,渐变就线性变化//角度正切值double tan = Math.tan(Math.PI * mAngle / 180);if (45 > mAngle && mAngle >= 0) {//[0,45)mShader = new LinearGradient(0, (float) ((mHeight - tan * mWidth) / 2), mWidth, (float) ((mHeight + tan * mWidth) / 2), mColors, null, Shader.TileMode.CLAMP);} else if (135 >= mAngle && mAngle >= 45) {//[45,135]if (mAngle == 90) {mShader = new LinearGradient(mWidth / 2f, 0, mWidth / 2f, mHeight, mColors, null, Shader.TileMode.CLAMP);} else {mShader = new LinearGradient((float) ((mWidth - mHeight / tan) / 2), 0, (float) ((mWidth + mHeight / tan) / 2), mHeight, mColors, null, Shader.TileMode.CLAMP);}} else if (180 >= mAngle && mAngle > 135) {mShader = new LinearGradient(mWidth, (float) ((mHeight + tan * mWidth) / 2), 0, (float) ((mHeight - tan * mWidth) / 2), mColors, null, Shader.TileMode.CLAMP);} else {//默认左 -> 右mShader = new LinearGradient(0, 0, mWidth, 0, mColors, null, Shader.TileMode.CLAMP);}break;case GRADIENT_SWEEP://cx,cy,圆的中心坐标mShader = new SweepGradient(mWidth / 2f, mHeight / 2f, mColors, null);break;case GRADIENT_RADIAL://cx,cy,中心坐标int max = Math.max(mWidth, mHeight);mShader = new RadialGradient(mWidth / 2f, mHeight / 2f, max / 2f, mColors, null, Shader.TileMode.CLAMP);break;}mPaint.setShader(mShader);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);//在measure之后, layout之前mRectF = new RectF(0, 0, w, h);mWidth = w;mHeight = h;}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);setShader();if (mMode == MODE_RECT) {//矩形canvas.drawRect(mRectF, mPaint);} else {//圆角canvas.drawRoundRect(mRectF, mRoundRadius, mRoundRadius, mPaint);}}//api//public void setmMode(int mMode) {this.mMode = mMode;}public void setmGradientMode(int mGradientMode) {this.mGradientMode = mGradientMode;}public void setmAngle(int mAngle) {this.mAngle = mAngle % 180;}public void setmRoundRadius(int mRoundRadius) {this.mRoundRadius = mRoundRadius;}//颜色种类不少于2public void setmColors(int[] mColors) {if (mColors.length < 2) {return;}this.mColors = mColors;}
}

渐变色网站:

https://webgradients.com/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1559948.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

二、IOC容器

文章目录 1. IOC的底层原理1.1 什么是IOC1.2 IOC 底层原理1.3 画图讲解 IOC 底层原理 2. IOC接口&#xff08;BeanFactory&#xff09;3. IOC 操作 Bean 管理&#xff08;概念&#xff09;3.1 什么是Bean管理3.2 Bean管理操作的两种方式 4. IOC操作 Bean 管理&#xff08;基于 …

【Redis】Set类型常用命令

目录 一. Set集合类型简介.二. 增加元素相关命令2.1 向集合中添加元素(sadd)2.2 从集合中移动元素( smove ) 三. 查询元素相关操作.3.1 查询集合中存在的所有元素.( smembers )3.2 查询集合中是否存在member( sismember ) 四. 随机获取集合中的元素4.1 随机获取集合中的n个元素…

基于单片机的穿戴式泳池遇险紧急呼救系统的设计

本计基于单片机的穿戴式泳池遇险紧急呼救系统装置。该装置采用STC12C5A60S2单片机与心率检测模块MAX30102的一体化脉冲血氧分析仪和心率监测器&#xff0c;对人体的心跳进行了实时检测。该装置由发送端和接收端两部分组成&#xff0c;中间由LORA无线通信模块进行数据传输&#…

C语言刷题 LeetCode 30天挑战 (十)Stack 栈 (MinStack)

这个题目要求你设计一个特殊的栈&#xff08;MinStack&#xff09;&#xff0c;不仅要具备普通栈的基本功能&#xff08;push、pop 和 top&#xff09;&#xff0c;还要能够在常数时间内&#xff08;O(1) 时间复杂度&#xff09;获取栈中的最小元素&#xff08;getMin&#xff…

curl执行报【先没有那个文件或目录】解决办法

开发微信发过了curl命令后&#xff0c;执行报错 是空格导致的&#xff0c;解决办法是打开下面网址重新输入空格即可 在线curl命令转代码 删除这个空格 重新输入空格

『网络游戏』服务器向客户端分发消息【20】

对服务器添加System引用 修改脚本&#xff1a;LoginSys.cs 修改脚本&#xff1a;NetSvc.cs 修改脚本&#xff1a;ServerSession.cs 修改脚本&#xff1a;GameMsg.cs 修改脚本&#xff1a;MsgPack.cs 修改脚本&#xff1a;LoginSys.cs 修改脚本&#xff1a;ServerRoot.cs 修改脚…

java随机生成数学算式

生成随机数学算式可谓是计算机领域的一个经典的问题, 本文使用JFrame,JButton,JTextField等java图形化工具,生成一个可以随机切换题目,可以实现计时功能的一个图形化界面 源代码展示 randomMath类 package login;import javax.swing.*; import java.awt.*; import java.awt.e…

运筹说 第126期 | 存储论经典例题讲解——随机存储模型

通过上一期&#xff0c;我们已经学习了确定型存储论模型在经济管理中的应用&#xff0c;但其忽略了现实中的随机性和不确定性因素&#xff0c;本期小编选择了一些考虑不确定因素的随机存储模型的典型例题&#xff0c;进行详细讲解。 单周期的随机型存储模型 单周期的随机型存储…

基于STM32的“Flash闪存”基础 及 “SD NAND Flash”测试例程

文章目录 一、“FLASH闪存”是什么&#xff1f; 简介 分类 特点 虚拟化 二、SD NAND Flash 概述 引脚分配 数据传输模式 SD NAND寄存器 通电图 参考设计 三、STM32测试例程 本篇除了对flash闪存进行简单介绍外&#xff0c;另给读者推荐一种我本人也在用的小容量闪…

STM32 USB CUBEMX

开发背景 使用的平台&#xff1a;STM32H750 注意事项 时钟必须是48MHZ&#xff0c;其它都不行 2. 将默认任务的堆栈设大一点 如果使用操作系统&#xff0c;USB任务跑在默认任务里&#xff0c;因此需要设置默认任务的堆栈缓存是直接定义的全局变量&#xff0c;需要设置编译器…

【windows Server 2012】把我的电脑放在桌面

WinR 打开命令输入框 输入 rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,0

Vue+Vant实现7天日历展示,并在切换日期时实时变换

效果图&#xff1a; 主要使用 moment.js 插件完成 HTML部分 <div class"day-content"><div class"day-content-t"><div>{{ monthVal }}</div><div click"onCalendar()">更多>></div></div><…

月入8.3K,电子厂普工转行网优,每个人都可以是潜力股!

今天主人公只有22岁&#xff0c;大专学历&#xff0c;毕业之后一直在芯片厂从事流水线工作&#xff0c;枯燥烦闷的生活让他下定决心转行&#xff0c;目前收到一份薪资8300元的offer&#xff0c;让我们一起来看看他的故事~ 1 为什么选择网优行业&#xff1f; 大学我学的软件技术…

DAY6 面向对象

概念 对象是一种特殊的数据结构&#xff0c;可以用来记住一个事物的数据&#xff0c;从而代表该事物&#xff0c;可以理解为一个模板表&#xff0c;总而言之万物皆对象&#xff0c;比如一个人、一个物体等。 怎么创建对象 先设计对象的模板&#xff0c;也就是对象的设计图&a…

影视飓风全平台下架引思:录屏分辨率与码率科普及实用软件推荐

在影视飓风10月8日发布视频《清晰度不如4年前!视频变糊是你的错觉吗》后&#xff0c;引发了很多关于视频清晰度的讨论。 有知乎用户总结提出现在在线视频被降画质的几个点&#xff1a;一是原始视频上传到服务器就被压缩&#xff0c;虽分辨率看似不变&#xff0c;但如 H.265 等高…

【SQL】收入更高的员工

目录 语法 需求 示例 分析 代码 语法 FROM Employee a, Employee b 两个表之间笛卡尔积&#xff08;Cartesian product&#xff09;的形式&#xff0c;用了逗号分隔的连接&#xff08;comma-separated join&#xff09;&#xff0c;这是早期SQL语法中用于连接表的一种方式…

TikTok 伪装度分析:揭开社交媒体的真实面纱

在现代社交媒体中&#xff0c;TikTok凭借其短视频的形式和算法推荐的机制&#xff0c;迅速吸引了大量用户。然而&#xff0c;随着用户基数的扩大&#xff0c;平台上的内容呈现出多样化的趋势&#xff0c;而“伪装度”这一概念也逐渐成为我们分析TikTok内容质量和用户行为的重要…

SpringBoot使用esayExcel根据模板导出excel

1、依赖 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.3</version></dependency> 2、模板 3、实体类 package com.skybird.iot.addons.productionManagement.qualityTesting…

泰始明昌文旅:如何打造真正的文旅爆品体系

泰始明昌文旅&#xff1a;如何打造真正的文旅爆品体系 泰始明昌文旅&#xff1a;如何打造真正的爆品体系 关键词&#xff1a;泰始明昌文旅,文旅爆品,核心卖点,用户痛点,项目特点,对手弱点,爆品体系,爆品品类,结构化,品质,价值链接,生态体系,营销推广,持续创新 摘要&#xff…

接口和多态

接口 概念 接口是功能的集合&#xff0c;它同样是一种引用数据类型&#xff0c;可以把接口看作抽象类更为抽象的 "类"。 接口只描述所应该具备的功能方法&#xff0c;但是没有具体的方法实现&#xff0c;即接口中具有的都是抽象方法&#xff0c;这些抽象方法的实现是…