Search code examples
iosuiimageviewuiimagetransparencyalpha

How to make UIImage fully opaque so that nothing shows through from the background?


I have a UIImageView that I am making a child view of a larger UILabel, using addSubview:. Part of the image (a PNG -- using UIImage) has a transparent background and part of it does not. This is because the image is a circle and I want any background that is outside the circle to show through and be visible. But I want the circular image itself to be drawn over everything. Yet what I am getting looks like this:

enter image description here

Notice that the border from the rectangle of the parent view shows through even though the circle's green inside is drawn over the grey background. I want none of the UILabel's rectangular border to be showing through the circle.

Perhaps this is a problem with my image. I used the Paintbrush app on MacOS to modify a png that I had, but I'm not good at image editing. I have UIImageView's alpha set to 1.0 and opaque set to YES. I construct and add the UIImageView as a subview to the UILabel like this:

NSArray *subViews = [self subviews];
for (UIView *view in subViews) {
    if ([view isKindOfClass:[UILabel class]]) {
        UILabel *lblPad = (UILabel*)view;
        CGRect frame = CGRectMake(lblPad.frame.size.width - 14, -11, 25, 25);
        UIImageView *badge = [self constructBadge:frame];
        [lblPad addSubview:badge];
    }
}

-(UIImageView*)constructBadge:(CGRect)frameIn
{    
    UIImageView *ivRet = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"icon_check_circle_mod2.png"]];
    ivRet.frame = frameIn;
    ivRet.userInteractionEnabled = NO;
    [ivRet setAlpha:1.0];
    [ivRet setOpaque:YES];

    return ivRet;
}

The png image I am using is:

enter image description here

Another I have tried which behaves the same is here:

enter image description here

How to fix this?

[EDIT -- NEW DEVELOPMENT]

I discovered that one line of code is directly related to, perhaps causing, this. I am setting a border around each UILabel on the view, with the following code:

NSArray *subViews = [self subviews];
self.dictAllLabels = [NSMutableDictionary dictionary];
for (UIView *view in subViews) {
    if ([view isKindOfClass:[UILabel class]]) {
        UILabel *lblPad = (UILabel*)view;
        CALayer *layer = [lblPad layer];
        //[layer setBorderWidth:1.0];
        [layer setBorderColor:[[UIColor darkGrayColor] CGColor]];
    }
}

If I comment out the setBorderWidth: call the circular image appears correctly. If I uncomment it out the problem occurs. So my question should have been, "Why does changing the border width on the CALayer of the label make the subview semi-transparent?"


Solution

  • You have explained the source of the issue perfectly! The problem, however, is not that the circle image view is transparent. The problem is that the border is effectively front of it. That's because of the relationship between the circle view, as a subview of the label, and the border drawing. And that is because a subview of a view is a sublayer of that view's layer.

    The solution is simply to make the circle image view not a subview of the label.

    CGRect labFrame = lblPad.frame;
    CGRect frame = CGRectMake(
        labFrame.origin.x + labFrame.size.width - 14, 
        labFrame.origin.y - 11, 
        25,
        25
    );
    UIImageView *badge = [self constructBadge:frame];
    [self addSubview:badge];