iOS - Swift 仿微信聊天图片显示

效果图

如图所示,图片左侧有个小箭头

效果图

原理

其实原理比较简单,准备一张图片MaskImgae,先对其进行拉伸,然后按照其轮廓对图片进行裁剪就行了

MaskImgae

步骤

这里摘重点说,布局什么的按自己意愿去弄吧。我固定了图片的显示大小为 102 * 152

1、对MaskImgae进行拉伸

// 设置拉伸范围
let stretchInsets = UIEdgeInsetsMake(30, 28, 23, 28)
// 待拉伸的图片
let stretchImage = UIImage(named: "SenderImageNodeMask")
// 进行拉伸
let bubbleMaskImage = stretchImage.resizableImage(withCapInsets: stretchInsets, resizingMode: .stretch)

拉伸的效果如图

拉伸效果

2、对imageView设置裁剪区域

这里我的 imageView 叫 chatImgView 上面的拉伸效果图是临时把拉伸好的图片赋值给了chatImgView,只是为了给大家看到效果而已,�各位看官如果有赋值请记得改回来~~

好,下面进行裁剪

// 新建一个图层
let layer = CALayer()
// 设置图层显示的内容为拉伸过的MaskImgae
layer.contents = bubbleMaskImage.cgImage
// 设置拉伸范围(注意:这里contentsCenter的CGRect是比例(不是绝对坐标))
layer.contentsCenter = self.CGRectCenterRectForResizableImage(bubbleMaskImage)
// 设置图层大小与chatImgView相同
layer.frame = CGRect(x: 0, y: 0, width: 102, height: 152)
// 设置比例
layer.contentsScale = UIScreen.main.scale
// 设置不透明度
layer.opacity = 1
// 设置裁剪范围
self.chatImgView.layer.mask = layer
// 设置裁剪掉超出的区域
self.chatImgView.layer.masksToBounds = true
func CGRectCenterRectForResizableImage(_ image: UIImage) -> CGRect {
    // LXFLog("\(image.capInsets)")
    // 这里的image.capInsets就是UIEdgeInsetsMake(30, 28, 23, 28)
    return CGRect(
        x: image.capInsets.left / image.size.width,
        y: image.capInsets.top / image.size.height,
        width: (image.size.width - image.capInsets.right - image.capInsets.left) / image.size.width,
        height: (image.size.height - image.capInsets.bottom - image.capInsets.top) / image.size.height
    )
}

这样就完成了

解释一下下

UIEdgeInsetsMake

MaskImgae 的大小为 56 * 50

// UIEdgeInsetsMake(top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat)
UIEdgeInsetsMake(30, 28, 23, 28)

红色范围就是要拉伸的范围(随手一扣,不太准确,意思意思下就好了~~)

拉伸区域

contentsCenter

这是对某个区域进行全面拉伸,如果不设置的话默认值为

CGRect(x: 0, y: 0, width: 1, height: 1)

就是直接进行缩放 那我们先来看看,如果不对contentsCenter这个值进行设置会是什么效果

直接拉伸

我们来看下官方解释

var contentsCenter: CGRect { get set }
Description 
The rectangle that defines how the layer contents are scaled
if the layer’s contents are resized. Animatable.

翻译:如果图层的内容是重新设置了尺寸的,那定义的这个矩形(contentsCenter)是为了告诉图层,图层的内容是如何被缩放的

那明了,我们的图片是被拉伸后再绘制到layer上的,为了正确显示我们的图片,我们得告诉layer它是怎么被进行拉伸的。是的,就是下面代码所指定的范围

UIEdgeInsetsMake(30, 28, 23, 28)

�但是,正如上面提到过的,contentsCenter所要赋值的CGRect是比例,不是绝对坐标,所以现在我们得�通过(30, 28, 23, 28)�获取比例值,转换方法已经在上面给出了,就是CGRectCenterRectForResizableImage 我们来打印下 image.capInsets的内容

LXFLog("\(image.capInsets)")
LXFLog("\(image.capInsets.top)")
LXFLog("\(image.capInsets.bottom)")
LXFLog("\(image.capInsets.left)")
LXFLog("\(image.capInsets.right)")

打印结果

UIEdgeInsets(top: 30.0, left: 28.0, bottom: 23.0, right: 28.0)
30.0
23.0
28.0
28.0

�好,现在结合 下面的图 与 CGRectCenterRectForResizableImage 方法中的代码就很明确比例是怎么取到的了

拉伸区域

附上相关项目:Swift 3.0 高仿微信

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏一个爱瞎折腾的程序猿

sqlserver使用存储过程跟踪SQL

USE [master] GO /****** Object: StoredProcedure [dbo].[sp_perfworkload_trace_s...

2020
来自专栏大内老A

The .NET of Tomorrow

Ed Charbeneau(http://developer.telerik.com/featured/the-net-of-tomorrow/) Exciti...

31210
来自专栏跟着阿笨一起玩NET

c#实现打印功能

2692
来自专栏张善友的专栏

Mix 10 上的asp.net mvc 2的相关Session

Beyond File | New Company: From Cheesy Sample to Social Platform Scott Hansel...

2547
来自专栏芋道源码1024

熔断器 Hystrix 源码解析 —— 断路器 HystrixCircuitBreaker

本文主要基于 Hystrix 1.5.X 版本 1. 概述 2. HystrixCircuitBreaker 3. HystrixCircuitBreaker....

5287
来自专栏杨龙飞前端

scrollto 到指定位置

2494
来自专栏陈仁松博客

ASP.NET Core 'Microsoft.Win32.Registry' 错误修复

今天在发布Asp.net Core应用到Azure的时候出现错误InvalidOperationException: Cannot find compilati...

4818
来自专栏飞扬的花生

jsencrypt参数前端加密c#解密

      写程序时一般是通过form表单或者ajax方式将参数提交到服务器进行验证,如何防止提交的请求不被抓包后串改,虽然无法说绝对安全却给非法提交提高了难度...

3859
来自专栏pangguoming

Spring Boot集成JasperReports生成PDF文档

由于工作需要,要实现后端根据模板动态填充数据生成PDF文档,通过技术选型,使用Ireport5.6来设计模板,结合JasperReports5.6工具库来调用渲...

1.2K7
来自专栏一个会写诗的程序员的博客

Spring Reactor 项目核心库Reactor Core

Non-Blocking Reactive Streams Foundation for the JVM both implementing a Reactiv...

2142

扫码关注云+社区