一个简单的例子,说明Matrix类的妙用

在Android、前端或者别的平台的软件开发中,有时会遇到类似如下需求:

  1. 将某个图片显示到指定的区域;
  2. 要求不改变图片本身的宽高比,进行缩放;
  3. 要求最大限度的居中填充到显示区域。

以下示意图可以简单描绘该需求

以Android平台为例,如果我们的目标显示对象为Imageview,那么很简单,只要如下设置即可

xml 复制代码
<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的同学,可能第一反应就是根据图片本身的宽高以及目标显示区域的宽高,去计算一个缩放比,如下代码:

java 复制代码
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);

    // 绘制 Bitmap
    canvas.drawBitmap(bitmap, matrix, null);
}

但是,当你深入研究Matrix中的方法,你就会发现,根本不需要这么麻烦,以下几句即可简单完美实现

java 复制代码
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);

    // 绘制 Bitmap
    canvas.drawBitmap(bitmap, matrix, null);
}

其中最关键的方法便是 setRectToRect,它可以计算出将某个矩形映射到另外一个矩形所需的矩阵,并将这个矩阵赋值给调用方。其实,Matrix还有很多使用强大的接口,感兴趣的同学可以系统深入探索下。尤其是工作学习当中涉及到图片缩放、裁剪、旋转、平移等操作的同学,更应该学习下。

相关推荐
高梦轩1 天前
MySQL高可用
android·运维·数据库
lizhongxuan1 天前
Claude Code 防上下文爆炸:源码级深度解析
前端·后端
柳杉1 天前
震惊!字符串还能这么玩!
前端·javascript
RATi GORI1 天前
MySQL中的CASE WHEN语句:用法、示例与解析
android·数据库·mysql
是上好佳佳佳呀1 天前
【前端(五)】CSS 知识梳理:浮动与定位
前端·css
MoFe11 天前
【Mysql】创建IP授权用户并授权
android
wefly20171 天前
纯前端架构深度解析:jsontop.cn,JSON 格式化与全栈开发效率平台
java·前端·python·架构·正则表达式·json·php
冬奇Lab1 天前
Camera2 API架构基础:Android视频系统的大门
android·音视频开发·源码阅读
hnlgzb1 天前
安卓app kotlin语法,Hilt是什么东西?
android·开发语言·kotlin
我命由我123451 天前
React - 类组件 setState 的 2 种写法、LazyLoad、useState
前端·javascript·react.js·html·ecmascript·html5·js