mirror of
https://github.com/joeblau/COSTouchVisualizer.git
synced 2024-09-11 12:36:58 +03:00
Reformat code
This commit is contained in:
parent
d3d6c680b1
commit
5c4b5ddc09
@ -30,7 +30,7 @@
|
||||
@property (nonatomic, strong) UIWindow *overlayWindow;
|
||||
@property (nonatomic, assign) BOOL active;
|
||||
@property (nonatomic, assign) BOOL fingerTipRemovalScheduled;
|
||||
@property (nonatomic, strong) NSTimer* timer;
|
||||
@property (nonatomic, strong) NSTimer *timer;
|
||||
|
||||
- (void)COSTouchVisualizerWindow_commonInit;
|
||||
- (BOOL)anyScreenIsMirrored;
|
||||
@ -47,7 +47,6 @@
|
||||
|
||||
@implementation COSTouchVisualizerWindow
|
||||
|
||||
|
||||
@synthesize touchImage = _touchImage;
|
||||
@synthesize touchAlpha = _touchAlpha;
|
||||
@synthesize fadeDuration = _fadeDuration;
|
||||
@ -61,136 +60,140 @@
|
||||
@synthesize fingerTipRemovalScheduled = _fingerTipRemovalScheduled;
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)decoder {
|
||||
// This covers NIB-loaded windows.
|
||||
self = [super initWithCoder:decoder];
|
||||
if (self != nil) [self COSTouchVisualizerWindow_commonInit];
|
||||
return self;
|
||||
// This covers NIB-loaded windows.
|
||||
self = [super initWithCoder:decoder];
|
||||
if (self != nil)
|
||||
[self COSTouchVisualizerWindow_commonInit];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)rect {
|
||||
// This covers programmatically-created windows.
|
||||
self = [super initWithFrame:rect];
|
||||
if (self != nil) [self COSTouchVisualizerWindow_commonInit];
|
||||
return self;
|
||||
// This covers programmatically-created windows.
|
||||
self = [super initWithFrame:rect];
|
||||
if (self != nil)
|
||||
[self COSTouchVisualizerWindow_commonInit];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)COSTouchVisualizerWindow_commonInit {
|
||||
self.strokeColor = [UIColor blackColor];
|
||||
self.fillColor = [UIColor whiteColor];
|
||||
self.strokeColor = [UIColor blackColor];
|
||||
self.fillColor = [UIColor whiteColor];
|
||||
|
||||
self.rippleStrokeColor = [UIColor whiteColor];
|
||||
self.rippleFillColor = [UIColor blueColor];
|
||||
self.rippleStrokeColor = [UIColor whiteColor];
|
||||
self.rippleFillColor = [UIColor blueColor];
|
||||
|
||||
self.touchAlpha = 0.5;
|
||||
self.fadeDuration = 0.3;
|
||||
self.touchAlpha = 0.5;
|
||||
self.fadeDuration = 0.3;
|
||||
|
||||
self.rippleAlpha = 0.2;
|
||||
self.rippleFadeDuration = 0.2;
|
||||
self.rippleAlpha = 0.2;
|
||||
self.rippleFadeDuration = 0.2;
|
||||
|
||||
self.stationaryMorphEnabled = YES;
|
||||
self.stationaryMorphEnabled = YES;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(screenConnect:)
|
||||
name:UIScreenDidConnectNotification
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(screenConnect:)
|
||||
name:UIScreenDidConnectNotification
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(screenDisconnect:)
|
||||
name:UIScreenDidDisconnectNotification
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(screenDisconnect:)
|
||||
name:UIScreenDidDisconnectNotification
|
||||
object:nil];
|
||||
|
||||
// Set up active now, in case the screen was present before the window was created (or application launched).
|
||||
[self updateFingertipsAreActive];
|
||||
// Set up active now, in case the screen was present before the window was created (or application launched).
|
||||
[self updateFingertipsAreActive];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIScreenDidConnectNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIScreenDidDisconnectNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIScreenDidConnectNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIScreenDidDisconnectNotification object:nil];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (UIImage *)touchImage {
|
||||
if (!_touchImage) {
|
||||
UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 50.0, 50.0)];
|
||||
if (!_touchImage) {
|
||||
UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 50.0, 50.0)];
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(clipPath.bounds.size, NO, 0);
|
||||
UIGraphicsBeginImageContextWithOptions(clipPath.bounds.size, NO, 0);
|
||||
|
||||
UIBezierPath *drawPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(25.0, 25.0)
|
||||
radius:22.0
|
||||
startAngle:0
|
||||
endAngle:2 * M_PI
|
||||
clockwise:YES];
|
||||
UIBezierPath *drawPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(25.0, 25.0)
|
||||
radius:22.0
|
||||
startAngle:0
|
||||
endAngle:2 * M_PI
|
||||
clockwise:YES];
|
||||
|
||||
drawPath.lineWidth = 2.0;
|
||||
drawPath.lineWidth = 2.0;
|
||||
|
||||
[self.strokeColor setStroke];
|
||||
[self.fillColor setFill];
|
||||
[self.strokeColor setStroke];
|
||||
[self.fillColor setFill];
|
||||
|
||||
[drawPath stroke];
|
||||
[drawPath fill];
|
||||
[drawPath stroke];
|
||||
[drawPath fill];
|
||||
|
||||
[clipPath addClip];
|
||||
[clipPath addClip];
|
||||
|
||||
_touchImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
}
|
||||
return _touchImage;
|
||||
_touchImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
}
|
||||
return _touchImage;
|
||||
}
|
||||
|
||||
- (UIImage *)rippleImage {
|
||||
if (!_rippleImage) {
|
||||
UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 50.0, 50.0)];
|
||||
if (!_rippleImage) {
|
||||
UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 50.0, 50.0)];
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(clipPath.bounds.size, NO, 0);
|
||||
UIGraphicsBeginImageContextWithOptions(clipPath.bounds.size, NO, 0);
|
||||
|
||||
UIBezierPath *drawPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(25.0, 25.0)
|
||||
radius:22.0
|
||||
startAngle:0
|
||||
endAngle:2 * M_PI
|
||||
clockwise:YES];
|
||||
UIBezierPath *drawPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(25.0, 25.0)
|
||||
radius:22.0
|
||||
startAngle:0
|
||||
endAngle:2 * M_PI
|
||||
clockwise:YES];
|
||||
|
||||
drawPath.lineWidth = 2.0;
|
||||
drawPath.lineWidth = 2.0;
|
||||
|
||||
[self.rippleStrokeColor setStroke];
|
||||
[self.rippleFillColor setFill];
|
||||
[self.rippleStrokeColor setStroke];
|
||||
[self.rippleFillColor setFill];
|
||||
|
||||
[drawPath stroke];
|
||||
[drawPath fill];
|
||||
[drawPath stroke];
|
||||
[drawPath fill];
|
||||
|
||||
[clipPath addClip];
|
||||
[clipPath addClip];
|
||||
|
||||
_rippleImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
}
|
||||
return _rippleImage;
|
||||
_rippleImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
}
|
||||
return _rippleImage;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Screen notifications
|
||||
|
||||
- (void)screenConnect:(NSNotification *)notification {
|
||||
[self updateFingertipsAreActive];
|
||||
[self updateFingertipsAreActive];
|
||||
}
|
||||
|
||||
- (void)screenDisconnect:(NSNotification *)notification {
|
||||
[self updateFingertipsAreActive];
|
||||
[self updateFingertipsAreActive];
|
||||
}
|
||||
|
||||
- (BOOL)anyScreenIsMirrored {
|
||||
if (![UIScreen instancesRespondToSelector:@selector(mirroredScreen)]) return NO;
|
||||
if (![UIScreen instancesRespondToSelector:@selector(mirroredScreen)])
|
||||
return NO;
|
||||
|
||||
for (UIScreen *screen in [UIScreen screens]) {
|
||||
if ([screen mirroredScreen] != nil) return YES;
|
||||
}
|
||||
return NO;
|
||||
for (UIScreen *screen in [UIScreen screens]) {
|
||||
if ([screen mirroredScreen] != nil)
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)updateFingertipsAreActive; {
|
||||
- (void)updateFingertipsAreActive {
|
||||
#if DEBUG_FINGERTIP_WINDOW
|
||||
self.active = YES;
|
||||
self.active = YES;
|
||||
#else
|
||||
self.active = [self anyScreenIsMirrored];
|
||||
self.active = [self anyScreenIsMirrored];
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -198,211 +201,231 @@
|
||||
#pragma mark UIWindow overrides
|
||||
|
||||
- (void)sendEvent:(UIEvent *)event {
|
||||
if (self.active) {
|
||||
NSSet *allTouches = [event allTouches];
|
||||
for (UITouch *touch in [allTouches allObjects]) {
|
||||
switch (touch.phase) {
|
||||
case UITouchPhaseBegan:
|
||||
case UITouchPhaseMoved:
|
||||
{
|
||||
// Generate ripples
|
||||
COSTouchSpotView *rippleView = [[COSTouchSpotView alloc] initWithImage:self.rippleImage];
|
||||
[self.overlayWindow addSubview:rippleView];
|
||||
if (self.active) {
|
||||
NSSet *allTouches = [event allTouches];
|
||||
for (UITouch *touch in [allTouches allObjects]) {
|
||||
switch (touch.phase) {
|
||||
case UITouchPhaseBegan:
|
||||
case UITouchPhaseMoved: {
|
||||
// Generate ripples
|
||||
COSTouchSpotView *rippleView = [[COSTouchSpotView alloc] initWithImage:self.rippleImage];
|
||||
[self.overlayWindow addSubview:rippleView];
|
||||
|
||||
rippleView.alpha = self.rippleAlpha;
|
||||
rippleView.center = [touch locationInView:self.overlayWindow];
|
||||
rippleView.alpha = self.rippleAlpha;
|
||||
rippleView.center = [touch locationInView:self.overlayWindow];
|
||||
|
||||
[UIView animateWithDuration:self.rippleFadeDuration
|
||||
delay:0.0
|
||||
options:UIViewAnimationOptionCurveEaseIn // See other options
|
||||
animations:^{
|
||||
[rippleView setAlpha:0.0];
|
||||
[rippleView setFrame:CGRectInset(rippleView.frame, 25, 25)];
|
||||
}
|
||||
completion:^(BOOL finished) {
|
||||
[rippleView removeFromSuperview];
|
||||
}];
|
||||
}
|
||||
case UITouchPhaseStationary:
|
||||
{
|
||||
COSTouchSpotView *touchView = (COSTouchSpotView *)[self.overlayWindow viewWithTag:touch.hash];
|
||||
[UIView animateWithDuration:self.rippleFadeDuration
|
||||
delay:0.0
|
||||
options:UIViewAnimationOptionCurveEaseIn // See other options
|
||||
animations:^{
|
||||
[rippleView setAlpha:0.0];
|
||||
[rippleView setFrame:CGRectInset(rippleView.frame, 25, 25)];
|
||||
}
|
||||
completion:^(BOOL finished) { [rippleView removeFromSuperview]; }];
|
||||
}
|
||||
case UITouchPhaseStationary: {
|
||||
COSTouchSpotView *touchView = (COSTouchSpotView *)[self.overlayWindow viewWithTag:touch.hash];
|
||||
|
||||
if (touch.phase != UITouchPhaseStationary && touchView != nil && [touchView isFadingOut]) {
|
||||
[self.timer invalidate];
|
||||
[touchView removeFromSuperview];
|
||||
touchView = nil;
|
||||
}
|
||||
if (touch.phase != UITouchPhaseStationary && touchView != nil && [touchView isFadingOut]) {
|
||||
[self.timer invalidate];
|
||||
[touchView removeFromSuperview];
|
||||
touchView = nil;
|
||||
}
|
||||
|
||||
if (touchView == nil && touch.phase != UITouchPhaseStationary) {
|
||||
touchView = [[COSTouchSpotView alloc] initWithImage:self.touchImage];
|
||||
[self.overlayWindow addSubview:touchView];
|
||||
if (touchView == nil && touch.phase != UITouchPhaseStationary) {
|
||||
touchView = [[COSTouchSpotView alloc] initWithImage:self.touchImage];
|
||||
[self.overlayWindow addSubview:touchView];
|
||||
|
||||
if (self.stationaryMorphEnabled) {
|
||||
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.6 target:self selector:@selector(performMorph:) userInfo:touchView repeats:YES];
|
||||
if (self.stationaryMorphEnabled) {
|
||||
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.6
|
||||
target:self
|
||||
selector:@selector(performMorph:)
|
||||
userInfo:touchView
|
||||
repeats:YES];
|
||||
}
|
||||
}
|
||||
|
||||
if (![touchView isFadingOut]) {
|
||||
touchView.alpha = self.touchAlpha;
|
||||
touchView.center = [touch locationInView:self.overlayWindow];
|
||||
touchView.tag = touch.hash;
|
||||
touchView.timestamp = touch.timestamp;
|
||||
touchView.shouldAutomaticallyRemoveAfterTimeout =
|
||||
[self shouldAutomaticallyRemoveFingerTipForTouch:touch];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case UITouchPhaseEnded:
|
||||
case UITouchPhaseCancelled: {
|
||||
[self removeFingerTipWithHash:touch.hash animated:YES];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (![touchView isFadingOut]) {
|
||||
touchView.alpha = self.touchAlpha;
|
||||
touchView.center = [touch locationInView:self.overlayWindow];
|
||||
touchView.tag = touch.hash;
|
||||
touchView.timestamp = touch.timestamp;
|
||||
touchView.shouldAutomaticallyRemoveAfterTimeout = [self shouldAutomaticallyRemoveFingerTipForTouch:touch];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case UITouchPhaseEnded:
|
||||
case UITouchPhaseCancelled:
|
||||
{
|
||||
[self removeFingerTipWithHash:touch.hash animated:YES];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[super sendEvent:event];
|
||||
[super sendEvent:event];
|
||||
|
||||
[self scheduleFingerTipRemoval]; // We may not see all UITouchPhaseEnded/UITouchPhaseCancelled events.
|
||||
[self scheduleFingerTipRemoval]; // We may not see all UITouchPhaseEnded/UITouchPhaseCancelled events.
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Private
|
||||
|
||||
- (UIWindow *)overlayWindow {
|
||||
if (!_overlayWindow) {
|
||||
_overlayWindow = [[UIWindow alloc] initWithFrame:self.frame];
|
||||
_overlayWindow.userInteractionEnabled = NO;
|
||||
_overlayWindow.windowLevel = UIWindowLevelStatusBar;
|
||||
_overlayWindow.backgroundColor = [UIColor clearColor];
|
||||
_overlayWindow.hidden = NO;
|
||||
}
|
||||
if (!_overlayWindow) {
|
||||
_overlayWindow = [[UIWindow alloc] initWithFrame:self.frame];
|
||||
_overlayWindow.userInteractionEnabled = NO;
|
||||
_overlayWindow.windowLevel = UIWindowLevelStatusBar;
|
||||
_overlayWindow.backgroundColor = [UIColor clearColor];
|
||||
_overlayWindow.hidden = NO;
|
||||
}
|
||||
|
||||
return _overlayWindow;
|
||||
return _overlayWindow;
|
||||
}
|
||||
|
||||
- (void)scheduleFingerTipRemoval {
|
||||
if (self.fingerTipRemovalScheduled) return;
|
||||
self.fingerTipRemovalScheduled = YES;
|
||||
[self performSelector:@selector(removeInactiveFingerTips) withObject:nil afterDelay:0.1];
|
||||
if (self.fingerTipRemovalScheduled)
|
||||
return;
|
||||
self.fingerTipRemovalScheduled = YES;
|
||||
[self performSelector:@selector(removeInactiveFingerTips) withObject:nil afterDelay:0.1];
|
||||
}
|
||||
|
||||
- (void)cancelScheduledFingerTipRemoval {
|
||||
self.fingerTipRemovalScheduled = YES;
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(removeInactiveFingerTips) object:nil];
|
||||
self.fingerTipRemovalScheduled = YES;
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(removeInactiveFingerTips) object:nil];
|
||||
}
|
||||
|
||||
- (void)removeInactiveFingerTips {
|
||||
self.fingerTipRemovalScheduled = NO;
|
||||
self.fingerTipRemovalScheduled = NO;
|
||||
|
||||
NSTimeInterval now = [[NSProcessInfo processInfo] systemUptime];
|
||||
const CGFloat REMOVAL_DELAY = 0.2;
|
||||
NSTimeInterval now = [[NSProcessInfo processInfo] systemUptime];
|
||||
const CGFloat REMOVAL_DELAY = 0.2;
|
||||
|
||||
for (COSTouchSpotView *touchView in [self.overlayWindow subviews]) {
|
||||
if (![touchView isKindOfClass:[COSTouchSpotView class]]) continue;
|
||||
for (COSTouchSpotView *touchView in [self.overlayWindow subviews]) {
|
||||
if (![touchView isKindOfClass:[COSTouchSpotView class]])
|
||||
continue;
|
||||
|
||||
if (touchView.shouldAutomaticallyRemoveAfterTimeout && now > touchView.timestamp + REMOVAL_DELAY)
|
||||
[self removeFingerTipWithHash:touchView.tag animated:YES];
|
||||
}
|
||||
if (touchView.shouldAutomaticallyRemoveAfterTimeout && now > touchView.timestamp + REMOVAL_DELAY)
|
||||
[self removeFingerTipWithHash:touchView.tag animated:YES];
|
||||
}
|
||||
|
||||
if ([[self.overlayWindow subviews] count])
|
||||
[self scheduleFingerTipRemoval];
|
||||
if ([[self.overlayWindow subviews] count])
|
||||
[self scheduleFingerTipRemoval];
|
||||
}
|
||||
|
||||
- (void)removeFingerTipWithHash:(NSUInteger)hash animated:(BOOL)animated {
|
||||
COSTouchSpotView *touchView = (COSTouchSpotView *)[self.overlayWindow viewWithTag:hash];
|
||||
if (touchView == nil)
|
||||
return;
|
||||
COSTouchSpotView *touchView = (COSTouchSpotView *)[self.overlayWindow viewWithTag:hash];
|
||||
if (touchView == nil)
|
||||
return;
|
||||
|
||||
if ([touchView isFadingOut]) return;
|
||||
if ([touchView isFadingOut])
|
||||
return;
|
||||
|
||||
BOOL animationsWereEnabled = [UIView areAnimationsEnabled];
|
||||
BOOL animationsWereEnabled = [UIView areAnimationsEnabled];
|
||||
|
||||
if (animated) {
|
||||
[UIView setAnimationsEnabled:YES];
|
||||
[UIView beginAnimations:nil context:nil];
|
||||
[UIView setAnimationDuration:self.fadeDuration];
|
||||
}
|
||||
if (animated) {
|
||||
[UIView setAnimationsEnabled:YES];
|
||||
[UIView beginAnimations:nil context:nil];
|
||||
[UIView setAnimationDuration:self.fadeDuration];
|
||||
}
|
||||
|
||||
touchView.frame = CGRectMake(touchView.center.x - touchView.frame.size.width,
|
||||
touchView.center.y - touchView.frame.size.height,
|
||||
touchView.frame.size.width * 2,
|
||||
touchView.frame.size.height * 2);
|
||||
touchView.frame =
|
||||
CGRectMake(touchView.center.x - touchView.frame.size.width, touchView.center.y - touchView.frame.size.height,
|
||||
touchView.frame.size.width * 2, touchView.frame.size.height * 2);
|
||||
|
||||
touchView.alpha = 0.0;
|
||||
touchView.alpha = 0.0;
|
||||
|
||||
if (animated) {
|
||||
[UIView commitAnimations];
|
||||
[UIView setAnimationsEnabled:animationsWereEnabled];
|
||||
}
|
||||
if (animated) {
|
||||
[UIView commitAnimations];
|
||||
[UIView setAnimationsEnabled:animationsWereEnabled];
|
||||
}
|
||||
|
||||
touchView.fadingOut = YES;
|
||||
[touchView performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:self.fadeDuration];
|
||||
touchView.fadingOut = YES;
|
||||
[touchView performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:self.fadeDuration];
|
||||
}
|
||||
|
||||
- (BOOL)shouldAutomaticallyRemoveFingerTipForTouch:(UITouch *)touch;
|
||||
{
|
||||
// We don't reliably get UITouchPhaseEnded or UITouchPhaseCancelled
|
||||
// events via -sendEvent: for certain touch events. Known cases
|
||||
// include swipe-to-delete on a table view row, and tap-to-cancel
|
||||
// swipe to delete. We automatically remove their associated
|
||||
// fingertips after a suitable timeout.
|
||||
//
|
||||
// It would be much nicer if we could remove all touch events after
|
||||
// a suitable time out, but then we'll prematurely remove touch and
|
||||
// hold events that are picked up by gesture recognizers (since we
|
||||
// don't use UITouchPhaseStationary touches for those. *sigh*). So we
|
||||
// end up with this more complicated setup.
|
||||
// We don't reliably get UITouchPhaseEnded or UITouchPhaseCancelled
|
||||
// events via -sendEvent: for certain touch events. Known cases
|
||||
// include swipe-to-delete on a table view row, and tap-to-cancel
|
||||
// swipe to delete. We automatically remove their associated
|
||||
// fingertips after a suitable timeout.
|
||||
//
|
||||
// It would be much nicer if we could remove all touch events after
|
||||
// a suitable time out, but then we'll prematurely remove touch and
|
||||
// hold events that are picked up by gesture recognizers (since we
|
||||
// don't use UITouchPhaseStationary touches for those. *sigh*). So we
|
||||
// end up with this more complicated setup.
|
||||
|
||||
UIView *view = [touch view];
|
||||
view = [view hitTest:[touch locationInView:view] withEvent:nil];
|
||||
UIView *view = [touch view];
|
||||
view = [view hitTest:[touch locationInView:view] withEvent:nil];
|
||||
|
||||
while (view != nil) {
|
||||
if ([view isKindOfClass:[UITableViewCell class]]) {
|
||||
for (UIGestureRecognizer *recognizer in [touch gestureRecognizers]) {
|
||||
if ([recognizer isKindOfClass:[UISwipeGestureRecognizer class]]) return YES;
|
||||
}
|
||||
while (view != nil) {
|
||||
if ([view isKindOfClass:[UITableViewCell class]]) {
|
||||
for (UIGestureRecognizer *recognizer in [touch gestureRecognizers]) {
|
||||
if ([recognizer isKindOfClass:[UISwipeGestureRecognizer class]])
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
if ([view isKindOfClass:[UITableView class]]) {
|
||||
if ([[touch gestureRecognizers] count] == 0)
|
||||
return YES;
|
||||
}
|
||||
|
||||
view = view.superview;
|
||||
}
|
||||
|
||||
if ([view isKindOfClass:[UITableView class]]) {
|
||||
if ([[touch gestureRecognizers] count] == 0) return YES;
|
||||
}
|
||||
|
||||
view = view.superview;
|
||||
}
|
||||
|
||||
return NO;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)performMorph:(NSTimer*)theTimer {
|
||||
UIView *view = (UIView*)[theTimer userInfo];
|
||||
NSTimeInterval duration = .4;
|
||||
NSTimeInterval delay = 0;
|
||||
// Start
|
||||
view.alpha = _touchAlpha;
|
||||
view.transform = CGAffineTransformMakeScale(1, 1);
|
||||
[UIView animateWithDuration:duration/4 delay:delay options:0 animations:^{
|
||||
// End
|
||||
view.transform = CGAffineTransformMakeScale(1, 1.2);
|
||||
} completion:^(BOOL finished) {
|
||||
[UIView animateWithDuration:duration/4 delay:0 options:0 animations:^{
|
||||
// End
|
||||
view.transform = CGAffineTransformMakeScale(1.2, 0.9);
|
||||
} completion:^(BOOL finished) {
|
||||
[UIView animateWithDuration:duration/4 delay:0 options:0 animations:^{
|
||||
// End
|
||||
view.transform = CGAffineTransformMakeScale(0.9, 0.9);
|
||||
} completion:^(BOOL finished) {
|
||||
[UIView animateWithDuration:duration/4 delay:0 options:0 animations:^{
|
||||
// End
|
||||
view.transform = CGAffineTransformMakeScale(1, 1);
|
||||
} completion:^(BOOL finished) {
|
||||
- (void)performMorph:(NSTimer *)theTimer {
|
||||
UIView *view = (UIView *)[theTimer userInfo];
|
||||
NSTimeInterval duration = .4;
|
||||
NSTimeInterval delay = 0;
|
||||
// Start
|
||||
view.alpha = _touchAlpha;
|
||||
view.transform = CGAffineTransformMakeScale(1, 1);
|
||||
[UIView animateWithDuration:duration / 4
|
||||
delay:delay
|
||||
options:0
|
||||
animations:^{
|
||||
// End
|
||||
view.transform = CGAffineTransformMakeScale(1, 1.2);
|
||||
}
|
||||
completion:^(BOOL finished) {
|
||||
[UIView animateWithDuration:duration / 4
|
||||
delay:0
|
||||
options:0
|
||||
animations:^{
|
||||
// End
|
||||
view.transform = CGAffineTransformMakeScale(1.2, 0.9);
|
||||
}
|
||||
completion:^(BOOL finished) {
|
||||
[UIView animateWithDuration:duration / 4
|
||||
delay:0
|
||||
options:0
|
||||
animations:^{
|
||||
// End
|
||||
view.transform = CGAffineTransformMakeScale(0.9, 0.9);
|
||||
}
|
||||
completion:^(BOOL finished) {
|
||||
[UIView animateWithDuration:duration / 4
|
||||
delay:0
|
||||
options:0
|
||||
animations:^{
|
||||
// End
|
||||
view.transform = CGAffineTransformMakeScale(1, 1);
|
||||
}
|
||||
completion:^(BOOL finished){
|
||||
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
Loading…
Reference in New Issue
Block a user