【问题标题】:Mask UIView with another UIView用另一个 UIView 屏蔽 UIView
【发布时间】:2019-04-14 03:46:47
【问题描述】:

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

这是最基本的设置。我有两个矩形 UIView,红色和蓝色。 我希望蓝色方块切入红色方块,所以红色方块看起来像一个“L”

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 中完成)

【问题讨论】:

    标签: ios swift mask


    【解决方案1】:

    由于在 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 )
                 }
            }
    

    【讨论】:

    • hmpf.. 我不敢相信没有比这更简单的解决方案了 :( 这就是我要问的问题:stackoverflow.com/questions/53221725/animated-color-transition/…
    • 不一样。在这种情况下,您会显示一个隐藏层,这对遮罩视图很有用。但是如果你想隐藏所有图层,蒙版视图在这里无能为力。
    猜你喜欢
    • 2011-10-11
    • 2011-07-24
    • 2011-03-04
    • 2011-11-06
    • 2014-09-04
    • 1970-01-01
    • 2015-03-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多