Home > Articles > Programming > General Programming/Other Languages

  • Print
  • + Share This
From the author of

Implementing the TOUCHkit Overlay View

The TOUCHkit overlay is a single clear UIView singleton. It's created the first time the application requests its shared instance, and the call adds it to the application's key window. The overlay's user interaction flag is disabled, allowing touches to continue on through the responder chain, even after processing those touches through the standard began/moved/ended/canceled event callbacks.

Listing 2

+ (id) sharedInstance
{
    // Create shared instance if it does not yet exist
    if(!sharedInstance)
    {
        sharedInstance = [[self alloc] 
            initWithFrame:CGRectZero];
    }
    
    // Parent it to the key window
    if (!sharedInstance.superview)
    {
        UIWindow *keyWindow= 
            [UIApplication sharedApplication].keyWindow;
        sharedInstance.frame = keyWindow.bounds;
        [keyWindow addSubview:sharedInstance];
    }
    
    return sharedInstance;
}


// You can override the default color if you want using 
// touchColor property
- (id) initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame])
    {
        self.backgroundColor = [UIColor clearColor];
        self.userInteractionEnabled = NO;
        self.multipleTouchEnabled = YES;
        touchColor = [[UIColor whiteColor] 
            colorWithAlphaComponent:0.5f];
        touches = nil;
    }
    
    return self;
}

The touch processing events draw a circle at each touch point, creating a strong pointer to the touches until that drawing is complete. Here are the callback and drawing methods that handle that functionality.

Listing 3

// Basic Touches processing

- (void) touchesBegan:(NSSet *)theTouches 
       withEvent:(UIEvent *)event 
{
    touches = theTouches;
    [self setNeedsDisplay];
}

- (void) touchesMoved:(NSSet *)theTouches 
        withEvent:(UIEvent *)event 
{
    touches = theTouches;
    [self setNeedsDisplay];
}

- (void) touchesEnded:(NSSet *)theTouches 
        withEvent:(UIEvent *)event 
{
    touches = nil;
    [self setNeedsDisplay];
}

// Draw touches interactively
- (void) drawRect: (CGRect) rect
{
    // Clear
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextClearRect(context, self.bounds);
    
    // Fill see-through
    [[UIColor clearColor] set];
    CGContextFillRect(context, self.bounds);
    
    float size = 25.0f; // based on 44.0f standard touch point
    
    for (UITouch *touch in touches)
    {
        // Create a backing frame
        [[[UIColor darkGrayColor] colorWithAlphaComponent:0.5f] set];
        CGPoint aPoint = [touch locationInView:self];
        CGContextAddEllipseInRect(context, 
            CGRectMake(aPoint.x - size, aPoint.y - size, 
                2 * size, 2 * size));
        CGContextFillPath(context);
        
        // Draw the foreground touch
        float dsize = 1.0f;
        [touchColor set];
        aPoint = [touch locationInView:self];
        CGContextAddEllipseInRect(context, 
            CGRectMake(aPoint.x - size - dsize, 
                aPoint.y - size - dsize, 
                2 * (size - dsize), 2 * (size - dsize)));
        CGContextFillPath(context);
    }

    // Reset touches after use
    touches = nil;
}
  • + Share This
  • 🔖 Save To Your Account