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

 
posted @ 2023-02-28 20:50  不停奔跑的蜗牛  阅读(359)  评论(0编辑  收藏  举报