Question

I know there are better ways to achieve drawing tools using CoreGraphics and what-not, I'm using this UIView method because I want to achieve a pixelated effect and I have some other custom stuff in mind that would be difficult to do with just the built in CG code.



I have a grid of 400 UIViews to create my pixelated canvas...
The user selects a paint color and begins to drag their finger over the canvas of 400 UIViews, as their finger hits a UIView the color of that UIView (aka pixel) will change to the color the user has selected...

Right now I have coded the whole thing and everything is working but it is laggy (because I am using touchesMoved) and many points are skipped...



I am currently using touchesMoved and am moving a UIView to the fingers location(I am calling this the fingerLocationRect).

When I update a pixel's (1 of 400 miniature UIViews) color I am doing so by checking if the fingerLocationRect is intersection any one of my UIView rects. If they are I update the color.

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint currentPosition = [touch locationInView:self.view];
    fingerLocationRect.center = CGPointMake(currentPosition.x, currentPosition.y);
    int tagID = 1;
    while (tagID <= 400) {
        if(CGRectIntersectsRect(fingerLocationRect.frame, [drawingView viewWithTag:tagID].frame)) {
            [drawingView viewWithTag:tagID].backgroundColor = [UIColor colorWithRed:redVal/255.f green:greenVal/255.f blue:blueVal/255.f alpha:1.f];
        }
        tagID ++;
    }
}



The problem is that touchesMoved is not updated very often... so if I drag my finger across the canvas only like 5 of the pixels change instead of the 40 I actually touched.



I'm wondering if using CGRectIntersectsRect with touchesMoved is the best method to detect if the user slides of a UIView... Right now it is not updating nearly fast enough and I am getting the result on the left instead of the result on the right. (I only achieve the effect on the right if I move my finger VERY slowly...)

enter image description here



All that said, is there a method for detecting when a user slides over a UIView other than using touchesMoved? If not, any ideas on how to grab all of the UIViews in-between the touch locations returned by touchesMoved? I have them all having tags of 1-400 (the first row is 1-10, second row is 11-21, etc.)

P.s. if a panGestureRecognizer updated more frequently than a touchesMoved?


To get an idea of what the 400 UIViews look like here they all are with arc4random based colors:

enter image description here



Was it helpful?

Solution

You are looping through 400 views every time touchesMoved: is called. You just need to do a little math to determine which view in the grid is being touched. Assuming that drawingView is the "canvas" view that contains all 400 "pixels" and the tags are ordered from the top-left to the bottom-right then:

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];    
    CGPoint point = [touch locationInView:drawingView];
    NSInteger column = floorf(20 * point.x / drawingView.bounds.size.width); //20 is the number of column in the canvas
    NSInteger row = floorf(20 * point.y / drawingView.bounds.size.height); //20 is the number of rows in the canvas
    [viewWithTag:column + 20*row].backgroundColor = [UIColor colorWithRed:redVal/255.f green:greenVal/255.f blue:blueVal/255.f alpha:1.f];
}

This method performance improvement will allow cocoa to make more frequent calls to touchesMoved:

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top