Dynamic rounded rect drawing w/Multitouch
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.–I made a code sample that simply draws a rounded rect whose size is what you make with your fingers. Remember, you will need to optimize this for use in your own applications. Also, 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;
@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:(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!
Download link: http://www.touchrepo.com/SampleCode/TEST_MULTITOUCH_APP.zip
More comments: ipodtouchfans.com
Comments
2 Comments on Dynamic rounded rect drawing w/Multitouch
-
rahulvyas on
Wed, 30th Sep 2009 11:58 pm
-
Collateral on
Thu, 12th Nov 2009 1:52 pm
your tutorial is great.but sometimes the rectangle disappears…could you tell me some modification in your code so that it first it shows a crosshair like in photoshop.then we drag n resize it.
[WORDPRESS HASHCASH] The poster sent us ‘0 which is not a hashcash value.
Thank you. This tut helped me figure out multitouch, which ive been trying to figure out for a while.
Tell me what you're thinking...
and oh, if you want a pic to show with your comment, go get a gravatar!

