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

Android裁剪图片为波浪形或者曲线形的ImageView

如果需要做一个自定义的波浪效果的进度条,裁剪图片,对ImageView的图片进行裁剪,比如下面2张图,如何实现?

高亮

先看下面的效果,看到其实只需要对第一张高亮的图片进行处理即可,灰色状态的作为背景图。

1、实现原理

这里首先想到的是自定义View,在Android中,使用二阶贝塞尔曲线可以实现我们想要的效果,关键的API就是Path的rQuadTo()方法。

        path.reset()path.moveTo(startX, startY)path.quadTo(currentX, currentY, endX, endY)canvas.drawPath(path, curvePaint)

startX和startY,endX和endY为两个固定点,currentX和currentY就是控制点,通过改变控制点的位置来改变二阶贝塞尔曲线的形状。

a点和b点就是固定点,c点是控制点,我们可以改变c点的位置来改变曲线的形状。

在Android中,使用cubicTo来实现三阶贝塞尔。上面的需求方案使用二阶即可实现,三阶的可以自行了解。

2、事例分析

首先可以通过自定义一个贝赛尔曲线来了解一下:

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;public class BezierCurveView extends View {private Paint paint;private Path path;public BezierCurveView(Context context) {super(context);init();}public BezierCurveView(Context context, AttributeSet attrs) {super(context, attrs);init();}public BezierCurveView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {paint = new Paint();paint.setColor(Color.BLUE);paint.setStyle(Paint.Style.STROKE);paint.setStrokeWidth(5f);path = new Path();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);int height = getHeight();int width = getWidth();float dx = width / 4f;float dy = height / 4f;path.reset();path.moveTo(0, height / 2f); // 起点path.rQuadTo(dx, -dy, 2 * dx, 0f); // 控制点、终点path.rQuadTo(dx, dy, 2 * dx, 0f); // 控制点、终点path.rQuadTo(dx, -dy, 2 * dx, 0f); // 控制点、终点path.rQuadTo(dx, dy, 2 * dx, 0f); // 控制点、终点path.lineTo(width, height);path.lineTo(0f, height);path.close();canvas.drawPath(path, paint);}
}

要使用这个自定义View,你需要在布局文件中引用一下:

<com.example.myapp.BezierCurveViewandroid:layout_width="match_parent"android:layout_height="200dp" />

看下效果:

3、使用贝塞尔裁剪ImageView

1)自定义ImageView

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Path;
import android.util.AttributeSet;import androidx.annotation.Nullable;/*** 图片裁剪为贝赛尔曲线边缘ImageView*/
public class BezierImageView extends androidx.appcompat.widget.AppCompatImageView {private static final String TAG = "ArcImageView";public BezierImageView (Context context) {this(context, null);}public BezierImageView (Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public BezierImageView (Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);path = new Path();}private final Path path;/*** 进度值(0~100),默认100*/private int progress = 100;public void setProgress(int progress) {this.progress = progress;postInvalidate();}@Overrideprotected void onDraw(Canvas canvas) {final int width = getWidth();final int height = getHeight();float dx = width / 4f;float dy = height / 8f;float yOffset = (100 - progress) / 100f * height;float[] p1 = {0f, yOffset};float[] p2 = {dx, -dy};float[] p3 = {2 * dx, 0f};float[] p4 = {dx, dy};float[] p5 = {2 * dx, 0f};float[] p6 = {dx, -dy};float[] p7 = {2 * dx, 0f};float[] p8 = {dx, dy};float[] p9 = {2 * dx, 0f};path.reset();path.moveTo(p1[0], p1[1]);path.rQuadTo(p2[0], p2[1], p3[0], p3[1]);path.rQuadTo(p4[0], p4[1], p5[0], p5[1]);path.rQuadTo(p6[0], p6[1], p7[0], p7[1]);path.rQuadTo(p8[0], p8[1], p9[0], p9[1]);path.lineTo(width, height);path.lineTo(0f, height);path.close();canvas.clipPath(path);super.onDraw(canvas);}
}

2)如何使用?

    <com.....BezierImageView android:id="@+id/bg"android:layout_width="200dp"android:layout_height="200dp"android:layout_centerInParent="true"android:scaleType="fitCenter"android:src="@drawable/bg_cover" />
bg.setProgress(50);

直接调用setProgress()方法,传入要裁剪的百分比即可。

效果如下所示:

4、使用sin()正弦函数实现波浪/曲线效果

基于3中,直接修改onDraw()中的关键代码即可:

@Overrideprotected void onDraw(Canvas canvas) {final int width = getWidth();final int height = getHeight();// 变量描述,可自己调整:// offset:Y轴偏移量// yHeight:可控制Y轴高度(值越小百分比显示越大)// countF:控制波数(越大波数越少)// xOffset:可控制波长幅度(值越大幅度越大,越小越平缓)float offset = 0.1f, yHeight = 1.0f, countF = 60.0f, xOffset = 0.04f;// 方案1:path.moveTo(0, height);for (int i = 0; i < width; i++) {path.lineTo(i, (float) (height * ((yHeight - offset) + Math.sin(i / countF + Math.PI) * xOffset)));}path.lineTo(width, height);path.lineTo(0f, height);path.close();canvas.clipPath(path);super.onDraw(canvas);}

使用sin()函数结合lineTo()方法,同样可以实现波浪曲线效果:

相关文章:

Android裁剪图片为波浪形或者曲线形的ImageView

如果需要做一个自定义的波浪效果的进度条&#xff0c;裁剪图片&#xff0c;对ImageView的图片进行裁剪&#xff0c;比如下面2张图&#xff0c;如何实现&#xff1f; 先看下面的效果&#xff0c;看到其实只需要对第一张高亮的图片进行处理即可&#xff0c;灰色状态的作为背景图。…...

Linux课程____shell脚本应用

:一、认识shell 常用解释器 Bash , ksh , csh 登陆后默认使用shell&#xff0c;一般为/bin/bash&#xff0c;不同的指令&#xff0c;运行的环境也不同 二、 编写简单脚本并使用 # vim /frist.sh //编写脚本文件&#xff0c;简单内容 #&#xff01;/bin/bash …...

设计模式12--组合模式

定义 案例一 案例二 优缺点...

【微服务】软件架构的演变之路

目录 单体式架构的时代单体式架构(Monolithic)优点缺点适用场景单体式架构面临诸多问题1.宽带提速&#xff0c;网民增多2.Web2.0时代的特点问题描述优化方向 集群优点缺点适用场景搭建集群后面临诸多问题用户请求问题用户的登录信息数据查询 改进后的架构 垂直架构优点缺点 分布…...

安全算法 - 加密算法

加密算法是一种在信息安全领域中广泛应用的算法&#xff0c;能够将数据进行加密转换&#xff0c;以保证数据的保密性和安全性。 它具有保密性、对称加密和非对称加密、密钥管理、数据完整性和认证等重要特点和应用。 加密算法可以分为对称加密和非对称加密两种类型&#xff1…...

安全算法 - 国密算法

国密算法是中国自主研发的密码算法体系&#xff0c;包括对称加密算法、非对称加密算法和哈希算法。其中&#xff0c;国密算法采用SM4作为对称加密算法&#xff0c;SM2作为非对称加密算法&#xff0c;以及SM3作为哈希算法。国密算法在信息安全领域具有重要意义和广泛应用&#x…...

蓝桥杯2014年第十三届省赛真题-武功秘籍

一、题目 武功秘籍 小明到X山洞探险&#xff0c;捡到一本有破损的武功秘籍&#xff08;2000多页&#xff01;当然是伪造的&#xff09;。他注意到&#xff1a;书的第10页和第11页在同一张纸上&#xff0c;但第11页和第12页不在同一张纸上。 小明只想练习该书的第81页到第92页的…...

Could not initialize class java.awt.Font

项目场景&#xff1a; 项目场景&#xff1a;java项目在web端导出Excel、Word、PDF等文档 问题描述 在Windows系统中开发以及运行文件导出正常&#xff0c;单机部署到Linux中或者使用docker部署后&#xff0c;导出报错。 异常&#xff1a; eleasing transactional SqlSession…...

Mysql or与in的区别

创建一个表格 内涵一千万条数据 这张表中&#xff0c;只有id有建立索引&#xff0c;且其余都没有 测试1&#xff1a;使用or的情况下&#xff0c;根据主键进行查询 可以看到根据主键id进行or查询 花费了30-114毫秒&#xff0c;后面30多毫秒可能是因为Mysql的Buffer Pool缓冲池的…...

STM32——USART

一、通信 1.1通信是什么&#xff1b; 通信是将一个设备的数据发送到另一个设备中&#xff0c;从而实现硬件的扩展&#xff1b; 1.2通信的目的是什么&#xff1b; 实现硬件的扩展-在STM32中集成了很多功能&#xff0c;例如PWM输出&#xff0c;AD采集&#xff0c;定时器等&am…...

WebCopilot:一款功能强大的子域名枚举和安全漏洞扫描工具

关于WebCopilot WebCopilot是一款功能强大的子域名枚举和安全漏洞扫描工具&#xff0c;该工具能够枚举目标域名下的子域名&#xff0c;并使用不同的开源工具检测目标存在的安全漏洞。 工具运行机制 WebCopilot首先会使用assetsfinder、submaster、subfinder、accumt、finddom…...

HarmonyOS实战开发-如何实现一个支持加减乘除混合运算的计算器。

介绍 本篇Codelab基于基础组件、容器组件&#xff0c;实现一个支持加减乘除混合运算的计算器。 说明&#xff1a; 由于数字都是双精度浮点数&#xff0c;在计算机中是二进制存储数据的&#xff0c;因此小数和非安全整数&#xff08;超过整数的安全范围[-Math.pow(2, 53)&#…...

每日OJ题_子序列dp⑥_力扣873. 最长的斐波那契子序列的长度

目录 力扣873. 最长的斐波那契子序列的长度 解析代码 力扣873. 最长的斐波那契子序列的长度 873. 最长的斐波那契子序列的长度 难度 中等 如果序列 X_1, X_2, ..., X_n 满足下列条件&#xff0c;就说它是 斐波那契式 的&#xff1a; n > 3对于所有 i 2 < n&#x…...

病毒循环Viral Loop是什么?为何能实现指数增长

一、什么是病毒循环&#xff08;Viral Loop&#xff09;&#xff1f; 病毒循环&#xff08;Viral Loop&#xff09;是一种机制&#xff0c;它推动连续的推荐以实现持续增长。 它会促使你现有的客户推荐其他人&#xff0c;去认识你的品牌&#xff0c;然后让这些新客户进一步告诉…...

下载huggingface中数据集/模型(保存到本地指定路径)

一. snapshot_download # 1.安装huggingface_hub # pip install huggingface_hubimport osfrom huggingface_hub import snapshot_downloadprint(downloading entire files...) # 注意&#xff0c;这种方式仍然保存在cache_dir中 snapshot_download(repo_id"ibrahimhamam…...

HarmonyOS实战开发-使用List组件实现导航与内容联动的效果。

1 卡片介绍 使用ArkTS语言&#xff0c;实现一个导航与内容二级联动的效果。 2 标题 二级联动&#xff08;ArkTS&#xff09; 3 介绍 本篇Codelab是主要介绍了如何基于List组件实现一个导航和内容的二级联动效果。样例主要包含以下功能&#xff1a; 切换左侧导航&#xff…...

ArcGIS二次开发(一)——搭建开发环境以及第一个简单的ArcGIS Engine 程序

Arcgis10.2、Arcgis Engine10.2与Microsoft Visual Studio 2012的版本进行安装 1、推荐教程与安装包2、安装顺序3、安装成功测试VS新建项目可以创建ArcGIS项目&#xff0c;并且在VS中拖拽ArcGIS工具 4、搭建第一个简单的ArcGIS Engine 程序 ArcEngine和VS版本是有对应的&#x…...

Oracle 19c 高可用部署实战系列之Data Guard理论与实战

课程介绍 Oracle Data Guard确保企业数据的高可用性、数据保护和灾难恢复。 Oracle Data Guard提供了一组全面的服务&#xff0c;用于创建、维护、管理和监视一个或多个备用数据库&#xff0c;使生产Oracle数据库能够在灾难和数据损坏中幸存下来。Oracle Data Guard将这些备用…...

ubuntu常用记录

常用命令 ps aux |grep ... pip show pkgname nvidia-smi -l du -sh * df -h head -n 10 file.txt htop sudo apt install package_name kill process_id 软链接 在 Linux 中&#xff0c;软连接&#xff08;Symbolic Link&#xff0c;也称为符号链接或软链接&#xff09;是一…...

顺序表专题

文章目录 目录1. 数据结构相关概念1.1 什么是数据结构1.2 为什么需要数据结构 2. 顺序表的概念及结构3. 顺序表分类4. 实现动态顺序表4.1 初始化4.2 顺序表的尾部插入4.3 打印顺序表4.4 顺序表的头部插入4.5 顺序表的尾部删除4.6 顺序表的头部删除4.7 指定位置之前插入数据4.8 …...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

NPOI操作EXCEL文件 ——CAD C# 二次开发

缺点:dll.版本容易加载错误。CAD加载插件时&#xff0c;没有加载所有类库。插件运行过程中用到某个类库&#xff0c;会从CAD的安装目录找&#xff0c;找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库&#xff0c;就用插件程序加载进…...

API网关Kong的鉴权与限流:高并发场景下的核心实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中&#xff0c;API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关&#xff0c;Kong凭借其插件化架构…...

Python网页自动化Selenium中文文档

1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API&#xff0c;让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API&#xff0c;你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理

在城市的某个角落&#xff0c;一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延&#xff0c;滚滚浓烟弥漫开来&#xff0c;周围群众的生命财产安全受到严重威胁。就在这千钧一发之际&#xff0c;消防救援队伍迅速行动&#xff0c;而豪越科技消防一体化安全管控平台构建的消防“…...

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践

在 Kubernetes 集群中&#xff0c;如何在保障应用高可用的同时有效地管理资源&#xff0c;一直是运维人员和开发者关注的重点。随着微服务架构的普及&#xff0c;集群内各个服务的负载波动日趋明显&#xff0c;传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...