设置CGContext透明背景

57

我仍然在努力使用CGContext绘制一条线。我已经得到了要绘制的线条,但是现在我需要矩形的背景透明,以便现有的背景可以透过来显示。这是我的测试代码:

(void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor);
    CGContextSetAlpha(context,0.0);
    CGContextFillRect(context, rect);

    CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
    CGContextSetLineWidth(context, 5.0);
    CGContextMoveToPoint(context, 100.0,0.0);
    CGContextAddLineToPoint(context,100.0, 100.0);
    CGContextStrokePath(context);
}

有什么想法吗?

8个回答

75

在调用UIGraphicsGetCurrentContext()后,调用CGContextClearRect(context,rect)

编辑: 好的,明白了。

你的自定义视图应该包含以下内容:

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self setBackgroundColor:[UIColor clearColor]];
    }
    return self;
}

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextClearRect(context, rect);
    CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
    CGContextSetLineWidth(context, 5.0);
    CGContextMoveToPoint(context, 100.0,0.0);
    CGContextAddLineToPoint(context,100.0, 100.0);
    CGContextStrokePath(context);
}

我的测试使用了这个非常基本的UIViewController:

- (void)viewDidLoad {
    [super viewDidLoad];
    UIImageView *v = [[UIImageView alloc] initWithFrame:self.view.bounds];
    [v setBackgroundColor:[UIColor redColor]];
    [self.view addSubview:v];
    TopView *t = [[TopView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:t];
    [v release];
    [t release];
}

8
背景是黑色,应该是 iPhone 的背景。我实际上是想在一个 UIView 上面画图。 - Jim B
我不太明白。你确定已经将UIView添加到了父视图中吗?这个drawRect是在你想要绘制的UIView上面,还是在另一个UIView上面?你是否意外地为这个UIView设置了背景颜色? - David Kanarek
谢谢你的问题。我希望IM已经将UIView添加到了它的父视图中。绘制矩形肯定是在视图中进行的,因为线条已经正确地绘制出来了。是的,我已经设置了一个背景到UIView中,我想展示的就是这个背景。我只是想在现有视图的顶部画一条线。在西雅图感到沮丧。 - Jim B
这里不能使用Clear Rect。 - Stephen J

45

简单易行的方法:

- (id)initWithFrame:(CGRect)frame
{
    if ((self = [super initWithFrame:frame]))
    {       
        self.opaque = NO;
    }
    return self;
}

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextClearRect(context, rect);
    //your code
}

4
我将在表视图单元格中使用这个作为一个配件指示器。self.opaque = NO 可以起作用,而接受的答案中 [self setBackgroundColor:[UIColor clearColor]] 却不能。 - T.J.
self.opaque = false 在创建自定义 UICollectionViewCell 的子视图时帮了我很大的忙。 - ae14
1
这应该是一个被接受的答案。self.opaque = NO 可以使使用 drawRect 方法绘制的视图透明。谢谢! - Michael

7

使用 opaque == false 初始化上下文,Swift 3

UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale) 

不透明

一个布尔标志,指示位图是否是不透明的。如果您知道位图是完全不透明的,请指定true以忽略alpha通道并优化位图的存储。指定false意味着位图必须包括一个alpha通道来处理任何部分透明的像素。


这也是我的问题。尽管isOpaque为true,屏幕上的图层仍然是透明的。因此,我将self.isOpaque作为第二个参数删除了,并想知道生成的UIImage为什么不是不透明的。 - heyfrank
不要忘记关闭上下文以避免内存泄漏:UIGraphicsEndImageContext() - Bocaxica

4

以下是我用于处理使用InterfaceBuilder手动添加的UIImage时起作用的内容。

- (id)initWithCoder:(NSCoder *)aDecoder {

    if(self = [super initWithCoder:aDecoder]) {
        self.backgroundColor = [UIColor clearColor];
    }

    return self;
}


-(void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();    
    CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
    CGContextSetLineWidth(context, 5.0);
    CGContextMoveToPoint(context, 100.0,0.0);
    CGContextAddLineToPoint(context,100.0, 100.0);
    CGContextStrokePath(context);
}

当你手动创建自己的UIImageView时,David Kanarek的答案是有效的。如果你已经通过界面生成器手动添加了一个UIView,则需要使用不同的方法,如调用initWithCoder方法。


3

我有同样的问题,后来我发现原因是这样的。 我覆盖了init方法,即 -(id)initWithFrame:(CGRect)rect. 在这个方法中,我使用了 self.background = [UIColor clearColor]; 但是我在xib文件中使用了这个视图!!!这将调用init方法。

-(id)initWithCoder:(NSCoder*)aDecoder;

因此,覆盖所有的init方法并设置backgroundColor将会正常工作。


1
即使在xib中设置了,对我来说以上方法都不起作用,只有在代码中设置才有效。+1 - Stephen J

2
CGContextClearRect(context,rect) 

如果提供的上下文是窗口或位图上下文,则Quartz会有效地清除矩形。对于其他类型的上下文,Quartz以设备相关的方式填充矩形。但是,在除窗口或位图上下文以外的上下文中不应使用此函数。

1
您可以使用以下代码创建图像上下文:

cacheContext = CGBitmapContextCreate (cacheBitmap, size.width, size.height, 8, bitmapBytesPerRow, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaPremultipliedLast);
CGContextSetRGBFillColor(cacheContext, 0, 0, 0, 0);
CGContextFillRect(cacheContext, (CGRect){CGPointZero, size});

关键是 kCGImageAlphaPremultipliedLast。


0

在这里有些难以理解的问题,但是如果您无法让一个“背景”UIView显示在一个“顶部”视图中,而您正在该视图中进行绘制,则可以使用以下解决方案:topView.backgroundColor = [UIColor clearColor]; 我曾经遇到过(我认为)同样的问题,这个方法对我很有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接