Permalink
Browse files

update with multi-touch sample code

  • Loading branch information...
1 parent ddfb9cd commit 6f676d50c211528f128362774de1a42a7cb72907 @kailoa committed Mar 27, 2009
@@ -17,15 +17,24 @@
@interface TouchSampleCodeViewController : UIViewController
{
- IBOutlet UIView *TapAndHoldView;
- IBOutlet UIView *TapAndHoldWithDelayView;
- NSTimer *TouchHoldTimer; ///< Main Timer
- NSInteger TouchAndHoldCounter; ///< Used for informational purposes only.
- NSDate *FirstTouchTime; ///< Array of vertices to be pushed around by the user
+ // Tap and hold
+ IBOutlet UIView *TapAndHoldView; ///< This view is rotated after when a user tap and holds.
+ IBOutlet UIView *TapAndHoldWithDelayView; ///< This view is rotated after a short delay.
+ NSTimer *TouchHoldTimer; ///< Main Timer
+ NSInteger TouchAndHoldCounter; ///< Used for informational purposes only.
+ NSDate *FirstTouchTime; ///< Used for informational purposes only.
- IBOutlet UIView *DoubleTapAndHoldView;
- NSInteger DoubleTapAndHoldCounter;
- NSDate *DoubleTapTime;
+ // Double tap and hold
+ IBOutlet UIView *DoubleTapAndHoldView; ///< This view is rotated after a double tap and hold.
+ NSInteger DoubleTapAndHoldCounter; ///< Used for informational purposes only.
+ NSDate *DoubleTapTime; ///< Used for informational purposes only.
+
+ // Tracking All touches
+ NSMutableArray *ActiveTouches; ///< Used to keep track of all current touches.
+
+ // Pinch and Zoom
+ IBOutlet UIView *PinchAndStretchView; ///< View to demo pinch and stretch.
+ CGSize OriginalDifference; ///< Used for calulating the relative difference between two multi-taps for pinch/strech and zoom/unzoom
}
@end
@@ -13,6 +13,7 @@
#import "TouchSampleCodeViewController.h"
#define kTouchUpdateTimer (1.0/15.0)
+#define kRotateAngleInRadians 0.1
@implementation TouchSampleCodeViewController
@@ -29,6 +30,9 @@ - (void)didReceiveMemoryWarning {
- (void)dealloc {
[TouchHoldTimer invalidate];
TouchHoldTimer = nil;
+ [FirstTouchTime release];
+ [DoubleTapTime release];
+ [ActiveTouches release];
[super dealloc];
}
@@ -45,25 +49,57 @@ - (void)viewDidLoad
/*********************************************************************/
#pragma mark -
#pragma mark ** Utilities **
+
+CGSize CGSizeDistanceBetween2Points(CGPoint point1, CGPoint point2)
+{
+ return CGSizeMake(point1.x -point2.x, point1.y - point2.y);
+}
+
+/*********************************************************************/
+#pragma mark -
+#pragma mark ** Touch Timer Methods **
+- (void)touchIsBeingPinchedOrStretched:(NSSet *)touches;
+{
+ // calculate the distance between the two touches
+ CGSize difference = CGSizeDistanceBetween2Points([[ActiveTouches objectAtIndex:0] locationInView:self.view],
+ [[ActiveTouches objectAtIndex:1] locationInView:self.view]);
+ CGFloat x_scale_factor = OriginalDifference.width/difference.width;
+ CGFloat y_scale_factor = OriginalDifference.height/difference.height;
+ NSLog(@"Scale Factor: %x:f, y:%f", x_scale_factor, y_scale_factor);
+
+ // modify the transform in order to scale the view
+ PinchAndStretchView.transform = CGAffineTransformScale(CGAffineTransformIdentity,
+ x_scale_factor,
+ y_scale_factor);
+}
- (void)touchIsBeingHeldWithTimer:(NSTimer *)timer;
{
NSSet *touches = [timer userInfo];
NSInteger count = [[touches anyObject] tapCount];
NSTimeInterval hold_time = -1*[FirstTouchTime timeIntervalSinceNow];
if (count == 1) {
TouchAndHoldCounter += 1;
- TapAndHoldView.transform = CGAffineTransformRotate(TapAndHoldView.transform, 0.1);
- NSLog(@"Held for %d counts and %g seconds.", TouchAndHoldCounter, hold_time);
+ TapAndHoldView.transform = CGAffineTransformRotate(TapAndHoldView.transform, kRotateAngleInRadians);
+// NSLog(@"Held for %d counts and %g seconds.", TouchAndHoldCounter, hold_time);
if (hold_time > HOLD_TIME_DELAY)
- TapAndHoldWithDelayView.transform = CGAffineTransformRotate(TapAndHoldWithDelayView.transform, 0.1);
+ TapAndHoldWithDelayView.transform = CGAffineTransformRotate(TapAndHoldWithDelayView.transform, kRotateAngleInRadians);
}
else if (count == 2) {
DoubleTapAndHoldCounter += 1;
- DoubleTapAndHoldView.transform = CGAffineTransformRotate(DoubleTapAndHoldView.transform, -0.1);
- NSLog(@"Held for %d counts and %g seconds.", DoubleTapAndHoldCounter, -1*[DoubleTapTime timeIntervalSinceNow]);
+ DoubleTapAndHoldView.transform = CGAffineTransformRotate(DoubleTapAndHoldView.transform, -1 * kRotateAngleInRadians);
+// NSLog(@"Held for %d counts and %g seconds.", DoubleTapAndHoldCounter, -1*[DoubleTapTime timeIntervalSinceNow]);
}
}
+- (void)cleanupTimers;
+{
+ [TouchHoldTimer invalidate];
+ TouchHoldTimer = nil;
+ [FirstTouchTime release];
+ FirstTouchTime = nil;
+ [DoubleTapTime release];
+ DoubleTapTime = nil;
+}
/*********************************************************************/
#pragma mark -
@@ -72,39 +108,65 @@ - (void)touchIsBeingHeldWithTimer:(NSTimer *)timer;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
METHOD_LOG;
- //Start touch timer
- TouchAndHoldCounter = 0.0;
- FirstTouchTime = [[NSDate alloc] init];
- TouchHoldTimer = [NSTimer scheduledTimerWithTimeInterval:kTouchUpdateTimer
- target:self
- selector:@selector(touchIsBeingHeldWithTimer:)
- userInfo:touches
- repeats:YES];
- if ([[touches anyObject] tapCount] == 2)
- DoubleTapTime = [[NSDate alloc] init];
+ OBJECT_LOG(touches);
+
+ // NSSet *touches is the set of touches that began now. We want to
+ // keep track of ALL touches, including touches that may have began
+ // sometime ago. We have our own NSMutableArray* ActiveTouches to
+ // do so.
+ if (ActiveTouches == nil)
+ ActiveTouches = [[NSMutableArray alloc] init];
+
+ for (UITouch *touch in touches) {
+ if (![ActiveTouches containsObject:touch])
+ [ActiveTouches addObject:touch];
+ }
+
+ if ([ActiveTouches count] == 1) { //single touch
+ //Start touch timer
+ TouchAndHoldCounter = 0.0;
+ FirstTouchTime = [[NSDate alloc] init];
+ TouchHoldTimer = [NSTimer scheduledTimerWithTimeInterval:kTouchUpdateTimer
+ target:self
+ selector:@selector(touchIsBeingHeldWithTimer:)
+ userInfo:touches
+ repeats:YES];
+ if ([[touches anyObject] tapCount] == 2)
+ DoubleTapTime = [[NSDate alloc] init];
+ } else if ([ActiveTouches count] == 2) { //two finger touch
+ OriginalDifference = CGSizeDistanceBetween2Points([[ActiveTouches objectAtIndex:0] locationInView:self.view],
+ [[ActiveTouches objectAtIndex:1] locationInView:self.view]);
+ }
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
- METHOD_LOG;
-}
-- (void)cleanup;
-{
- [TouchHoldTimer invalidate];
- TouchHoldTimer = nil;
- [FirstTouchTime release];
- FirstTouchTime = nil;
- [DoubleTapTime release];
- DoubleTapTime = nil;
+ if ([ActiveTouches count] == 1) { //single touch
+ // do nothing
+ } else if ([ActiveTouches count] == 2) { //two finger touch
+ [self cleanupTimers];
+ [self touchIsBeingPinchedOrStretched:touches];
+ }
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
-{
+{
METHOD_LOG;
- [self cleanup];
+ OBJECT_LOG(touches);
+ for (UITouch *touch in touches) {
+ [ActiveTouches removeObject:touch];
+ }
+ [self cleanupTimers];
+
+ if ([touches count] == 1) { //single touch
+ // do nothing
+ } else if ([touches count] == 2) { //two finger touch
+ //
+ }
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
METHOD_LOG;
- [self cleanup];
+ [self cleanupTimers];
+ [ActiveTouches removeAllObjects];
}
@end
@@ -31,7 +31,11 @@ - (void)dealloc {
#pragma mark -
#pragma mark ** Touch Handlers **
-//For the purpose of this sample code, we are just forwarding all the touch handlers to the view controller for processing.
+// For the purpose of this sample code, we are just forwarding all the touch
+// handlers to the view controller for processing. This is not normal and
+// actually breaks _some_ MVC patterns. Conversely, in some apps, it makes
+// sense to compartmentalize touch handling with the controllers.
+
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[ViewController touchesBegan:touches withEvent:event];
View
@@ -26,6 +26,18 @@
#define OBJECT_LOG(object) (NSLog(@"" #object @" %@",[object description] ));
#endif
+#if !defined(POINTLOG) //one argument
+#define POINTLOG(point) (NSLog(@"" #point @" x:%f y:%f", point.x, point.y ));
+#endif
+
+#if !defined(SIZELOG) //one argument
+#define SIZELOG(size) (NSLog(@"" #size @" width:%f height:%f", size.width, size.height ));
+#endif
+
+#if !defined(RECTLOG) //one argument
+#define RECTLOG(rect) (NSLog(@"" #rect @" x:%f y:%f w:%f h:%f", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height ));
+#endif
+
#if !defined(SELECTOR_LOG) //No arguments
#define SELECTOR_LOG (NSLog(@"%@ in %s", NSStringFromSelector(_cmd), __FILE__));
#endif
@@ -57,15 +69,3 @@
#if !defined(MSG_ASSERT_TRUE) //two arguments, if the argument is false, raise the assert and display the message
#define MSG_ASSERT_TRUE(test, msg) NSAssert5(test, @"\n\n **** Unexpected Assertion **** \nReason: %@\nAssertion in file:%s at line %i in Method %@ with object:\n %@", msg, __FILE__, __LINE__, NSStringFromSelector(_cmd), self)
#endif
-
-#if !defined(POINTLOG) //one argument
-#define POINTLOG(point) (NSLog(@"" #point @" x:%f y:%f", point.x, point.y ));
-#endif
-
-#if !defined(SIZELOG) //one argument
-#define SIZELOG(size) (NSLog(@"" #size @" width:%f height:%f", size.width, size.height ));
-#endif
-
-#if !defined(RECTLOG) //one argument
-#define RECTLOG(rect) (NSLog(@"" #rect @" x:%f y:%f w:%f h:%f", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height ));
-#endif
Oops, something went wrong.

0 comments on commit 6f676d5

Please sign in to comment.