Search code examples
iosuitoolbar

Creating an overlapping semi-transparent toolbar button that doesn't get bisected by tool bar


I'm creating a user interface with a green, oversized camera start/stop button that sits atop a toolbar:

UI Screenshot

Thus far, I've been using yoichitgy/EEToolbarCenterButton to implement this, and it seemed like exactly what I wanted at first.

The UI designer has specifically asked for the button to be transparent. They also want the toolbar behind it to be "cut out" in such a way that you don't see the toolbar behind the button. This is an illustration of how the button should work.

This is an illustration of how the button should work.

Here is an illustration of what they do not want:

This is an illustration of what I'm not supposed to do.

So is there anyway to do this? Oh yeah, one more thing: once this green button is pressed, it changes into a "Stop" button that is much smaller. The stop button should not be semi-transparent and the bar behind it should not have a chunk missing. In other words, I need to be able to turn this behavior on and off.


Solution

  • I ended up solving this issue myself by creating a custom UIToolbar class:

    DLYCustomToolbar.h

    #import <UIKit/UIKit.h>
    #import "UIToolbar+EEToolbarCenterButton.h"
    
    @interface DLYCustomToolbar : UIToolbar
    
    @property (nonatomic) bool isMasked;
    
    @end
    

    DLYCustomToolbar.m:

    #import "DLYCustomToolbar.h"
    
    @implementation DLYCustomToolbar
    
    - (void) drawRect:(CGRect)rect {
        [[UIColor colorWithRed:0 green:0 blue:0 alpha:0.5] setFill];
        UIRectFill(rect);
    
        CGContextRef context = UIGraphicsGetCurrentContext();
    
        CGContextSetBlendMode(context, kCGBlendModeClear);
    
        if(_isMasked) {
            float circleDiameter = 58;
            CGRect pathRect = CGRectMake(self.frame.size.width/2-circleDiameter/2, -circleDiameter/2+2, circleDiameter, circleDiameter);
            UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:pathRect];
            [path fill];
        }
    
        CGContextSetBlendMode(context, kCGBlendModeNormal);
    }
    
    - (void) setIsMasked:(bool)isMasked {
        if (isMasked != _isMasked) {
            _isMasked = isMasked;
            [self setNeedsDisplay];
        }
    }
    
    @end