我目前有两个UIView:一个红色背景,另一个是蓝色的。蓝色视图是红色视图的子视图。我想做的是在蓝色视图上“切割”出矩形,从而可以显示红色视图。你如何实现这个功能?
我目前有两个UIView:一个红色背景,另一个是蓝色的。蓝色视图是红色视图的子视图。我想做的是在蓝色视图上“切割”出矩形,从而可以显示红色视图。你如何实现这个功能?
你需要重写顶部视图的 drawRect
方法。例如,你可以创建一个继承自 UIView
的 HoleyView
类(可以通过在项目中添加新文件、选择 Objective-C 子类并将 "Subclass of" 设置为 UIView
来实现)。在 HoleyView
中,drawRect
方法应该类似于这样:
- (void)drawRect:(CGRect)rect {
// Start by filling the area with the blue color
[[UIColor blueColor] setFill];
UIRectFill( rect );
// Assume that there's an ivar somewhere called holeRect of type CGRect
// We could just fill holeRect, but it's more efficient to only fill the
// area we're being asked to draw.
CGRect holeRectIntersection = CGRectIntersection( holeRect, rect );
[[UIColor clearColor] setFill];
UIRectFill( holeRectIntersection );
}
如果您正在使用Interface Builder,请确保将holey视图的类更改为HoleyView
。您可以通过在Interface Builder中选择该视图并在检查器中选择"Identity"面板(在 "i" 图标的最右侧)来完成此操作。
您还必须使用以下代码片段设置顶部视图为非不透明状态,或者通过取消Interface Builder中视图属性中的Opaque
复选框(在视图属性的View部分中找到),并将其背景颜色的不透明度设置为0%(在同一部分设置背景颜色)。
topView.opaque = NO;
topView.backgroundColor = [UIColor clearColor];
如果你想要绘制圆形,你需要使用 Core Graphics(也称为 Quartz 2D)。你可能需要阅读编程指南,可以在这里找到。- (void)drawRect:(CGRect)rect {
// Get the current graphics context
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor( context, [UIColor blueColor].CGColor );
CGContextFillRect( context, rect );
if( CGRectIntersectsRect( holeRect, rect ) )
{
CGContextSetFillColorWithColor( context, [UIColor clearColor].CGColor );
CGContextFillEllipseInRect( context, holeRect );
}
}
clearColor
作为填充颜色的UIGraphicsFillRect
函数不会擦除矩形的内容,而是在现有内容上绘制空白颜色。CGContextClearRect
是唯一能够“擦除”CGContext
某部分内容的函数(尽管通常不建议使用它--最好使用遮罩来控制之前的绘图命令)。 - rpetrichopaque
设置为false,这一步是必需的。 - Dima Deplov其他答案都有一定道理,但是使用清晰的颜色绘制,或者说在任何路径中"擦除"现有颜色,甚至使用-[UIBezierPath fill]或类似的便捷方法也是完全可能的。您需要做的就是根据您要实现的效果将上下文混合模式设置为适当的值,如下所示:
CGContextSetBlendMode(context, kCGBlendModeClear);
[[UIColor clearColor] set];
[myArbitraryPolygonPath fill];
你可以在CGContext参考文献中查看大约两打不同的选项。
要画椭圆而不是矩形,只需将 blendMode 设置为 clear:
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor( context, [UIColor blackColor].CGColor );
CGContextFillRect( context, rect );
CGRect holeRectIntersection = CGRectIntersection( holeRect, rect );
CGContextSetFillColorWithColor( context, [UIColor clearColor].CGColor );
CGContextSetBlendMode(context, kCGBlendModeClear);
CGContextFillEllipseInRect( context, holeRect );
}
holeRectIntersection
而不是 holeRect
. - iphonic这些可能是愚蠢的方法,但我不会按照你描述的方式去做,而是让它看起来像你想要的样子。
(Jacques的答案突然出现了 - 对我来说看起来很好)
方法1: 在视图控制器中构建一个矩形列表,以平铺周围的“洞口”。随着您的孔数增加,平铺矩形的数量也会增加。
方法2: 反转您的思维。蓝色视图应该在后面,红色视图的部分放置在其上。您仍然可以看到一个红色视图,除了“孔”被蓝色视图遮盖之外,但实际上您正在从要公开的视图中复制区域,并将它们放在每个孔上方的遮罩上。如果您有一些模拟深度的效果,可以根据需要添加每个孔。
两种方法都不需要子类化或drawRect:。
2023年,最新技术包括...
class CompImage: UIIImageView {
override func common() {
super.common()
layer.compositingFilter = "multiplyBlendMode"
print("Filters available to you ...\n",
CIFilter.filterNames(inCategory: kCICategoryCompositeOperation))
}
}
并且
guard let ctx = UIGraphicsGetCurrentContext() else { return }
ctx.saveGState()
ctx.setStrokeColor(
..
ctx.setBlendMode(.multiply) // review the choices available
..