[Tutorial] Handling Multitouch/Drawing Rounded Rect

Discussion in 'iOS Development' started by SkylarEC, Jan 19, 2009.

  1. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,642
    Likes Received:
    129

    Please Register or Log in to view images


    Some of you might want to do Multi Touch within your application, but are a little confused by Apple's tutorial at http://developer.apple.com/iphone. Well, I tried to simplify things a little bit. So I made a code that simply draws a rounded whose size is what you make with your fingers. Remember, you will need to optimize this for use in your own applications.

    A ready to compile link to this tutorial is included at the bottom of this post. Again, it was made to test something before this code was added to an app; so please ignore any sloppiness: as this was another five minute job.

    The first step is to create the view in which we will be working. Just create a new subclass of UIView called TouchView and fill it in with the following code. In the header file, we will only be creating two ivars, CGPoint touch1; and CGPoint touch2;

    Code:
    @implementation TouchView
    
    
    - (id)initWithFrame:(CGRect)frame {
        if (self = [super initWithFrame:frame]) {
    		[self setMultipleTouchEnabled:YES];
        }
        return self;
    }
    
    
    - (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { 
    	NSArray *allTouches = [touches allObjects]; 
    	int count = [allTouches count]; 
    	if (count > 0) 
    		touch1 = [[allTouches objectAtIndex:0] locationInView:self]; 
    	if (count > 1) 
    		touch2 = [[allTouches objectAtIndex:1] locationInView:self]; 
    	
    	[self setNeedsDisplay]; 
    } 
    
    
    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    	
    	NSArray *allTouches = [touches allObjects]; 
    	int count = [allTouches count]; 
    	if (count > 0) 
    		touch1 = [[allTouches objectAtIndex:0] locationInView:self]; 
    	if (count > 1) 
    		touch2 = [[allTouches objectAtIndex:1] locationInView:self]; 
    	
    	[self setNeedsDisplay]; 
    	
    }
    
    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    	
    }
    
    - (void) drawRect:(CGRect)rect {
    	CGContextRef context = UIGraphicsGetCurrentContext(); 
    	CGContextClearRect(context, rect); 
    	CGContextSetLineWidth(context, 3.0f);
    	CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
    	CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 1.0); 	
    	CGRect drawrect = CGRectMake(touch1.x, touch1.y, touch2.x - touch1.x, touch2.y - touch1.y);
    	CGFloat radius = 10.0;	
    	CGFloat minx = CGRectGetMinX(drawrect), midx = CGRectGetMidX(drawrect), maxx = CGRectGetMaxX(drawrect);
    	CGFloat miny = CGRectGetMinY(drawrect), midy = CGRectGetMidY(drawrect), maxy = CGRectGetMaxY(drawrect);	
    	CGContextMoveToPoint(context, minx, midy);
    	CGContextAddArcToPoint(context, minx, miny, midx, miny, radius);
    	CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius);
    	CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius);
    	CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius);
    	CGContextClosePath(context);
    	CGContextDrawPath(context, kCGPathFillStroke);
    }
    
    
    - (void)dealloc {
        [super dealloc];
    }
    
    
    @end
    

    If you notice, the first thing we do when we create out view is setMultitouchEnabled. We don't need to do anything else at this point, but feel free to if you should like. What we are going to focus on is the touchesBegan and touchesMoved events. We don't need to worry about touchesEnded.

    Also, in this case, we are only drawing and creating a rounded rect with multitouch events, so we will not worry about taps, etc. Start by creating an NSArray of your UITouches from the NSSet that is passed to us when the touch methods are envoked. Immediately, count that array. If the count of your array is greater than zero, then you know you are touching. Set the location of the touch in your array at index:0 as your touch1 point. It is where the first finger touched. If the array is still larger still, then another finger has touched. We'll set our second point to the value of the second touch in your array index:1. Finally, we will need to tell our view that we will be updating its contents. Use [self setNeedsDisplay]; to do that.

    That covers your mouse down. The good news is that the mouseMoved is the exact same thing. You can either repeat the method, as I did in the example, or call [self touchesBegan:touches withEvent:event]; in your touchedMoved method. Whichever you prefer.

    [self setNeedsDisplay] causes the view to recall its - (void)drawRect

    Please Register or Log in to view images

    CGRect)rect; method. In it, we will draw our rounded rect based on the points gathered with the touches.

    Start by getting the current context and clearing our working space. We'll set a line width to 3 pixels. This is the outline of our rounded rect, as seen in the screenshot above. We'll set our line color to white and our fill color to red. The fill color is the color we will be painting our rounded rect.

    Next, define the rect of our rectangle using the points we gathered before. The touch points. Define a radius for our corners, 10px is pretty good. Now, determine the left, center, right edges of our box (x values) and the bottom, middle, and top of our box (y values).

    Let's move to our starting point now, minx/miny. We'll add some arcs and close our path off and draw our rounded rect. That's it. you now have a rounded rect the size you defined with your multiple touches.


    For a simple example, this gets the point across. Obviously, when you go to add this to your application, you will want to add code to check for more than two fingers. Also--and this is crucial for your users' experience--add some code to make sure that your rounded rect's height and/or width isn't smaller than your rect's corner radius.

    Enjoy!



    LINK: http://www.touchrepo.com/SampleCode/TEST_MULTITOUCH_APP.zip
  2. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,642
    Likes Received:
    129
    Challenge time: Recreate this image:

    Please Register or Log in to view images

    ;

    The background is straight up blue, the foreground is dark gray with the alpha set to 0.75. Specifically, it is red: 0.33, blue: 0.33, green: 0.33, alpha: 0.75.

    What you are looking at is a cutout using the above multi touch routines (and is in fact the thing I was testing with this test app).

    Where could you use this? All over the freakin' place. You see it in AlertViews when you need to scroll: through text, tables, etc.
  3. cocotutch

    cocotutch Community Development Team Staff Member

    Joined:
    Oct 6, 2008
    Messages:
    1,285
    Likes Received:
    117
    Device:
    5G iPod touch
    Hey, I really like that Tut!!!!!

    Any info on how I could manipulate that code to spin around a UIImageView with my Two Fingers?

    Cheers,
  4. centroid

    centroid New Member

    Joined:
    Nov 12, 2007
    Messages:
    405
    Likes Received:
    0
    Device:
    iPad 2 (Black)
    Reminds me of the paint applications.

    I really appreciate your time and effort in posting these tutorials. Just wanted to reply as don't see many others. Thanks again for posting these tutorials and helping those who are just beginning.
  5. danti

    danti New Member

    Joined:
    Jan 22, 2009
    Messages:
    1
    Likes Received:
    0
    how do i start, im so confused
  6. JoshuaCaputo

    JoshuaCaputo New Member

    Joined:
    Aug 2, 2008
    Messages:
    605
    Likes Received:
    0
    Device:
    iPod touch
    I don't think god would be very happy to hear you are taking his spot

    Please Register or Log in to view images

Share This Page