Open MartinSchultz opened 9 years ago
Anyone?
@MartinSchultz check this out https://github.com/mutualmobile/MMDrawerController/issues/407#issuecomment-161097378
I'm not quite getting how this solves the issue. What I see is the keyboard goes down (it was open and active on a text field) and once I swipe in the menu from the left, the keyboard pops up again with the side menu visible. Can you elaborate how your code fixes that? Maybe I'm too blind this morning :-) but I don't get it. (and thanks anyway for helping out!!)
@MartinSchultz I've thought you could simply detect in setGestureShouldRecognizeTouchBlock:
block that you have keyboard visible and change your behavior accordingly (e.g. dismiss it). But maybe it's a hacky way :-(.
There's a way, but it's a bit cumbersome.
@property (nonatomic, assign, readonly) MMDrawerSide openSide;
It's readonly so you cannot override the setter to inject your code anytime openSide changes. But luckily it's KVO-able. So you can do something like following. Subclass mmdrawercontroller and add this method:
static void * kSCRBSCRBDrawerControllerKVOContext = &kSCRBSCRBDrawerControllerKVOContext;
static NSString * const SCRBKVOOpenSideKeyPath = @"openSide";
NSString * const SCRBDrawerControllerDidChangeOpenSideNotification = @"SCRBDrawerControllerDidChangeOpenSideNotification";
NSString * const SCRBDrawerControllerOpenSideKey = @"SCRBDrawerControllerOpenSideKey";
- (void)startSendingOpenSideNotifications {
[self addObserver:self forKeyPath:SCRBKVOOpenSideKeyPath options:NSKeyValueObservingOptionNew context:kSCRBSCRBDrawerControllerKVOContext];
}
#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (context == kSCRBSCRBDrawerControllerKVOContext) {
MMDrawerSide openSide = [[change valueForKey:NSKeyValueChangeNewKey] integerValue];
[[NSNotificationCenter defaultCenter] postNotificationName:SCRBDrawerControllerDidChangeOpenSideNotification object:nil userInfo:@{SCRBDrawerControllerOpenSideKey : @(openSide)}];
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (void)dealloc {
[self removeObserver:self forKeyPath:SCRBKVOOpenSideKeyPath context:kSCRBSCRBDrawerControllerKVOContext];
}
All you need is to call startSendingOpenSideNotifications whenever you want, in viewDidLoad for example. After that your drawer controller starts posting app wide notifications every time you try to open the drawer menu. You can create a UITextView\UITextField subclass that will react to these notifications like this:
#import "SCRBDrawerController.h"
#import "SCRBTextField.h"
@implementation SCRBTextField
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self scrb_commonInit];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self scrb_commonInit];
}
return self;
}
- (void)scrb_commonInit {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleDrawerSideChange:) name:SCRBDrawerControllerDidChangeOpenSideNotification object:nil];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)_handleDrawerSideChange:(NSNotification *)ntf {
[self resignFirstResponder];
}
@end
Here's how I do it
Basically, you need to resign the first responder to hide the keyboard. Since you don't know which view is the first responder, you can send the action to the UIApplication like this:
[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];
Now, there are 2 cases that I know of how the drawer can be opened.
Case 1:
The drawer is opened using a gesture. Set a gesture completion block that resigns the first responder:
[self.drawerController setGestureCompletionBlock:^(MMDrawerController *drawerController, UIGestureRecognizer *gesture) {
// hide the keyboard when the gesture completes
if(drawerController.openSide == MMDrawerSideLeft) {
[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];
}
}];
Case 2:
The drawer is opened by toggling its state (e.g. when a "menu" button is touched). Resign the first responder when it finishes:
- (void)leftDrawerButtonPress:(id)sender {
[self.mm_drawerController toggleDrawerSide:MMDrawerSideLeft animated:YES completion:^(BOOL finished) {
// hide the keyboard when the drawer animation completes
if(finished) {
[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];
}
}];
}
I have only a left drawer, hence I'm handling only MMDrawerSideLeft. You can change that to your liking.
I hope this helps.
I'm showing a UIViewController in the center view with a text field. Keyboard shows up, but I need to hide it when the user swipes in the left drawer navigation.
I've searched the issues here but the solutions posted didn't work out for me. I tried using viewWillDisappear, but this method is not getting called. Is there any way to hook into the MMDrawer internals to find out when the user swipes in the drawer navigation so I can hide the keyboard?
Actually, the keyboard already disappears when swiping, but it comes back again when the left menu appears.
Thanks a lot Martin