web-dev-qa-db-ja.com

UIViewを長方形でマスクするだけです

あらゆる種類のUIViewの表示領域を単純にマスクする方法を知りたいです。私がこれまで読んだすべての答え/チュートリアルは、画像、グラデーション、または丸い角の作成によるマスキングについて説明しています。

例:境界(0、0、100、100)を持つUIViewがあり、マスクを使用してビューの右半分を切り取ります。したがって、マスクフレームは(0、0、50、100)になります。

これを簡単に行う方法はありますか? drawrectメソッドをオーバーライドしたくないのは、これはどのUIViewにも適用できるはずだからです。

私はこれを試しましたが、ビュー全体が見えなくなります。

CGRect mask = CGRectMake(0, 0, 50, 100);
UIView *maskView = [[UIView alloc] initWithFrame:mask];
viewToMask.layer.mask = maskView.layer;
51
Accatyyc

MSKからのリンクのおかげで、これがうまくいった方法です。

// Create a mask layer and the frame to determine what will be visible in the view.
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
CGRect maskRect = CGRectMake(0, 0, 50, 100);

// Create a path with the rectangle in it.
CGPathRef path = CGPathCreateWithRect(maskRect, NULL);

// Set the path to the mask layer.
maskLayer.path = path;

// Release the path since it's not covered by ARC.
CGPathRelease(path);

// Set the mask of the view.
viewToMask.layer.mask = maskLayer;
124
Accatyyc

マスクはまったく必要ありません。ちょうど小さいフレームでラッパービューに入れてclipsToBounds を設定します。

wrapper.clipsToBounds = YES;
20
Geri

回答ありがとうございます。

誰かがSOでこの質問に対して適切な答えを見つけられない場合、私がちょうどやったように、私はSwift 2.2 masking/clippingUIViewCGRect/UIBezierPathの場合:

https://Gist.github.com/Flar49/7e977e81f1d2827f5fcd5c6c6a3c3d94

extension UIView {

    func mask(withRect rect: CGRect, inverse: Bool = false) {
        let path = UIBezierPath(rect: rect)
        let maskLayer = CAShapeLayer()

        if inverse {
            path.append(UIBezierPath(rect: self.bounds))
            maskLayer.fillRule = kCAFillRuleEvenOdd
        }

        maskLayer.path = path.cgPath

        self.layer.mask = maskLayer
    }

    func mask(withPath path: UIBezierPath, inverse: Bool = false) {
        let path = path
        let maskLayer = CAShapeLayer()

        if inverse {
            path.append(UIBezierPath(rect: self.bounds))
            maskLayer.fillRule = kCAFillRuleEvenOdd
        }

        maskLayer.path = path.cgPath

        self.layer.mask = maskLayer
    }
}

使用法:

let viewSize = targetView.bounds.size
let rect = CGRect(x: 20, y: 20, width: viewSize.width - 20*2, height: viewSize.height - 20*2)

// Cuts rectangle inside view, leaving 20pt borders around
targetView.mask(withRect: rect, inverse: true)

// Cuts 20pt borders around the view, keeping part inside rect intact
targetView.mask(withRect: rect)

将来誰かを救うことを願っています:)

20
Flar

Swift ViewController、受け入れられた答えに基づいた非常に簡単な例:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let redView = UIView(frame: view.bounds)
        view.addSubview(redView)

        view.backgroundColor = UIColor.greenColor()
        redView.backgroundColor = UIColor.redColor()

        mask(redView, maskRect: CGRect(x: 50, y: 50, width: 50, height: 50))
    }

    func mask(viewToMask: UIView, maskRect: CGRect) {
        let maskLayer = CAShapeLayer()
        let path = CGPathCreateWithRect(maskRect, nil)
        maskLayer.path = path

        // Set the mask of the view.
        viewToMask.layer.mask = maskLayer;
    }
}

出力

enter image description here

2
Dan Rosenstark

alpha channelのオプションレイヤーは、レイヤーの背景と、フィルター処理された背景でレイヤーのコンテンツを合成した結果の間で選択するためのマスクとして使用されます。

@property(retain)CALayer * mask

必要な処理を行う正しい方法は、マスクするレイヤーと同じmaskViewと同じフレーム(0、0、100、100)のviewToMaskを作成することです。次に、非表示にするパスにclearColorを設定する必要があります(これにより、パスに対するビューの対話がブロックされるため、ビューの階層に注意してください)。

1
A-Live

Swift 5、@ Dan Rosenstarkに感謝

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let red = UIView(frame: view.bounds)
        view.addSubview(red)
        view.backgroundColor = UIColor.cyan
        red.backgroundColor = UIColor.red
        red.mask(CGRect(x: 50, y: 50, width: 50, height: 50))
    }
}

extension UIView{
    func mask(_ rect: CGRect){
        let mask = CAShapeLayer()
        let path = CGPath(rect: rect, transform: nil)
        mask.path = path
        // Set the mask of the view.
        layer.mask = mask
    }
}
0
dengST30