Simplemente enmascara una UIView con un rectángulo

Quiero saber cómo enmascarar simplemente el área visible de una UIView de cualquier tipo. Todas las respuestas / tutoriales que he leído hasta ahora describen enmascarar con una image, gradiente o crear esquinas networkingondeadas, lo cual es mucho más avanzado que lo que estoy buscando.

Ejemplo: Tengo una UIView con los límites (0, 0, 100, 100) y quiero cortar la mitad derecha de la vista usando una máscara. Por lo tanto, mi marco de máscara sería (0, 0, 50, 100).

¿Alguna idea de cómo hacer esto simplemente? No quiero anular el método drawrect, ya que esto debería ser aplicable a cualquier UIView.

He intentado esto pero solo hace que toda la vista sea invisible.

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

Gracias al enlace de MSK, esta es la forma en que fui con lo que funciona 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 covenetworking by ARC. CGPathRelease(path); // Set the mask of the view. viewToMask.layer.mask = maskLayer; 

No hace falta ninguna máscara. Simplemente colóquelo en una vista de contenedor con el marco más pequeño y establezca clipsToBounds .

 wrapper.clipsToBounds = YES; 

Gracias por las respuestas chicos.

En caso de que alguien no pueda encontrar la respuesta adecuada para esta pregunta por horas, como acabo de hacer, he reunido una idea funcional en Swift 2.2 para masking / clipping UIView con 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.appendPath(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.appendPath(UIBezierPath(rect: self.bounds)) maskLayer.fillRule = kCAFillRuleEvenOdd } maskLayer.path = path.CGPath self.layer.mask = maskLayer } } 

Uso:

 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) 

Espero que le salve a alguien en el futuro 🙂

Una capa opcional cuyo canal alfa se utiliza como máscara para seleccionar entre el background de la capa y el resultado de la composition de los contenidos de la capa con su background filtrado.

@property (retener) CALayer * máscara

La forma correcta de hacer lo que desea es crear la maskView del mismo cuadro (0, 0, 100, 100) como la viewToMask qué capa desea enmascarar. Luego debe configurar el color claro para la ruta que desea que sea invisible (esto bloqueará la interacción de la vista sobre la ruta, así que tenga cuidado con la jerarquía de la vista).

Ejemplo muy simple en Swift ViewController, basado en la respuesta aceptada:

 import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let networkingView = UIView(frame: view.bounds) view.addSubview(networkingView) view.backgroundColor = UIColor.greenColor() networkingView.backgroundColor = UIColor.networkingColor() mask(networkingView, 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; } } 

Salida

introduzca la descripción de la imagen aquí

Configurar MaskToBounds no es suficiente, por ejemplo, en el escenario donde tiene UIImageView que se coloca dentro de RelativeLayout . En el caso de que coloque su UIImageView cerca del borde superior del layout y luego gire su UIImageView , se pasará por encima del layout y no se recortará. Si establece ese indicador en verdadero, se recortará sí, pero también se recortará si UIImageView está en el centro del layout, y eso no es lo que desea.

Por lo tanto, la determinación de maskRect es el enfoque correcto.