iOS Swift处理点9图片
一、什么是点9图?
点9图是Android开发中用到的一种特殊格式的图片,后缀名是“.9.png”的图片。左上两条线控制可拉伸区域(未画线表示不可拉伸),右下两条线控制内容显示区(无文字内容不画)。
二、点9图的作用是什么?
简单来说,点9图的作用就是可以保证图片在不模糊变形的前提下做到自适应。
什么意思呢?我们来举个简单的例子说明吧。下图是我们常见的按钮背景,切图的时候如果没有用点9切图,开发想改变按钮的高度的时候,会直接整体拉伸,得到的结果就是圆角就变形了,如下图:
那么用点9图之后,会通过左、上两条横线定义图片可以拉伸的部分,问题就得到了解决啦,如下图:
三 iOS中如何处理图片局部拉伸
iOS中处理进行图片局部拉伸,相关API如下:
@available(iOS 5.0, *) open func resizableImage(withCapInsets capInsets: UIEdgeInsets) -> UIImage @available(iOS 6.0, *) open func resizableImage(withCapInsets capInsets: UIEdgeInsets, resizingMode: UIImage.ResizingMode) -> UIImage
capInsets定义图片的不拉伸范围(这个范围是相对于源图片大小而言),resizingMode定义了图片以拉伸/平铺的方式变换。
四 iOS中如何处理点9图片
iOS和安卓为了可以统一用一套UI,iOS需要显示点九图片,具体思路是获取到图片中上、左两条直线的像素颜色值,取得黑线距离两边的距离即为不可拉伸区域,得到上下左右不可拉伸区域之后,用iOS局部拉伸API处理。
func ninePatchImage(_ scale: Int = 3) -> UIImage{ guard let imageRef = self.cgImage else{ return self } guard let rgbaImage :[[CGFloat]] = getRGBA() else{ return self } let scale:CGFloat = CGFloat(scale) //最上边一行的各像素点数组 var topBarRgba:[[CGFloat]] = [] for i in 1..<imageRef.width - 1 { topBarRgba.append(rgbaImage[i]) } //最左边一排像素点数组 var leftBarRgba = [[CGFloat]]() for i in 0..<rgbaImage.count { if i % imageRef.width == 0{ leftBarRgba.append(rgbaImage[i]) } } leftBarRgba.removeFirst() leftBarRgba.removeLast() guard let edge = stretchEdge(topBarRgba: topBarRgba, leftBarRgba: leftBarRgba) else { return self } if let cgImage = self.cgImage?.cropping(to: CGRect(x: 1, y: 1, width: self.size.width - 2, height: self.size.height - 2)){ var cropImage = UIImage.init(cgImage: cgImage, scale: CGFloat(scale), orientation: .up) cropImage = cropImage.resizableImage(withCapInsets: UIEdgeInsets(top: edge.top/scale, left: edge.left/scale, bottom: edge.bottom/scale, right: edge.right/scale),resizingMode: .stretch) return cropImage } return self }
获取黑线距离各边的具体长度
private func stretchEdge(topBarRgba:[[CGFloat]],leftBarRgba:[[CGFloat]]) -> UIEdgeInsets?{ var left = -1 for i in 0..<topBarRgba.count { if topBarRgba[i][3] == 1 { left = i break } } if left == -1{ return nil } var right = -1 for i in (0..<topBarRgba.count).reversed() { if topBarRgba[i][3] == 1 { right = i break } } if right == -1{ return nil } var top = -1 for i in (0..<leftBarRgba.count) { if leftBarRgba[i][3] == 1 { top = i break } } if top == -1{ return nil } var bottom = -1 for i in (0..<leftBarRgba.count).reversed() { if leftBarRgba[i][3] == 1 { bottom = i break } } if bottom == -1{ return nil } bottom = leftBarRgba.count - 1 - bottom right = topBarRgba.count - 1 - right return UIEdgeInsets(top: CGFloat(top), left: CGFloat(left), bottom: CGFloat(bottom), right: CGFloat(right)) }
文字显示区域也可以获取到,但是iOS中没有相关处理,让UI最好上和下,左和右黑线长度相同
地址: https://github.com/duzhaoquan/DQTool