用另一个UIView屏蔽UIView

时间:2018-11-11 01:05:06

标签: ios swift mask

是的,曾经有人问过这个问题,解决方案不起作用或有不同的应用程序。

这是最基本的设置。我有两个矩形UIViews,红色和蓝色。 我想将蓝色方块切成红色方块,所以红色方块看起来像个“ L”

enter image description here

import Foundation
import UIKit

class TestController: UIViewController {
    override func viewDidLoad() {
        view.backgroundColor = .gray
        view.addSubview(viewA)
        view.addSubview(maskView)

        viewA.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        viewA.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        viewA.widthAnchor.constraint(equalToConstant: 100).isActive = true
        viewA.heightAnchor.constraint(equalToConstant: 100).isActive = true
        viewA.translatesAutoresizingMaskIntoConstraints = false

        maskView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 50).isActive = true
        maskView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: -50).isActive = true
        maskView.widthAnchor.constraint(equalToConstant: 100).isActive = true
        maskView.heightAnchor.constraint(equalToConstant: 100).isActive = true
        maskView.translatesAutoresizingMaskIntoConstraints = false

        // Things which don't work
        //viewA.mask = maskView // both views disappear
        //viewA.layer.mask = maskView.layer // both views disappear
        //viewA.layer.addSublayer(maskView.layer) // hides mask view
    }

    var viewA: UIView = {
        let view = UIView()
        view.backgroundColor = .red
        view.layer.masksToBounds = true
        return view
    }()

    var maskView: UIView = {
        let view = UIView()
        view.backgroundColor = .blue
        return view
    }()
}

这是我期望的结果:(在Photoshop中完成)

enter image description here

1 个答案:

答案 0 :(得分:0)

由于在iOS中没有任何一种神奇的方法可以掩盖这种方式,因此我在这里介绍一种简单的方法来实现这一目标。

别忘了平移空白区域,如果离开红色方块,它将变成蓝色方块。

为了您自己的目的,尤其是视图,不难修改UIViews的子类。

    import UIKit

        class TestController: UIViewController {

                override func viewDidLoad() {
                    view.backgroundColor = .gray
                    view.addSubview(viewA)
                    view.addSubview(maskView)
                    maskView.maskedView = viewA
                    viewA.activeMask = maskView
                    viewA.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
                    viewA.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
                    viewA.widthAnchor.constraint(equalToConstant: 100).isActive = true
                    viewA.heightAnchor.constraint(equalToConstant: 100).isActive = true
                    viewA.translatesAutoresizingMaskIntoConstraints = false
                    maskView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 50).isActive = true
                    maskView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: -50).isActive = true
                    maskView.widthAnchor.constraint(equalToConstant: 100).isActive = true
                    maskView.heightAnchor.constraint(equalToConstant: 100).isActive = true
                    maskView.translatesAutoresizingMaskIntoConstraints = false
                }

                var viewA: MyUIView = {
                    let view = MyUIView()
                    view.backgroundColor = .clear
                    view.layer.masksToBounds = true
                    return view
                }()


            var maskView: ActiveMaskView = {
                let view = ActiveMaskView()
                    view.backgroundColor = .clear
                    return view
                }()


            }

        class ActiveMaskView: UIView{
            override func didMoveToSuperview() {
                super.didMoveToSuperview()
                let panGesture =  UIPanGestureRecognizer.init(target: self, action: #selector(moveAround(_:)))
                self.addGestureRecognizer(panGesture)
            }
              weak  var maskedView : UIView?
            private var frameOrigin : CGPoint = CGPoint.zero

          @objc  func moveAround(_ panGesture: UIPanGestureRecognizer){
            guard let superview = superview else {return}
                switch panGesture.state {
                case .began:
                  frameOrigin = frame.origin
                    self.backgroundColor = UIColor.blue
                case .changed:
                    let translation  = panGesture.translation(in: superview)
                    frame = CGRect.init(origin: CGPoint.init(x: frameOrigin.x + translation.x, y: frameOrigin.y + translation.y), size: frame.size)
                    maskedView?.setNeedsDisplay()
                    break
                case .ended:
                    self.backgroundColor =
                        frame.intersects(maskedView!.frame) ?
                    UIColor.clear : UIColor.blue
                    maskedView?.setNeedsDisplay()
                case .cancelled:
                    frame = CGRect.init(origin: frameOrigin , size: frame.size)
                    self.backgroundColor =
                        frame.intersects(maskedView!.frame) ?
                    UIColor.clear : UIColor.blue
                    maskedView?.setNeedsDisplay()
                default:
                    break;
                }
            }
        }

        class MyUIView: UIView{

          weak  var activeMask: ActiveMaskView?

            override func draw(_ rect: CGRect) {
                super.draw(rect)
                let ctx = UIGraphicsGetCurrentContext()
                ctx?.setFillColor(UIColor.red.cgColor)
                ctx?.fill(self.layer.bounds)
                ctx?.setBlendMode(.sourceOut)
                guard let activeMask = activeMask , let superview = superview else {
                   return
                }
              let sc = frame.intersection(activeMask.frame)
            let interSection = superview.convert(sc, to: self)
                ctx?.fill(interSection )
             }
        }