æè¿ãåæ§ã®æ©èœãå¿ èŠã«ãªããŸããã ç§ã®å€ã決æãåããããªãããç§ãæãæ¢è£œã®å®è£ ãèŠã€ããããªãã£ãã®ã§ãèªåã§æžãããšã決ããã ãã®çµæãã©ã®ãããªå°é£ã«çŽé¢ããªããã°ãªããªãã£ãã®ãããããŠæ°ãããã®ãæã¡äžãã£ã-ã«ããã®äžã§ã
ã©ã®ãœãªã¥ãŒã·ã§ã³ãå¿ èŠã§ããïŒ æ¢åã®ãããžã§ã¯ãæ§é ã§åæ§ç¯ããå¿ èŠããªããã®ã¯ãå¯èœãªéãå°ããã·ã³ãã«ã§ããïŒãããŠèª°ãããããªãã®ã§ããïŒïŒ ãã®ãããããšãã°ã ãã®ãœãªã¥ãŒã·ã§ã³ãæ°ã«å ¥ããªãã£ããããå人ãviewControllerãã«ãŒããšããŠäœ¿çšããããšãææ¡ããããã²ãŒã·ã§ã³ããã®ã¹ã¿ã€ã«ã«èšå®ããŠããŸãã
self.viewController = [[ARTEmailSwipe alloc] init]; // you will want to use your own custom classes here, but for the example I have just instantiated it with the UIViewController class. self.viewController.centerViewController = [[UIViewController alloc] init]; self.viewController.bottomViewController = [[UIViewController alloc] init];
ã¯ãã圌ã®å®è£ ã¯çŽ400è¡ããããŸãããããã¯ãã¹ãŠåæºããŸãã
ãŸããç§èªèº«ã以åã«ãããã©ã®ããã«å®è£ ãããã«ã€ããŠïŒ
ã³ãŒã
vcModal = [storyboard instantiateViewControllerWithIdentifier:@"vcModal"]; vcModal.modalPresentationStyle = UIModalPresentationCustom; vcModal.delegate = self; [self addChildViewController: vcModal]; vcModal.view.frame = self.view.bounds; [self.view addSubview: vcModal.view]; [self.view bringSubviewToFront:vcModal.view]; [vcModal didMoveToParentViewController: self]; CGRect bound = [[UIScreen mainScreen] bounds]; CGRect finalFrameVC = vcAddNewGoal.view.frame; vcAddNewGoal.view.frame = CGRectOffset(finalFrameVC, 0, CGRectGetHeight(bound)); // // âŠ
æ§ããã«èšã£ãŠããããã¯æããšã¬ã¬ã³ããªãœãªã¥ãŒã·ã§ã³ã§ã¯ãããŸãããå¶éã課ããããããã«æ°ããã³ã³ãããŒã©ãŒãåŸã§åé€ããæ¹æ³ã«ã€ããŠãæ··ä¹±ããŠããŸãã UIViewControllerAnimatedTransitioningãããã«äœ¿çšããªãã£ãã®ã¯ãªãã§ããïŒ æ£çŽãªãšãããèŠããŠããªããããããŸããããæåã¯ããã䜿ãå§ãããããããŸãããã以äžã§èª¬æããå°é£ã«ééãããããæããŠãæŸèæã圫ãããšã«ããŸããã
UIViewControllerAnimatedTransitioning
æ zyãªäººããã®ãããã³ã«ã®äœ¿çšã«ã€ããŠæžããããšãé€ããŠãããã¯iOS 7以æ¥ååšããŠããŸããã äœçŸãã®ãã¥ãŒããªã¢ã«ãšèšäºããããŸãã çŸããã¯ããããã³ã«èªäœãéåžžã«ã·ã³ãã«ã§ããããšã§ãã å¿ èŠãªã¡ãœããã¯2ã€ã ãå®è£ ããå¿ èŠããããŸããtransitionDurationïŒ-ã¢ãã¡ãŒã·ã§ã³æéãè¿ãããanimateTransitionïŒViewControllersèªäœã®ã¢ãã¡ãŒã·ã§ã³ãçºçããanimateTransitionïŒ ç°¡åãªããšã¯ãããŸãããïŒ æã£ãã ãããŠãããã§ã¢ãã¡ãŒã·ã§ã³ã¡ãœããã¯æ¥œããæžãããŠããŸãïŒ
animateTransitionïŒ
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{ self.transitionContext = transitionContext; UIViewController *fromtVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; UIView *containerView = [transitionContext containerView]; CGRect finalFrameVC = [transitionContext finalFrameForViewController:toVC]; NSTimeInterval duration = [self transitionDuration:transitionContext]; viewH = CGRectGetHeight(fromtVC.view.frame); // vc , UIViewController *modalVC = reversed ? fromtVC : toVC; UIViewController *nonModalVC = reversed ? toVC : fromtVC; // , CGRect modalFinalFrame = reversed ? CGRectOffset(finalFrameVC, 0, viewH) : finalFrameVC; float scaleFactor = 0.0; float alphaVal = 0.0; if (reversed) { scaleFactor = 1.0; alphaVal = 1.0; } else { // modalFinalFrame.origin.y += kModalViewYOffset; // modalVC.view.frame = CGRectOffset(finalFrameVC, 0, viewH); scaleFactor = kNonModalViewMinScale; alphaVal = kNonModalViewMinAlpha; [containerView addSubview:toVC.view]; } [UIView animateWithDuration:duration delay:0.0 usingSpringWithDamping:100 initialSpringVelocity:10 options:UIViewAnimationOptionAllowUserInteraction animations:^{ nonModalVC.view.transform = CGAffineTransformScale(CGAffineTransformIdentity, scaleFactor, scaleFactor); nonModalVC.view.alpha = alphaVal; modalVC.view.frame = modalFinalFrame; } completion:^(BOOL finished) { [transitionContext completeTransition:![transitionContext transitionWasCancelled]]; reversed = !reversed; }];
ã¢ãŒãã«ãŠã£ã³ããŠèªäœã¯ãUIPercentDrivenInteractiveTransitionã䜿çšããŠç§»åãããŸããã ãã¹ãŠãæ©èœããŠããããã§ããŠã£ã³ããŠã衚瀺ãããåããéããŸãã ããããããã¯ãã¹ãŠèæ¡ããããããã¢ãŒãã«ãŠã£ã³ããŠãäžã«ããå Žåãåã®ç»é¢ã§äœæ¥ã§ããåã®ç»é¢ã¯ã¯ãªãã¯ã«å¿çããŸããïŒ ããã¯ãParseã®ééã®ãã¥ãŒã¹ä»¥æ¥ãæè¿ã®å€±æã®2çªç®ã§ããã fromtVCç»é¢ãcontainerViewã«è¿œå ãããšãããããè¿œå ããã®ãæãçã«ããªã£ãŠããããã«æããŸããã ããã¯æ©èœããŸãã-以åã®ç»é¢ã¯ã¢ã¯ãã£ãã§ããããä»ã§ã¯ãããéãããšãäžè¬çã«é»ãç»é¢ãããããŸããã§ããã
ããã¥ã¡ã³ããšstackOverflowãèªãã åŸãVCããã³ã³ããã«è¿œå ããããšã¯æ±ºããŠäžå¯èœã§ã¯ãªãããšãæããã«ãªããŸããããäœãããã¹ãããæ確ã§ã¯ãããŸããã§ããã ç§ã®åé¡ã説æããåŸãç§ã¯SOã«ã€ããŠè³ªåããããŒã¹ã¿ãŒã«ã€ããŠã質åããŸãããããŸã çãã¯ãããŸããã§ããã
ç§ã¯çªç¶ãanimateTransitionïŒã¡ãœããã®ã¡ã«ããºã å šäœãååã«èªèããŠããªãããšã«æ°ä»ããŸããã ã€ãŸããç¹å®ã®ãªããžã§ã¯ãããããŸã
containerViewãéãããã³ã³ãããŒã©ãŒãããã«è¿œå ãããŸãããããã¯ã©ã®ãããªãã®ã§ããã¥ãŒéå±€ã®ã©ã®å Žæãå ããŸãããåã®ã³ã³ãããŒã©ãŒã¯ã©ããªããŸããïŒ ç§ã¯ãããã®è³ªåã«çããããšã§è§£æ±ºçãèŠã€ããããšãã§ãããšç¢ºä¿¡ããŠããŸããïŒãã¿ãã¬-ãããŠç§ã¯ééã£ãŠããŸããã§ããïŒã ç§ã¯ãã ãã£ãïŒ
containerView.backgroundColor = [UIColor yellowColor];
ã«
åŸ
containerViewã¯åã®ãã¥ãŒã«è¿œå ãããéåžžã®éæãªUIViewã§ãããfromVCã¯ãã®äžã«å¹³åçã«æšªããã£ãŠããããšãæããã«ãªããŸããã ããã¯ããã®ã³ã³ããããããšã®å¯Ÿè©±ã劚ããããšãæå³ããŸãã移åãããªãã·ã§ã³ã§ã¯ãªããããäœããã®æ¹æ³ã§ãããã·ã¥ãããå¿ èŠããããŸãã UIViewã«ã¯ãªãã¯ãéä¿¡ãããæãç°¡åãªæ¹æ³ã¯ããããèšå®ããããšã§ã
userInteractionEnabled = NO;
ããããããã¯ãã®ãµããã¥ãŒã®ãã¹ãŠã«åºãããŸããããããªãã·ã§ã³ã§ã¯ãããŸããã
å¿çãã§ãŒã³
ããã«ééããããšããªãå Žåã¯ã ã¬ã¹ãã³ããŒãã§ãŒã³ã玹ä»ããŸãã ã€ãŸããã¬ã¹ãã³ããŒãã§ãŒã³ã¯ãã¯ãªãã¯ãªã©ã®ã€ãã³ãã察å¿ãããªããžã§ã¯ãã«éä¿¡ããiOSã¡ã«ããºã ã§ãã ã€ãã³ãã¯ãåä¿¡ããŠåŠçã§ãããªããžã§ã¯ãã«å°éãããŸã§ããã®ãã§ãŒã³ã«æ²¿ã£ãŠã移åãããŸãã ã¯ãªãã¯ã®å ŽåãUIWindowãªããžã§ã¯ãã¯æåã«ãã¯ãªãã¯ãçºçãããã¥ãŒã«ã€ãã³ããé ä¿¡ããããšããŸãã ãã®ãã¥ãŒã¯ããããã¹ããã¥ãŒãšåŒã°ãããã®ããããã¹ããã¥ãŒã®æ€çŽ¢ããã»ã¹ã¯ããããã¹ããšåŒã°ããŸãã ããããã¹ãã§ã¯ãé©åãªãã¥ãŒå ã§ã¯ãªãã¯ãçºçããããšã確èªãããã®ãµããã¥ãŒããã¹ãŠååž°çã«ç¢ºèªããŸãã ã¯ãªãã¯å¶éå ã«ãããã®éå±€ã®æäžäœã¬ãã«ã®ãã¥ãŒã¯ããããã¹ããã¥ãŒã«ãªãããã®åŸiOSã¯åŠçã®ããã«ãã®ãã¥ãŒã«ã€ãã³ããéä¿¡ããŸã
ããã¥ã¡ã³ããããã®ããã»ã¹ã®çŽ æŽãããã€ã©ã¹ãïŒ
ãŠãŒã¶ãŒããã¥ãŒEãã¯ãªãã¯ãããšããŸããiOSã¯ã次ã®é åºã§ãµããã¥ãŒããã§ãã¯ããããšã§ããããã¹ããã¥ãŒãèŠã€ããŸãã
1.ãã¥ãŒAå ã§ãæŒããBãšCã確èªããŸãã
2. Bå ã§ã¯ãªãCå ãæŒããDãšEã確èªããŸãã
3.ã¯ãªãã¯ã¯Då ã§ã¯ãªããEå ã§ããEã¯ã¯ãªãã¯ã®åº§æšãå«ãéå±€ã®æäžäœã¬ãã«ã®ãã¥ãŒã§ãããããããããã¹ããã¥ãŒã«ãªããŸãã
ãªããã®ãã¹ãŠãç©èªã ã£ãã®ã§ããïŒ ãããŠãUIViewã¡ãœããã¯hitTestïŒwithEventïŒã«æžãæããããšãã§ããŸãïŒ
ã¿ã¹ã¯ã¯æ¬¡ã®ãšããã§ãããcontainerViewãã¯ãªãã¯ããŠãåæã«éåžžã©ããåŠçããããµããã¥ãŒãã¯ãªãã¯ããããšãå¯èœã«ããŸãã ãµãã¯ã©ã¹ãèšè¿°ããcontainerViewãã匷å¶çã«ç¶æ¿ããããšã¯ã§ããŸããã 次ã®ãããªãã®ïŒ
-åäœããŸããã ãã®ãããã«ããŽãªãäœæããå¿ èŠããããŸãïŒãŸãã¯ããã·ã¢æåŠã®å Žåã®ããã«ããã¯ã©ã¹ã®ç¶ç¶ã®ã«ããŽãªãïŒã ãæšæºãã¡ãœããhitTestïŒwithEventïŒã¯æ¬¡ã®ããã«ãªããŸããMyUIViewSubclass *containerView = (MyUIViewSubclass *)[transitionContext containerView];
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { if (!self.isUserInteractionEnabled || self.isHidden || self.alpha <= 0.01) { return nil; } if ([self pointInside:point withEvent:event]) { for (UIView *subview in [self.subviews reverseObjectEnumerator]) { CGPoint convertedPoint = [subview convertPoint:point fromView:self]; UIView *hitTestView = [subview hitTest:convertedPoint withEvent:event]; if (hitTestView) { return hitTestView; } } return self; } return nil; }
ã€ãŸããã©ãããã¯ãªãã¯ããã¬ã¹ãã³ããŒãã§ãŒã³ã§IsUserInteractionEnabledãç¡å¹ãŸãã¯é衚瀺ãŸãã¯éæ床ã99ïŒ ãè¶ ãããã¥ãŒã衚瀺ãããå Žåãnilãè¿ãããããã®ã¯ãªãã¯ãã¯ãªãã¯ããŠãã¹ããç¶è¡ããŸãã ãã以å€ã®å ŽåãhitTestãã¥ãŒãèŠã€ããããšããèŠã€ãã£ãå Žåã¯ãããè¿ããŸããããã«ãããã¯ãªãã¯ã€ãã³ãããã®ãã¥ãŒã«éä¿¡ãããããnilãè¿ãããŸãããäœãèµ·ãããŸããã
ã³ã³ãããã¯ãªãã¯ããŠãéä¿¡ãããªãããã«ããæ¹æ³ã¯ïŒ äœããã®æ¹æ³ã§containerViewãæ£ç¢ºã«åºå¥ããå¿ èŠããããŸããæãç°¡åãªã®ã¯ãåã«ã¿ã°ãèšå®ããããšã§ã
UIView *containerView = [transitionContext containerView]; containerView.tag = GITransitionContainerViewTag;
Tag'omç§ã¯æé«ã®çªå·73ãéžã³ãŸãã :)ã
ãŸããhitTestïŒwithEventïŒã¡ãœããã§ã¯ãè¿œå ã®æ¡ä»¶ãè¿œå ãããŸãã
if (hitTestView && hitTestView.tag != GITransitionContainerViewTag) { return hitTestView; }
ãããã£ãŠãã¯ãªãã¯ããŠãcontainerViewã«ãåãŸããããšã¯ãããŸããããéå±€ã®å¥¥æ·±ãã«ç§»åããŸãã
ãããã倧ããªãã®ããããŸãã ããããããšã§ãUIViewã®æšæºåäœããªãŒããŒã©ã€ãããcontainerViewã ãã§ãªããããã°ã©ã å ã®çµ¶å¯Ÿçã«ãã¹ãŠã®UIViewã®åäœãå€æŽããŸã-ããã¯æãŸãããããŸããïŒã³ã¡ã³ãã§ææããŠãããHabrausersã«æè¬ããŸãïŒã ãããä¿®æ£ããã«ã¯ãobjective-Cã©ã³ã¿ã€ã ãã€ãŸãã¡ãœããå®è£ ãåãæ¿ããã¡ã«ããºã ïŒã¡ãœããã¹ãŠã£ãºãªã³ã°ïŒã䜿çšããŸãã
ããã«ã¯ãæå°éã®ã³ãŒãå€æŽãå¿ èŠã§ãã
1ïŒåãUIViewã«ããŽãªã§ãhitTestïŒWithEventã¡ãœããã«ãã¬ãã£ãã¯ã¹ãè¿œå ããŸãã次ã«äŸã瀺ããŸãã
- (UIView *)GI_hitTest:(CGPoint)point withEvent:(UIEvent *)event;
2ïŒcontainerViewãžã®ãªã³ã¯ãåãåã£ãåŸãã¡ãœãããåãæ¿ããŸãã
static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ // Swizzling Method originalMethod = class_getInstanceMethod([containerView class], @selector(hitTest:withEvent:)); Method swappedMethod = class_getInstanceMethod([containerView class], @selector(GI_hitTest:withEvent:)); method_exchangeImplementations(originalMethod, swappedMethod); });
ãããã£ãŠããªãŒããŒã©ã€ããããã¡ãœããhitTestïŒWithEventã¯containerViewã«å¯ŸããŠã®ã¿åŒã³åºãããã·ã¹ãã å ã®ä»ã®UIViewã«ã¯è§ŠããŸããã
ããã§ããã¹ãŠãæå³ãããšããã«æ©èœããŸãã èªãã§ãããŠããããšããããªãèªèº«ã®ããã«æ°ããäœãé¢çœãããšãåŠãã ããšãé¡ã£ãŠããŸãã
èå³ããããªãããããžã§ã¯ãã¯GitHubã«ãããŸã