动手教你撸一个iOS颜色拾取器

iOS 实现图片颜色拾取器

  • 为什么需要颜色拾取
  • iOS颜色拾取器的实现
    • CGContext的使用
    • 自定义颜色采集板View
    • 颜色选择器的使用
  • 结束

为什么需要颜色拾取

有些APP开发业务中经常需要用到颜色拾取的功能,来完成对所需颜色的选择,比如主题设置功能,废话不多说,需要的同学自己拿去用吧!

iOS颜色拾取器的实现

CGContext的使用

使用CGContext进行图片颜色的拾取能够节省内存的使用(CGContext对图片管理的具体使用后期来专讲一下)

  1. 获取UIImageView中的UIImage
  2. 拾取坐标的转换
  3. 利用BitmapInfo来获取UIImage的RGB分布
  4. 利用CGContext获取目标像素的分布值
  5. 输出对应位置的颜色值
func getColor(inImageView imageview: UIImageView, selectedPoint: CGPoint) -> UIColor?{
        //imageview图片
        let image: UIImage = imageview.image!
        //imageview中的坐标对用image的坐标
        let x_factor = image.size.width/imageview.frame.width
        let y_factor = image.size.height/imageview.frame.height
        let newSelectedPoint: CGPoint = CGPoint.init(x: selectedPoint.x*x_factor, y: y_factor*selectedPoint.y)
        if !CGRect.init(x: 0, y: 0, width: image.size.width, height: image.size.height).contains(newSelectedPoint){
            return nil
        }
        // 用来存放目标像素值
        var pixel = [UInt8](repeatElement(0, count: 4))
        // 颜色空间为 RGB,这决定了输出颜色的编码是 RGB 还是其他(比如 YUV)
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        // 设置位图颜色分布为 RGBA
        let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue
        guard let context = CGContext(data: &pixel, width: 1, height: 1, bitsPerComponent: 8, bytesPerRow: 4, space: colorSpace, bitmapInfo: bitmapInfo) else {
            return nil
        }
        // 设置 context 原点偏移为目标位置所有坐标
        context.translateBy(x: -newSelectedPoint.x, y: -newSelectedPoint.y)
        // 将图像渲染到 context 中
        imageview.layer.render(in: context)
        
        return UIColor(red: CGFloat(pixel[0]) / 255.0,
                       green: CGFloat(pixel[1]) / 255.0,
                       blue: CGFloat(pixel[2]) / 255.0,
                       alpha: CGFloat(pixel[3]) / 255.0)
    }

自定义颜色采集板View

  1. View中包含UIImageView显示需要采集颜色的图片
  2. 包含UIButton作为采集位置的指示器
  3. 利用UIPanGestureRecognizer实现拖动UIButton选择采集位置
import UIKit
typealias ColorChange = (UIColor?)->Void //选择颜色的闭包
@IBDesignable         //可视化的关键字
class ColorSelectedView: UIView {
    @IBOutlet var bgview: UIView!
    @IBOutlet weak var gradientImageView: UIImageView!
    @IBOutlet weak var selectedBtn: UIButton!
    var panGesture: UIPanGestureRecognizer!
    var colorChange: ColorChange?
    override init(frame: CGRect) {       //每一步都必须
        super.init(frame: frame)//实现父初始化
        bgview = loadViewFromNib()  //从xib中加载视图
        bgview.frame = bounds       //设置约束或者布局
        addSubview(bgview)          //将其添加到自身中
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        bgview = loadViewFromNib()
        bgview.frame = bounds
        addSubview(bgview)
    }
    //MARK:加载xib文件的view视图
    func loadViewFromNib() -> UIView {
        //重点注意,否则使用的时候不会同步显示在IB中,只会在运行中才显示。
        //注意下面的nib加载方式直接影响是否可视化,如果bundle不确切(为nil或者为main)则看不到实时可视化
        let nib = UINib(nibName:String(describing: ColorSelectedView.self), bundle: Bundle(for:ColorSelectedView.self))//【????】怎么将类名变为字符串:String(describing: MyView.self) Bundle的参数为type(of: self)也可以。
        let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
        panGesture = UIPanGestureRecognizer.init(target: self, action: #selector(gestureAction))
        selectedBtn?.addGestureRecognizer(panGesture)
        return view
    }
    
    //拖动选择需要采集颜色的位置
    @objc func gestureAction(_ sender: UIPanGestureRecognizer){
        if sender.view == self.selectedBtn{
            if sender.state != .ended && sender.state != .failed{
                let point: CGPoint = sender.location(in: self)
                var newpoint: CGPoint = point
                if point.x < 0 {
                    newpoint.x = 0
                }
                if point.y < 0 {
                    newpoint.y = 0
                }
                if point.x > self.frame.size.width-30 {
                    newpoint.x = self.frame.size.width-30
                }
                if point.y > self.frame.size.height-30 {
                    newpoint.y = self.frame.size.height-30
                }
                self.selectedBtn.frame.origin = newpoint
                let selecteColor: UIColor? =self.getColor(inImageView: self.gradientImageView, selectedPoint: CGPoint.init(x: newpoint.x+15, y: newpoint.y+15))
                if selecteColor != nil{
                    if colorChange != nil{
                        colorChange!(selecteColor)
                    }
                }
            }
        }
    }
}

动手教你撸一个iOS颜色拾取器_第1张图片

颜色选择器的使用

  1. 在xib文件中或者在storyboard可视化界面中直接使用
  2. 在代码中直接使用
@IBOutlet weak var colorSelectedView: ColorSelectedView!
...
colorSelectedView.colorChange = {
            (color: UIColor?) -> Void in
            if color != nil{
                ...
                //按自己需要使用该颜色
              }
        }

结束

哈哈,可以自己拖动Button进行位置选择,当拖动时会实时输出选中位置的颜色。好了,就是这么简单!你也来试试吧!

你可能感兴趣的:(iOS)