Animate the keyboard in sync with the UIView while edge-swiping back in iOS7

前端 未结 3 576
攒了一身酷
攒了一身酷 2020-12-12 16:43

I\'d like to get the behavior similar to Messages app (also common in most texting apps) in iOS7, where in a conversation view swiping right from the left edge of the screen

相关标签:
3条回答
  • 2020-12-12 17:21

    Unfortunately, there is no built-in method to do that. I really hope there will be something like UIScrollViewKeyboardDismissModeInteractive for UIViewControllers.

    For now, to do any animations in-between viewControllers, you should use a transitionCoordinator:

    - (BOOL)animateAlongsideTransition:(void (^)(id <UIViewControllerTransitionCoordinatorContext>context))animation
                            completion:(void (^)(id <UIViewControllerTransitionCoordinatorContext>context))completion;
    
    - (BOOL)animateAlongsideTransitionInView:(UIView *)view
                                   animation:(void (^)(id <UIViewControllerTransitionCoordinatorContext>context))animation
                                  completion:(void (^)(id <UIViewControllerTransitionCoordinatorContext>context))completion;
    

    For the keyboard you should do something like this:

    [self.transitionCoordinator animateAlongsideTransitionInView:self.keyboardSuperview
                                                       animation:
    ^(id<UIViewControllerTransitionCoordinatorContext> context) {
        self.keyboardSuperview.x = self.view.width;
    }
                                                      completion:nil];
    

    As for keyboardSuperview - you can get that by creating a fake inputAccessoryView:

    self.textField.inputAccessoryView = [[UIView alloc] init];
    

    Then the superview will be self.textField.inputAccessoryView.superview

    0 讨论(0)
  • 2020-12-12 17:29

    It should just work automatically, but sometimes it doesn't because of some conditions.

    If the current firstResponder is located inside of active UIViewController and it dismiss throughout UINavigationController mechanism, the expected keyboard animation (horizontal) will be performed automatically. Therefore, sometimes this default behaviour is broken by other strange factors and the keyboard starts to disappear with slide-down animation instead of horizontal animation.

    I spent some days with debugging internal UIKit stuff (around methods needDeferredTransition, allowCustomTransition and other) to find one special factor that plays key role in my case.

    I discovered that the logic inside UIPeripheralHost checks frame of current UIViewConroller's view, frame of UINavigationController's view (container) and screen size and, if it all doesn’t equal each other, UIPeripheralHost decides that this current situation seems like modal window and sets flag allowCustomTransition = NO. That turn-off UINavigationController-specific horizontal animation.

    Fixing issue with frames completely solves my problem.

    If you are experiencing same problems, you can try to debug internal UIKit stuff around these private methods and find your conditions that turn off horizontal animation:

    https://github.com/JaviSoto/iOS8-Runtime-Headers/blob/master/Frameworks/UIKit.framework/UIPeripheralHost.h

    https://github.com/JaviSoto/iOS8-Runtime-Headers/blob/master/Frameworks/UIKit.framework/_UIViewControllerKeyboardAnimationStyle.h

    0 讨论(0)
  • 2020-12-12 17:29

    You can use https://github.com/cotap/TAPKeyboardPop if you don't need anything special.

    In my case I've got some logic connected with UIKeyboardWillShowNotification and UIKeyboardWillHideNotification that were fired on "swipe-to-back" gesture. I've combine this answer and TAPKeyboardPop and this is what I've got:

    - (void)beginAppearanceTransition:(BOOL)isAppearing animated:(BOOL)animated {
        [super beginAppearanceTransition:isAppearing animated:animated];
        if (isAppearing || !animated || !_keyboardIsShown) {
            return;
        }
        if ([self respondsToSelector:@selector(transitionCoordinator)]) {
            UIView *keyboardView = self.searchBar.inputAccessoryView.superview;
            [self.searchBar becomeFirstResponder];
            [self.transitionCoordinator animateAlongsideTransitionInView:keyboardView
                                                               animation:^(id<UIViewControllerTransitionCoordinatorContext> context)
             {
                 CGRect endFrame = CGRectOffset(keyboardView.frame, CGRectGetWidth(keyboardView.frame), 0);
                 keyboardView.frame = endFrame;
             } completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
             {
                 if (![context isCancelled]) {
                     [self.searchBar resignFirstResponder];
                 }
             }];
        }
    }
    

    EDIT:

    I've added >iOS7 support and logic for knowing when keyboard is shown (_keyboardIsShown is set in UIKeyboardWillShowNotification/UIKeyboardWillHideNotification or in UIKeyboardDidHideNotification/UIKeyboardDidShowNotification).

    0 讨论(0)
提交回复
热议问题