视图变换 - 等比例变换防止视图拉伸

转载请注明出处

使用场景

在日常开发中,经常会遇到的一个需求是将图片/视频从界面的一个位置,变换到另一个位置。在处理这类问题的时候经常会遇到的一个问题就是比例变化,如果两个位置的宽高比例不一致,如果不做任何处理直接将图像显示到另一个位置图像就会被拉伸。如果使用的是 ImageView 的话,可以设置 scaleType 去选择一个合适的填充方式,但是一些情况下,使用的不是 ImageView 。

以 Android 开发中的相机预览图处理为例,我们通过下面的代码去获取相机的预览图,在手机上,我们获取分辨率,都会有很多分辨率可选:
这里我截取我手机上断点看到的分辨率的可选的列表:

可选择的分辨率很多,一共有 47 个。以 1280*720 ,和 1280*960 两个格式预览图为例,最后换算得到的分辨率的比例分别是 16:9 和 4:3 这两个比例。

因为相机预览图获取到的是的时候横着的,需要这里的比例可以理解为预览图的比例可以理解为 height/width。使用预览图上屏的时需要旋转 90 度。

下面以相机预览图上屏为例进行问题解决,如果不进行处理,不按比例缩放上屏画面一定会被拉伸。

等比变换

而 Android 手机机型众多,屏幕纵横比也会有很多值,例如有 16 : 9,4 : 3,13 : 6 等多种比例。

等高填充

以一个 16 : 9 纵横比的手机为例,当我们获取到的预览图的比例是 4 : 3 的话,如何把这张 4 : 3 的图片贴到屏幕上避免图片被拉伸呢。

4 : 3 的比例指的宽高比是 3 : 4

在这里插入图片描述
在保持图片比例的情况下,

  • 等高填充:宽度会有一部分超出。
  • 等宽填充:屏幕高度部分会有部分剩余。
等宽填充

那反过来,我们将一个 16 : 9 的预览图放到 4 : 3 的屏幕上,按照不同的变换方式,我们可以得到下面两种变换结果。
在这里插入图片描述
在保持图片比例的情况下,

  • 等高填充:屏幕宽度会有部分剩余。
  • 等宽填充:高度部分会有一些超出。
代码进行比目标宽高计算

因为变换的时候我们的目标都是铺满目标区域,因此我们在变换的时候,采用上面铺满屏幕的变换方式,因此有下面的变换公式,这段代码在 Android 相机处理官方 Demo 中有存在:

			// 预览图变换后的新的 宽高 
            val newWidth: Int
            val newHeight: Int
            val actualRatio = if (width > height) aspectRatio else 1f / aspectRatio
            // 目标区域的宽高比例  和 实际的图片的比例 相比较
            if (width < height * actualRatio) {
                // 对应上面的 16:9 的手机,填充 4:3 的图片
                newHeight = height
                newWidth = (height * actualRatio).roundToInt()
            } else {
            	// 对应上面的 4:3 的手机,填充 16:9 的
                newWidth = width
                newHeight = (width / actualRatio).roundToInt()
            }

上面的代码在对应的地方都加了注释,经过上面的代码我们可以计算得到一个新的宽高。

超出部分处理

在上面计算的变换后的宽高后,超出的部分我们要进行相应的处理,确保画面显示正常

设置负的 margin

以宽超出为例,我们需要设置负的 leftMargin:

如果是高度部分超出的话,就设置对应的负的 topMargin

leftMargin = -(newWidth-originWidth) / 2;

将整体 View 偏移一个 负的距离后,就可以实现整体居中,画面回比较正常。

clip 裁剪

如果没办法将 View 的一部分偏移到界面的不可见部分,那么就将超出的部分裁剪不显示,确保画面的正常。
Android 裁剪方式:参考自己这篇博客中的 clipChildren 默认是 true 进行裁剪
https://blog.csdn.net/liu_12345_liu/article/details/111822877?spm=1001.2014.3001.5502#clipToPadding_1
在这里插入图片描述
鸿蒙上的裁剪方式
在这里插入图片描述
默认为 false ,需要手动设置为 true 。

End

到这里,使用上面的方式,已经可以实现将图片不拉伸显示在界面中,当然如果要避免图片放大后画面模糊,尽量选择一个像素不是那么少的图片进行放大,缩小的话那就不牵扯模糊的问题。

参考:

android platform sample https://github.com/android/platform-samples/tree/main

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值