UIImagePickerController editing view circle overlay

后端 未结 5 1260
太阳男子
太阳男子 2020-12-13 02:58

I\'ve been able to get pretty far with what I\'ve been wanting to accomplish, and that\'s to replicate iOS\'s built in circular photo cropper for the built in contacts app.

5条回答
  •  暗喜
    暗喜 (楼主)
    2020-12-13 03:38

    Swift 3 version (also with rounded edit layer for pictures taken by camera):

    // Insert this code to your view controller
    private var editLayer: CAShapeLayer!
    private var label: UILabel!
    
    
    override func viewDidLoad()
    {
        super.viewDidLoad()
    
        // Rounded edit layer
        navigationController?.delegate = self
        NotificationCenter.default.addObserver(self, selector: #selector(pictureCaptured), name: NSNotification.Name(rawValue: "_UIImagePickerControllerUserDidCaptureItem"), object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(pictureRejected), name: NSNotification.Name(rawValue: "_UIImagePickerControllerUserDidRejectItem"), object: nil)
    }
    
    
    @objc private func pictureCaptured()
    {
        addRoundedEditLayer(to: ...your UIImagePickerController..., forCamera: true)
    }
    
    
    @objc private func pictureRejected()
    {
        editLayer.removeFromSuperlayer()
        label.removeFromSuperview()
    }
    
    
    deinit
    {
        NotificationCenter.default.removeObserver(self)
    }    
    
    
    
    // MARK: Navigation controller delegate
    
    func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool)
    {
        // Image picker in edit mode
        if let imageVC = NSClassFromString("PUUIImageViewController")
        {
            if viewController.isKind(of: imageVC) {
                addRoundedEditLayer(to: viewController, forCamera: false)
            }
        }
    }
    
    
    private func addRoundedEditLayer(to viewController: UIViewController, forCamera: Bool)
    {
        hideDefaultEditOverlay(view: viewController.view)
    
        // Circle in edit layer - y position
        let bottomBarHeight: CGFloat = 72.0
        let position = (forCamera) ? viewController.view.center.y - viewController.view.center.x - bottomBarHeight/2 : viewController.view.center.y - viewController.view.center.x
    
        let viewWidth = viewController.view.frame.width
        let viewHeight = viewController.view.frame.height
    
        let emptyShapePath = UIBezierPath(ovalIn: CGRect(x: 0, y: position, width: viewWidth, height: viewWidth))
        emptyShapePath.usesEvenOddFillRule = true
    
        let filledShapePath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: viewWidth, height: viewHeight - bottomBarHeight), cornerRadius: 0)
        filledShapePath.append(emptyShapePath)
        filledShapePath.usesEvenOddFillRule = true
    
        editLayer = CAShapeLayer()
        editLayer.path = filledShapePath.cgPath
        editLayer.fillRule = kCAFillRuleEvenOdd
        editLayer.fillColor = UIColor.black.cgColor
        editLayer.opacity = 0.5
        viewController.view.layer.addSublayer(editLayer)
    
        // Move and Scale label
        label = UILabel(frame: CGRect(x: 0, y: 10, width: viewWidth, height: 50))
        label.text = "Move and Scale"
        label.textAlignment = .center
        label.textColor = UIColor.white
        viewController.view.addSubview(label)
    }
    
    
    private func hideDefaultEditOverlay(view: UIView)
    {
        for subview in view.subviews
        {
            if let cropOverlay = NSClassFromString("PLCropOverlayCropView")
            {
                if subview.isKind(of: cropOverlay) {
                    subview.isHidden = true
                    break
                }
                else {
                    hideDefaultEditOverlay(view: subview)
                }
            }
        }
    }
    

提交回复
热议问题