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
如果需要做一个自定义的波浪效果的进度条,裁剪图片,对ImageView的图片进行裁剪,比如下面2张图,如何实现? 先看下面的效果,看到其实只需要对第一张高亮的图片进行处理即可,灰色状态的作为背景图。…...
Linux课程____shell脚本应用
:一、认识shell 常用解释器 Bash , ksh , csh 登陆后默认使用shell,一般为/bin/bash,不同的指令,运行的环境也不同 二、 编写简单脚本并使用 # vim /frist.sh //编写脚本文件,简单内容 #!/bin/bash …...
设计模式12--组合模式
定义 案例一 案例二 优缺点...
【微服务】软件架构的演变之路
目录 单体式架构的时代单体式架构(Monolithic)优点缺点适用场景单体式架构面临诸多问题1.宽带提速,网民增多2.Web2.0时代的特点问题描述优化方向 集群优点缺点适用场景搭建集群后面临诸多问题用户请求问题用户的登录信息数据查询 改进后的架构 垂直架构优点缺点 分布…...
安全算法 - 加密算法
加密算法是一种在信息安全领域中广泛应用的算法,能够将数据进行加密转换,以保证数据的保密性和安全性。 它具有保密性、对称加密和非对称加密、密钥管理、数据完整性和认证等重要特点和应用。 加密算法可以分为对称加密和非对称加密两种类型࿱…...
安全算法 - 国密算法
国密算法是中国自主研发的密码算法体系,包括对称加密算法、非对称加密算法和哈希算法。其中,国密算法采用SM4作为对称加密算法,SM2作为非对称加密算法,以及SM3作为哈希算法。国密算法在信息安全领域具有重要意义和广泛应用&#x…...
蓝桥杯2014年第十三届省赛真题-武功秘籍
一、题目 武功秘籍 小明到X山洞探险,捡到一本有破损的武功秘籍(2000多页!当然是伪造的)。他注意到:书的第10页和第11页在同一张纸上,但第11页和第12页不在同一张纸上。 小明只想练习该书的第81页到第92页的…...
Could not initialize class java.awt.Font
项目场景: 项目场景:java项目在web端导出Excel、Word、PDF等文档 问题描述 在Windows系统中开发以及运行文件导出正常,单机部署到Linux中或者使用docker部署后,导出报错。 异常: eleasing transactional SqlSession…...
Mysql or与in的区别
创建一个表格 内涵一千万条数据 这张表中,只有id有建立索引,且其余都没有 测试1:使用or的情况下,根据主键进行查询 可以看到根据主键id进行or查询 花费了30-114毫秒,后面30多毫秒可能是因为Mysql的Buffer Pool缓冲池的…...
STM32——USART
一、通信 1.1通信是什么; 通信是将一个设备的数据发送到另一个设备中,从而实现硬件的扩展; 1.2通信的目的是什么; 实现硬件的扩展-在STM32中集成了很多功能,例如PWM输出,AD采集,定时器等&am…...
WebCopilot:一款功能强大的子域名枚举和安全漏洞扫描工具
关于WebCopilot WebCopilot是一款功能强大的子域名枚举和安全漏洞扫描工具,该工具能够枚举目标域名下的子域名,并使用不同的开源工具检测目标存在的安全漏洞。 工具运行机制 WebCopilot首先会使用assetsfinder、submaster、subfinder、accumt、finddom…...
HarmonyOS实战开发-如何实现一个支持加减乘除混合运算的计算器。
介绍 本篇Codelab基于基础组件、容器组件,实现一个支持加减乘除混合运算的计算器。 说明: 由于数字都是双精度浮点数,在计算机中是二进制存储数据的,因此小数和非安全整数(超过整数的安全范围[-Math.pow(2, 53)&#…...
每日OJ题_子序列dp⑥_力扣873. 最长的斐波那契子序列的长度
目录 力扣873. 最长的斐波那契子序列的长度 解析代码 力扣873. 最长的斐波那契子序列的长度 873. 最长的斐波那契子序列的长度 难度 中等 如果序列 X_1, X_2, ..., X_n 满足下列条件,就说它是 斐波那契式 的: n > 3对于所有 i 2 < n&#x…...
病毒循环Viral Loop是什么?为何能实现指数增长
一、什么是病毒循环(Viral Loop)? 病毒循环(Viral Loop)是一种机制,它推动连续的推荐以实现持续增长。 它会促使你现有的客户推荐其他人,去认识你的品牌,然后让这些新客户进一步告诉…...
下载huggingface中数据集/模型(保存到本地指定路径)
一. snapshot_download # 1.安装huggingface_hub # pip install huggingface_hubimport osfrom huggingface_hub import snapshot_downloadprint(downloading entire files...) # 注意,这种方式仍然保存在cache_dir中 snapshot_download(repo_id"ibrahimhamam…...
HarmonyOS实战开发-使用List组件实现导航与内容联动的效果。
1 卡片介绍 使用ArkTS语言,实现一个导航与内容二级联动的效果。 2 标题 二级联动(ArkTS) 3 介绍 本篇Codelab是主要介绍了如何基于List组件实现一个导航和内容的二级联动效果。样例主要包含以下功能: 切换左侧导航ÿ…...
ArcGIS二次开发(一)——搭建开发环境以及第一个简单的ArcGIS Engine 程序
Arcgis10.2、Arcgis Engine10.2与Microsoft Visual Studio 2012的版本进行安装 1、推荐教程与安装包2、安装顺序3、安装成功测试VS新建项目可以创建ArcGIS项目,并且在VS中拖拽ArcGIS工具 4、搭建第一个简单的ArcGIS Engine 程序 ArcEngine和VS版本是有对应的&#x…...
Oracle 19c 高可用部署实战系列之Data Guard理论与实战
课程介绍 Oracle Data Guard确保企业数据的高可用性、数据保护和灾难恢复。 Oracle Data Guard提供了一组全面的服务,用于创建、维护、管理和监视一个或多个备用数据库,使生产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 中,软连接(Symbolic Link,也称为符号链接或软链接)是一…...
顺序表专题
文章目录 目录1. 数据结构相关概念1.1 什么是数据结构1.2 为什么需要数据结构 2. 顺序表的概念及结构3. 顺序表分类4. 实现动态顺序表4.1 初始化4.2 顺序表的尾部插入4.3 打印顺序表4.4 顺序表的头部插入4.5 顺序表的尾部删除4.6 顺序表的头部删除4.7 指定位置之前插入数据4.8 …...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...
