使用另一个UIView遮罩UIView

3

是的,这个问题以前已经被问过了,但是解决方案没有起作用或者适用于不同的应用。

这是最基本的设置。我有两个矩形的UIView,一个是红色的,另一个是蓝色的。 我想让蓝色的正方形切入红色的正方形,使红色的正方形看起来像一个“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


请注意,此为涉及 IT 技术方面的翻译内容,如需更多相关帮助,请随时告知。
1个回答

0

在iOS中没有魔法方式来掩盖视图,我在这里提供了一种简单的方法来实现。

不要忘记平移清晰区域,如果离开红色正方形,它将变成蓝色正方形。

修改UIView子类以满足自己的需求并不难,特别是对于视图。

    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 )
             }
        }

哼..我不敢相信没有比这更简单的解决方案 :( 这就是我提出问题的原因: https://stackoverflow.com/questions/53221725/animated-color-transition/53223330#53223330 - arvidurs
这是不同的。在这种情况下,您可以显示一个隐藏层,这对于遮罩视图非常有用。但是,如果您想要隐藏所有层,遮罩视图在这里就无法帮助了。 - E.Coms

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接