This is one of the very technique session in WWDC 2014. I have made a duplicate demo from this session and published it here.
Here is a list of problems and solutions from the talk.
- When
UIScrollView
with DrawerView (UIVisuallEffectView
) added to controller's view(AView), AView's user interaction is blocked. How to keep AView unblocked from user?
Set
UIScrollView
'suserInteractionEnabled
to beNO
.
- When
UIScrollView
's userInteractionEnabled is false, how can we keepUIScrollView
'spanGestureRecognizer
, so theUIScrollView
could be pulled up or down.
Easy solution would be pass the UIScrollView's property
panGestureRecognizer
to its superview, so the superview could recognize the pan gesture, while not being blocked.
- How to add subviews to
UIVisualEffectView
?
Since
UIVisualEffectView
would do tons of work for the blurring effect on the view, it's best to add any subview to itscontentView
, which is aUIView
on top of it. Then these subviews would not interfere with the computation of visual effect.
- How does
- hitTest:withEvent:
work?
This function is defined in
UIView
, the following is the pseudo code.- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if (/* point is in our bounds */) {
for (/* each subview, in reverse order */) {
UIView *hitView = /* recursive call on subview */
if (hitView != nil) {
return hitView;
}
}
return self;
}
return nil;
}
- How to reenable user interaction on
UIScrollView
without blocking its parent view?
- Set
UIScrollView
'suserInteractionEnabled
toYES
.- Subclass
UIScrollView
, override- hitTest:withEvent:
function, so this function either returnsUIScrollView
's subview, or its superview, rather itself.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView *hitView = [super hitTest:point withEvent:event]; if (hitView == self) { return nil; } return hitView; }
- How to not cancel other touch event when
UILongPressGestureRecognizer
is triggered?
Set
cancelsTouchesInView
ofUILongPressGestureRecognizer
toNO
.
- How to make several
UIGestureRecognizer
recognize simultaneously?
Implement
UIGestureRecognizer
delegate method:- gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:
, and returnYES
when certain both of twoUIGestureRecognizer
could be triggered.This way,
UIGestureRecognizer
could work simultaneously, between siblings and self, also between superview and self.Thank system for supporting resting touches.
- Good UX to implement:
- When grab / drop a dot: Apply a simple animation could be very good choice. Just scale the transform and change the alpha of view.
- When user does not click on the center of view, there might be a 'Jump' at first: This could be fixed simply move it to the user touch location when view is grabbed.
- Fastest Fix on conflict between
UIView
's touch event andUIScrollView
'spanGestureRecognizer
.
Just disable, then enable
UIScrollView
'spanGestureRecognizer
when UIView'sUILongPressGestureRecognizer
triggered. This will disablepanGestureRecognizer
for current user touch, but reenable it will allow panGestureRecognizer to recognize new touches from user.
- How to apply the feature "Touch Delay Gesture Recognizer" from
UIScrollView
toUIView
.
- Subclass
UIGestureRecognizer
.#import <UIKit/UIGestureRecognizerSubclass.h>
- Introduce a
NSTimer
for the purpose of delay.- Set
delaysTouchesBegan
toYES
in initializer.- Set
UIGestureRecognizer
's State to Failed when timer expired, touch cancelled or touch ended.- Override
- reset
function to reset timer.- Add this customized UIGestureRecognizer to the view, which is a subclass of
UIView
.
- One More Thing: how to more easily recognize user's touch when subclass of UIView is pretty small for user to click on?
Override method
- pointInside:withEvent:
ofUIView
, in the method, check bigger area instead, rather than the bounds of the view.44 is a very common number used in iOS system, so use it frequently and wisely.