56

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

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

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

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

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

7 に答える 7

130

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;
于 2012-07-09T08:30:04.987 に答える
28

答えてくれてありがとう。

誰かが SO でこの質問に対する適切な回答を何時間も見つけられない場合に備えて、私が行ったように、Swift 2.2 でmasking/ clipping UIViewwith CGRect/の作業要点を組み立てました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)

将来的に誰かの時間を節約できることを願っています:)

于 2016-10-07T12:28:57.760 に答える
22

マスクは一切必要ありません。小さいフレームのラッパー ビューに入れ、 clipsToBoundsを設定するだけです。

wrapper.clipsToBounds = true
于 2013-10-11T10:44:27.460 に答える
3

受け入れられた回答に基づく、Swift ViewController の非常に単純な例:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

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

        view.backgroundColor = UIColor.green
        redView.backgroundColor = UIColor.red

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

    func mask(_ viewToMask: UIView, maskRect: CGRect) {
        let maskLayer = CAShapeLayer()
        let path = CGPath(rect: maskRect, transform: nil)
        maskLayer.path = path

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

出力

ここに画像の説明を入力

于 2015-10-20T18:16:20.890 に答える
1

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

@property(retain) CALayer *マスク

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

于 2012-07-09T08:21:37.357 に答える