一个简单的例子,说明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还有很多使用强大的接口,感兴趣的同学可以系统深入探索下。尤其是工作学习当中涉及到图片缩放、裁剪、旋转、平移等操作的同学,更应该学习下。

相关推荐
是我知白哒7 分钟前
lxml提取某个外层标签里的所有文本
前端·爬虫·python
发飙的蜗牛'22 分钟前
23种设计模式
android·java·设计模式
m0_748246351 小时前
前端通过new Blob下载文档流(下载zip或excel)
前端·excel
半糖11221 小时前
将本地项目提交到远程仓库
前端·vue.js
web150850966415 小时前
【React&前端】大屏适配解决方案&从框架结构到实现(超详细)(附代码)
前端·react.js·前端框架
理想不理想v5 小时前
前端项目性能优化(详细)
前端·性能优化
CodeToGym5 小时前
使用 Vite 和 Redux Toolkit 创建 React 项目
前端·javascript·react.js·redux
Cachel wood6 小时前
Vue.js前端框架教程8:Vue消息提示ElMessage和ElMessageBox
linux·前端·javascript·vue.js·前端框架·ecmascript
桃园码工7 小时前
4_使用 HTML5 Canvas API (3) --[HTML5 API 学习之旅]
前端·html5·canvas
桃园码工8 小时前
9_HTML5 SVG (5) --[HTML5 API 学习之旅]
前端·html5·svg