安卓渐变的背景框实现
安卓渐变的背景框实现
- 1.背景
- 实现方法
- 1.利用PorterDuffXfermode进行图层的混合,这是最推荐的方法,也是最有效的。
- 2.利用canvas裁剪实现,这个方法有个缺陷,就是圆角会出现毛边,也就是锯齿。
- 3.利用layer绘制边框
1.背景
万恶的设计小姐姐又来搞事情啦,你说好好的设计一个纯色的背景框框不好嘛,非要把一个框框弄成渐变的,如果不拿出放大镜估计没几个人能看出来它是渐变的。来,我让你看看是啥样
框子是从左到右渐变的,设计应该是做了一个底图,然后上面盖了一个白色圆角矩形。那么我们该怎么去实现它呢?
实现方法
下面介绍三种实现它的方法。先贴上源码地址,大家记得给个star
https://github.com/stramChen/AndroidGradientBorderDrawable.git
1.利用PorterDuffXfermode进行图层的混合,这是最推荐的方法,也是最有效的。
关于图形混合不明白的,推荐看下面的文章
https://blog.csdn.net/iispring/article/details/50472485
实现思路大致就是先在canvas上绘制一个渐变的圆角矩形,然后再利用clear混合模式在原矩形中间绘制一个较小的圆角矩形将中间的颜色擦除,即中间绘制的颜色和原颜色会混合成透明色,这样就能达到渐变框框的效果了,是不是很容易。废话不多说,直接上代码。
/*** @des: 渐变背景边框* @author: 569133338@qq.com* @date: 2023/2/23 16:19*/
public class BorderDrawable extends Drawable {public int mLeftBorderWidth = 0;public int mRightBorderWidth = 0;public int mTopBorderWidth = 0;public int mBottomBorderWidth = 0;public float mBorderRadius =0;public float[] mBorderRadii;Path mOuterPath = new Path();Path mInnerPath = new Path();private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);private Shader mShader;private int mColor;private int[] mColors;private Integer mWidth;private Integer mHeight;private RectF mRectF;public BorderDrawable(int borderWidth) {this(borderWidth,borderWidth,borderWidth,borderWidth);}public void setCornerRadii(@Nullable float[] radii) {this.mBorderRadii = radii;}public void setCornerRadius(float radius) {this.mBorderRadius = radius;}public void setColor(int color){mColor = color;mPaint.setColor(mColor);}public void setColors(int[] colors){mColors = colors;}public BorderDrawable(int leftBorderWidth, int rightBorderWidth, int topBorderWidth, int bottomBorderWidth) {mLeftBorderWidth = leftBorderWidth;mRightBorderWidth = rightBorderWidth;mTopBorderWidth = topBorderWidth;mBottomBorderWidth = bottomBorderWidth;}@Overridepublic void draw(Canvas canvas) {int width = getBounds().width();int height = getBounds().height();if(mWidth == null || mHeight == null || mWidth != width || mHeight != height){mOuterPath.reset();mInnerPath.reset();if(Build.VERSION.SDK_INT >= 21){if(mBorderRadii != null){mOuterPath.addRoundRect(0,0,width,height,mBorderRadii, Path.Direction.CW);mInnerPath.addRoundRect(mLeftBorderWidth,mTopBorderWidth,width-mRightBorderWidth,height-mBottomBorderWidth,mBorderRadii, Path.Direction.CW);}else {mOuterPath.addRoundRect(0,0,width,height,mBorderRadius,mBorderRadius, Path.Direction.CW);mInnerPath.addRoundRect(mLeftBorderWidth,mTopBorderWidth,width-mRightBorderWidth,height-mBottomBorderWidth,mBorderRadius,mBorderRadius, Path.Direction.CW);}}else {if(mBorderRadii != null){mOuterPath.addRoundRect(new RectF(0,0,width,height),mBorderRadii, Path.Direction.CW);mInnerPath.addRoundRect(new RectF(mLeftBorderWidth,mTopBorderWidth,width-mRightBorderWidth,height-mBottomBorderWidth),mBorderRadii, Path.Direction.CW);}else {mOuterPath.addRoundRect(new RectF(0,0,width,height),mBorderRadius,mBorderRadius, Path.Direction.CW);mInnerPath.addRoundRect(new RectF(mLeftBorderWidth,mTopBorderWidth,width-mRightBorderWidth,height-mBottomBorderWidth),mBorderRadius,mBorderRadius, Path.Direction.CW);}}if(null != mColors){mShader = new LinearGradient(0, 0, width, 0,mColors, null, Shader.TileMode.REPEAT);mPaint.setShader(mShader);}mRectF = new RectF(0,0,width,height);mWidth = width;mHeight = height;}int layerId = canvas.saveLayer(mRectF, null, Canvas.ALL_SAVE_FLAG);canvas.drawPath(mOuterPath,mPaint);mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));canvas.drawPath(mInnerPath,mPaint);mPaint.setXfermode(null);canvas.restoreToCount(layerId);}@Overridepublic void setAlpha(int alpha) {}@Overridepublic void setColorFilter(@Nullable ColorFilter colorFilter) {}@Overridepublic int getOpacity() {return PixelFormat.UNKNOWN;}
}
使用方法也很简单
int[] colors = { Color.parseColor("#C084FF"), Color.parseColor("#8040FF") };//初始化并设置四个边框的宽度BorderDrawable borderDrawable = new BorderDrawable(5,5,5,30);//设置渐变色borderDrawable.setColors(colors);//设置圆角大小borderDrawable.setCornerRadius(20);//将设置好的,放到放到view里面即可view.setBackground(borderDrawable);
2.利用canvas裁剪实现,这个方法有个缺陷,就是圆角会出现毛边,也就是锯齿。
这个方法的思路基本上同上面一致,我们可以直接继承GradientDrawable来绘制外层的渐变背景,然后把颜色混合变成从原矩形中间进行画布的裁剪,把中间的画布给裁剪掉,这样不就只剩下边框了吗,哈哈哈。废话不多说,直接上代码啊。
/*** @des: 渐变背景边框* @author: 569133338@qq.com* @date: 2023/2/23 16:19*/
public class BorderDrawable2 extends GradientDrawable {public int mLeftBorderWidth = 0;public int mRightBorderWidth = 0;public int mTopBorderWidth = 0;public int mBottomBorderWidth = 0;public float mBorderRadius =0;public float[] mBorderRadii;Path mPath = new Path();public BorderDrawable2(int borderWidth) {this(borderWidth,borderWidth,borderWidth,borderWidth);}@Overridepublic void setCornerRadii(@Nullable float[] radii) {this.mBorderRadii = radii;super.setCornerRadii(radii);}@Overridepublic void setCornerRadius(float radius) {this.mBorderRadius = radius;super.setCornerRadius(radius);}public BorderDrawable2(int leftBorderWidth, int rightBorderWidth, int topBorderWidth, int bottomBorderWidth) {mLeftBorderWidth = leftBorderWidth;mRightBorderWidth = rightBorderWidth;mTopBorderWidth = topBorderWidth;mBottomBorderWidth = bottomBorderWidth;}@Overridepublic void draw(Canvas canvas) {int width = getBounds().width();int height = getBounds().height();if(Build.VERSION.SDK_INT >= 21){if(mBorderRadii != null){mPath.addRoundRect(mLeftBorderWidth,mTopBorderWidth,width-mRightBorderWidth,height-mBottomBorderWidth,mBorderRadii, Path.Direction.CW);}else {mPath.addRoundRect(mLeftBorderWidth,mTopBorderWidth,width-mRightBorderWidth,height-mBottomBorderWidth,mBorderRadius,mBorderRadius, Path.Direction.CW);}}else{if(mBorderRadii != null){mPath.addRoundRect(new RectF(mLeftBorderWidth,mTopBorderWidth,width-mRightBorderWidth,height-mBottomBorderWidth),mBorderRadii, Path.Direction.CW);}else {mPath.addRoundRect(new RectF(mLeftBorderWidth,mTopBorderWidth,width-mRightBorderWidth,height-mBottomBorderWidth),mBorderRadius,mBorderRadius, Path.Direction.CW);}}canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG|Paint.ANTI_ALIAS_FLAG));canvas.clipPath(mPath, Region.Op.DIFFERENCE);super.draw(canvas);}
}
使用方法也一如既往的简单
int[] colors = { Color.parseColor("#C084FF"), Color.parseColor("#8040FF") };//初始化并设置四个边框的宽度BorderDrawable2 borderDrawable2 = new BorderDrawable2(5,5,5,30);//设置渐变方向borderDrawable2.setOrientation(GradientDrawable.Orientation.LEFT_RIGHT);//设置渐变色borderDrawable2.setColors(colors);//设置圆角大小borderDrawable2.setCornerRadius(20);//将设置好的,放到放到view里面即可view.setBackground(borderDrawable2);
3.利用layer绘制边框
这种方法网上有一大堆教程,这里就不再赘述了,基本思路就是利用layer的两层item来实现,外层先绘制整体的背景色,内层比外层小一些像素,并盖在外层即可实现边框的效果。但这种实现方式有一种很大的缺陷,就是它不是真正意义上的边框,因为内层无法是透明的,如果是透明的,那么外层的颜色就露出来了,所以内层必须要用一个和整体控件一致的颜色来盖在上面,因此并不推荐这种方法。
好了,就写到这,祝大家天天开心。
相关文章:

安卓渐变的背景框实现
安卓渐变的背景框实现1.背景实现方法1.利用PorterDuffXfermode进行图层的混合,这是最推荐的方法,也是最有效的。2.利用canvas裁剪实现,这个方法有个缺陷,就是圆角会出现毛边,也就是锯齿。3.利用layer绘制边框1.背景 万…...

【拳打蓝桥杯】算法前置课——时间复杂度与空间复杂度
文章目录前言为什么需要复杂度分析?大O复杂度表示法时间复杂度分析几种常见时间复杂度实例分析空间复杂度分析内容小结最后说一句🐱🐉作者简介:大家好,我是黑洞晓威,一名大二学生,希望和大家一…...

vite中动态引入图片,打包之后找不到图片地址?
一般来说项目中我们集中存放图片,然后希望在页面中直接引入! 更好的就是直接在模板中调用一个函数 然后传入图片的名字就可以显示出来 事实上确实可以办到,我们用到了一个 new URL import.meta.url这俩个东西 再src目录下 static 下创建一…...

Docker 常用命令大全
目录 一、Docker (一)Docker基础命令 (二)docker镜像命令 (三)docker容器命令 (四)docker运维命令 一、Docker 容器是一种虚拟化技术,容器是镜像实例…...

React项目规范:目录结构、根目录别名、CSS重置、路由、redux、二次封装axios
React项目(一)一、创建项目二、目录结构三、craco配置别名并安装less1.craco安装2.配置别名3.安装less四、CSS样式重置五、配置路由六、配置Redux1.创建大仓库2.创建小仓库(1)方式1:RTK(2)方式2…...
SystemVerilog 教程第一章:简介
SystemVerilog 教程像 Verilog 和 VHDL 之类的硬件描述语言 (HDL) 主要用于描述硬件行为,以便将其转换为由组合门电路和时序元件组成的数字块。为了验证 HDL 中的硬件描述正确无误,就需要具有更多功能特性的面向对象的编程语言 (OOP) 来支持复杂的测试过…...

【Java|基础篇】逻辑控制-顺序结构、分支结构和循环结构
文章目录顺序结构分支结构if单分支语句if else双分支语句if else if else多分支语句switch语句循环语句for循环while循环do while循环continuebreak总结顺序结构 顺序结构是指代码按照从上往下的顺序依次执行 分支结构 选择语句是条件成立时,才会执行的语句.共有三种.分为是if…...

【数据挖掘实战】——家用电器用户行为分析及事件识别(BP神经网络)
项目地址:Datamining_project: 数据挖掘实战项目代码 目录 一、背景和挖掘目标 1、问题背景 2、原始数据 3、挖掘目标 二、分析方法与过程 1、初步分析 2、总体流程 第一步:数据抽取 第二步:探索分析 第三步:数据的预处…...
Kmeans聚类算法-python
import random import pandas as pd import numpy as np import matplotlib.pyplot as plt # 计算欧拉距离 def calcDis(dataSet, centroids, k): clalist[] for data in dataSet: diff np.tile(data, (k, 1)) - centroids #相减 (np.tile(a,(2,1))就是把…...
Linux|奇怪的知识|locate命令---文件管理小工具
前言: Linux的命令是非常多的,有一些冷门的命令,虽然很少用,但可能会有意想不到的功能,例如,本文将要介绍的locate命令。 (平常很少会想到使用此命令,find命令使用的更多,偶然想起…...
Cadence Allegro 导出Function Pin Report报告详解
⏪《上一篇》 🏡《上级目录》 ⏩《下一篇》 目录 1,概述2,Function Pin Reportt作用3,Function Pin Report示例4,Function Pin Report导出方法4.1,方法14.2,方法2B站关注“硬小二”浏览更多演示视频 1,概述...
蓝桥杯2018年第九题-缩位求和
题目:在电子计算机普及以前,人们经常用一个粗略的方法来验算四则运算是否正确。比如:248 * 15 3720把乘数和被乘数分别逐位求和,如果是多位数再逐位求和,直到是1位数,得2 4 8 14 > 1 4 5;1 5 65…...

基于Yolv5s的口罩检测
1.Yolov5算法原理和网络结构 YOLOv5按照网络深度和网络宽度的大小,可以分为YO-LOv5s、YOLOv5m、YOLOv5l、YOLOv5x。本文使用YOLOv5s,它的网络结构最为小巧,同时图像推理速度最快达0.007s。YO-LOv5的网络结构主要由四部分组成,分别…...

Linux基本命令
Linux基本命令Linux的目录结构Linux命令入门目录切换相关命令(cd/pwd)相对路径、绝对路径和特殊路径符创建目录命令(mkdir)文件操作命令part1 (touch、cat、more)文件操作命令part2 (cp、mv、rm)查找命令 (which、find…...
云原生场景下的安全左移
本博客地址:https://security.blog.csdn.net/article/details/129430859 一、安全左移概述 安全左移需要考虑开发安全、软件供应链安全、镜像仓库、配置核查这四个部分。 首先是开发安全,安全团队需要关注代码漏洞,比如使用代码检查工具进…...
mysql面试经典问题
文章目录 1. 能说下myisam 和 innodb的区别吗?2. 说下mysql的索引有哪些吧,聚簇和非聚簇索引又是什么?3. 那你知道什么是覆盖索引和回表吗?4. 锁的类型有哪些呢5. 你能说下事务的基本特性和隔离级别吗?6. 那ACID靠什么保证的呢?7. 那你说说什么是幻读,什么是MVCC?幻读什…...

微信小程序|基于小程序+C#制作一个考试答题小程序
基于小程序+C#制作一个考试答题小程序打破传统线下考试答题的边界线问题,使考试不用再局限与某个统一的场所,只要有设备,哪里都能考试。 一、小程序...
【1605. 给定行和列的和求可行矩阵】
来源:力扣(LeetCode) 描述: 给你两个非负整数数组 rowSum 和 colSum ,其中 rowSum[i] 是二维矩阵中第 i 行元素的和, colSum[j] 是第 j 列元素的和。换言之你不知道矩阵里的每个元素,但是你知…...

Linux命令之nano命令
一、nano命令简介 nano是一个小型、免费、友好的编辑器,旨在取代非免费Pine包中的默认编辑器Pico。nano不仅复制了Pico的外观,还实现了Pico中一些缺失(或默认禁用)的功能,例如“搜索和替换”和“转到行号和列号”。nan…...
IT项目管理(作业1)
一.单选题(共12题,100.0分) 1.以下哪项是项目的一个实例?( ) A、改进现有的业务流程或程序B、为公司运营提供信息技术支持C、批量生产一种新近开发出来的家用电冰箱D、管理一个公司 我的答案:A 2.下列哪项不能成为项目结束的理由?( ) A…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...

NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...

MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...