Je veux savoir comment masquer simplement la zone visible d'une UIView de toute sorte. Toutes les réponses/tutoriels que j'ai lus jusqu'à présent décrivent le masquage avec une image, un dégradé ou la création de coins ronds qui est beaucoup plus avancé que ce que je recherche.
Exemple: J'ai une UIView avec les limites (0, 0, 100, 100) et je veux couper la moitié droite de la vue en utilisant un masque. Par conséquent, mon cadre de masque serait (0, 0, 50, 100).
Une idée comment faire cela simplement? Je ne veux pas remplacer la méthode drawrect car cela devrait être applicable à tout UIView.
J'ai essayé cela, mais cela rend la vue entière invisible.
CGRect mask = CGRectMake(0, 0, 50, 100);
UIView *maskView = [[UIView alloc] initWithFrame:mask];
viewToMask.layer.mask = maskView.layer;
Grâce au lien de MSK, c'est la voie que j'ai suivie qui fonctionne bien:
// 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;
Pas besoin de masque du tout. Il suffit de le placer dans une vue wrapper avec le plus petit cadre, et de définir clipsToBounds .
wrapper.clipsToBounds = YES;
Merci pour les réponses les gars.
Au cas où quelqu'un ne trouverait pas de réponse appropriée sur SO pour cette question pendant des heures, comme je viens de le faire, j'ai assemblé un Gist de travail dans Swift 2.2 pour masking
/clipping
UIView
avec 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
}
}
Usage:
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)
J'espère que cela fera gagner du temps à quelqu'un à l'avenir :)
Exemple très simple dans un Swift ViewController, basé sur la réponse acceptée:
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;
}
}
Sortie
Un calque facultatif dont canal alpha est utilisé comme masque pour sélectionner entre l'arrière-plan du calque et le résultat de la composition du contenu du calque avec son arrière-plan filtré.
@property (conserver) masque CALayer *
La bonne façon de faire ce que vous voulez est de créer le maskView
du même cadre (0, 0, 100, 100) que le viewToMask
quel calque vous voulez masquer. Ensuite, vous devez définir clearColor pour le chemin que vous souhaitez rendre invisible (cela bloquera l'interaction de la vue sur le chemin, alors soyez prudent avec la hiérarchie des vues).
Swift 5, merci @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
}
}