一个简单的例子,说明Matrix类的妙用
在Android、前端或者别的平台的软件开发中,有时会遇到类似如下需求:
- 将某个图片显示到指定的区域;
- 要求不改变图片本身的宽高比,进行缩放;
- 要求最大限度的居中填充到显示区域。
以下示意图可以简单描绘该需求

以Android平台为例,如果我们的目标显示对象为Imageview,那么很简单,只要如下设置即可
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:scaleType="fitCenter"android:src="@drawable/image" />
其中实现以上需求最关键的代码为 android:scaleType=“fitCenter”。感兴趣的同学可以去查看源码,探究scaleType属性设置为fitCenter之后底层代码是如何实现的。
但是,如果我们的显示区域只是一个自定义view中特定坐标的区域,如(x1, y1, x2, y2)的矩形区域。不了解Matrix的同学,可能第一反应就是根据图片本身的宽高以及目标显示区域的宽高,去计算一个缩放比,如下代码:
public void drawBitmapFillRegion(Canvas canvas, Bitmap bitmap, Rect targetRect) {// 目标区域的宽高int targetWidth = targetRect.width();int targetHeight = targetRect.height();// Bitmap 的宽高int bitmapWidth = bitmap.getWidth();int bitmapHeight = bitmap.getHeight();// 计算宽高比float scale = Math.max((float) targetWidth / bitmapWidth, (float) targetHeight / bitmapHeight);// 计算缩放后的宽高float scaledWidth = scale * bitmapWidth;float scaledHeight = scale * bitmapHeight;// 计算偏移float offsetX = targetRect.left + (targetWidth - scaledWidth) / 2;float offsetY = targetRect.top + (targetHeight - scaledHeight) / 2;// 设置 Matrix 进行缩放和平移Matrix matrix = new Matrix();matrix.setScale(scale, scale);matrix.postTranslate(offsetX, offsetY);// 绘制 Bitmapcanvas.drawBitmap(bitmap, matrix, null);
}
但是,当你深入研究Matrix中的方法,你就会发现,根本不需要这么麻烦,以下几句即可简单完美实现
public void drawBitmapFillRegion(Canvas canvas, Bitmap bitmap) {// 定义源矩形,即 Bitmap 的边界RectF srcRect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());RectF srcRect = new RectF(x1, y1, x2, y2);// 设置 Matrix 进行缩放和平移Matrix matrix = new Matrix();matrix.setRectToRect(srcRect, targetRect, Matrix.ScaleToFit.CENTER);// 绘制 Bitmapcanvas.drawBitmap(bitmap, matrix, null);
}
其中最关键的方法便是 setRectToRect,它可以计算出将某个矩形映射到另外一个矩形所需的矩阵,并将这个矩阵赋值给调用方。其实,Matrix还有很多使用强大的接口,感兴趣的同学可以系统深入探索下。尤其是工作学习当中涉及到图片缩放、裁剪、旋转、平移等操作的同学,更应该学习下。
相关文章:
一个简单的例子,说明Matrix类的妙用
在Android、前端或者别的平台的软件开发中,有时会遇到类似如下需求: 将某个图片显示到指定的区域;要求不改变图片本身的宽高比,进行缩放;要求最大限度的居中填充到显示区域。 以下示意图可以简单描绘该需求 以Androi…...
【C++】类和对象(四):析构函数
大家好,我是苏貝,本篇博客带大家了解C的析构函数,如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️ 目录 1. 概念2. 特性 1. 概念 通过前面构造函数的学习,我们知道一个对象是怎么来的…...
linux中各目录作用及介绍
目录 1 /usr 1 /usr /usr 是 Unix-like 操作系统中的一个重要目录之一,代表可共享的用户资源(User System Resources)或 Unix Software Resource(UNIX 软件资源)。 /usr 目录通常包含了系统的许多可共享资源…...
v4.7版本使用线下付款方式不给管理员发送新订单通知问题修复
在app/api/controller/v1/order/StoreOrderController.php文件中,将红框内的代码注释,加上绿框的代码即可修复 if ($this->services->setOrderTypePayOffline($order[order_id])) {event(NoticeListener, [$order, admin_pay_success_code]);retur…...
vue3中mitt和pinia的区别和主要用途,是否有可重合的部分?
在 Vue 中,Mitt 和 Pinia 是两个不同的工具,它们的主要用途和功能有所不同,但在某些方面也存在重合的部分。 区别 Mitt: Mitt 是一个简单而强大的事件总线库,用于在组件之间进行事件的发布和订阅。 它提供了一种简洁…...
飞书文档解除复制限制
解除飞书文档没有编辑器权限限制复制功能方法 方法一:使用插件 方法二: 通过调试工具删除所有的copy事件 使用插件 缺点: 只有markdown格式,如果需要其他格式需要再通过Typora等markdown编辑器转pdf,word等格式 安装插件 Cloud Do…...
vue3中ref和reactive的用法,区别和优缺点,以及使用场景
写在前头: reactive定义的数据只能修改里面的属性,不能将整个数据替换,实在要替换请使用 Object.assign(obj1, obj2);举个例子 这种写法无法直接改变obj1 let obj1 reactive({name: 猫,age: 2, });obj1 {name: 猪,age: 2, } 正确的写法…...
电脑技巧:Rufus——最佳USB启动盘制作工具指南
目录 一、功能强大,兼容性广泛 二、界面友好,操作简便 三、快速高效,高度可定制 四、安全可靠,社区活跃 在日常的电脑使用中,无论是为了安装操作系统、修复系统故障还是进行其他需要可引导媒体的任务,拥…...
vue的基本使用
简介 vue组件 三个部分组成:结构、样式、逻辑文本插值 类似于java的spel表达式属性绑定 綁定是单向绑定的,修改输入框无法改变原本的,只能读,不能写 <input :value="name" placeholder="Type your name"><script> export default {name: H…...
C#高级:利用 CancellationToken 实现方法超时控制,提升应用响应性
完整版: using System; using System.Threading; using System.Threading.Tasks;public class Program {public static async Task Main(){var cts new CancellationTokenSource();// 设置超时时间为10秒cts.CancelAfter(TimeSpan.FromSeconds(3));try{var resul…...
Java Lock LockSupport 总结
前言 相关系列 《Java & Lock & 目录》(持续更新)《Java & Lock & LockSupport & 源码》(学习过程/多有漏误/仅作参考/不再更新)《Java & Lock & LockSupport & 总结》(学习总结/最新…...
线性表之链式存储基本操作(c语言实现,附解析)
今天,我来讲一下数据结构链表的基本操作,首先我们要知道链表的基本操作有创建,查找,插入,删除。接下来我们逐一实现操作。 结构体定义 typedef struct Node* List; struct Node{ ElementType Data; List next; };文章…...
27.Redis哨兵架构
Redis哨兵高可用架构 Sentinel(哨兵)是一种特殊的 Redis 服务,其主要功能并非提供常规的读写服务,而是专门用于监控 Redis 实例节点。 1.在哨兵架构下,客户端(client 端)首次会从哨兵处找出 Re…...
BGP路由优选
BGP 的路由优选规则是一套多步决策链,用来确定在多个可行路由中选择最优的路由。BGP 是一种路径向量协议,通过这些优选规则,网络管理员可以控制数据流量的流向,确保网络的稳定性和效率。下面以一个实例来详细说明 BGP 的优选规则及…...
cjson内存泄漏问题注意事项
(1)使用root cJSON_Parse(text); //将字符串转成json格式,函数中申请了一块内存给root 所以在最后要释放root cJSON_Delete(root ); //释放cJSON_Parse()分配出来的内存空间 (2)使用out cJSON_Print(root);(含有cJSON_PrintUnformatted函数&#x…...
雷军救WPS“三次”,WPS注入新生力量,不再“抄袭”微软
救WPS“三次” 1989年,求伯君用128万行代码编写出了WPS1.0,宣告了中国自主办公时代的开启。 那时候,雷军还在武汉大学深造,他早就把求伯君当成了自己的榜样,这一来二去的,雷军和WPS之间也就结下了不解之缘…...
zookeeper全系列学习之分布式锁实现
文章目录 前言一、分布式锁的通用实现思路二、ZK实现分布式锁的思路三、ZK实现分布式锁的编码实现1、核心工具类实现2、测试代码编写线程安全问题复现使用上面封装的ZkLockHelper实现的分布式锁 优点缺点 总结 前言 就像上篇文章zookeeper全系列学习之统一配置获取说的&#x…...
耐用的内衣洗衣机有哪些?双11好用内衣洗衣机品牌排行榜
现代社会高速发展,人们对于生活品质的追求不断提高,内衣作为贴身衣物,其清洁程度直接关系到个人卫生和健康。因此,耐用且高效的内衣洗衣机成为了许多家庭的必需品。在双11购物节期间,众多品牌推出了各种优惠活动&#…...
富格林:曝光可信经验击败陷阱
富格林认为,现货黄金投资是一项收益与风险并存的交易活动。在现货黄金中,时常为投资者曝光总结一些可信的交易经验,能在必要时帮助投资者击败陷阱,同时也会获得较高概率的收益。如今的投资经验和策略是非常多的,以下是…...
3211、生成不含相邻零的二进制字符串-cangjie
题目 3211、生成不含相邻零的二进制字符串 思路 dfs 代码 class Solution {let numRune [r0, r1]func dfs(arr: ArrayList<Rune>, ans: ArrayList<String>,n: Int64):Unit{if(arr.size > n){ans.insert(0, String(arr))// println("insert ${String(…...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?
FTP(File Transfer Protocol)本身是一个基于 TCP 的协议,理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况,主要原因包括: ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...
快速排序算法改进:随机快排-荷兰国旗划分详解
随机快速排序-荷兰国旗划分算法详解 一、基础知识回顾1.1 快速排序简介1.2 荷兰国旗问题 二、随机快排 - 荷兰国旗划分原理2.1 随机化枢轴选择2.2 荷兰国旗划分过程2.3 结合随机快排与荷兰国旗划分 三、代码实现3.1 Python实现3.2 Java实现3.3 C实现 四、性能分析4.1 时间复杂度…...
