当前位置: 首页 > news >正文

安卓渐变的背景框实现

安卓渐变的背景框实现

  • 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…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...