Search code examples
ioskeyboardhideuikeyboarduiwindow

How can I assign a pointer to the keyboard before I have assigned first responder


I am trying to create a user interface enabling users to switch between the keyboard and other menus when using a chat application.

On a click of the textField bar I want to raise either the keyboard or a collection view.

The problem occurs when I click the 'menu' button. I want the textField bar to raise revealing my menu view. Then, on a click on the keyboard button, instantly switch to the keyboard, rather than having it slide up from the bottom. This means I need to have the keyboard already loaded and hidden but in the background of the app.

Currently though the earliest I am managing to assign a variable to the keyboard is in the keyboardDidShow function.

-(void) keyboardDidShow: (NSNotification *) notification {

    // Get the window the keyboard is a subview of
    _window = [UIApplication sharedApplication].windows.lastObject;

    _keyboard = _window.subviews[0]; 
}

This means that after it has been loaded once I can hide and reveal it, but I don't want it visible when it is loading this first time.

To achieve this using alternate means I have tried adding my extra views as subviews of the UIWindow the keyboard is created in:

[_window addSubview:_menuView];
[_window addSubview:_gamesView];
[_window addSubview:_stickerView];

[self hideSpecificView];

Unfortunately I keep coming across the same problem, until I have loaded the keyboard once it needs to fully load before I can get a pointer to it to hide it.

Here is a picture of my toolBar incase I am not being clear:

enter image description here

On clicking the menu icon or the stickers icon I want the bar to raise with a collection view. If I then click the textfield, with these views visible, I want to hide the visible view to immediately show the keyboard behind.

I have also tried experimenting with keyboardWillShow but as the window hasn't been loaded in front our screen I can't get a pointer to the keyboard to hide it before it loads.

An example of what I am after can be found many chat apps (facebook messenger, LINE, Kakao Talk)

Any help would be greatly appreciated


Solution

  • Although the way I came up with isn't perfect it works almost perfectly so hopefully this might help people in the future. If anyone else has solved it differently please post as it would be interesting to know how you did it.

    I started by adding a class variable to a UIWindow in my header file and then setting off a timer to ping just after the keyboard will show method finishes. After this method has finished the keyboard has been created, just, and so I allocate it and hide it.

    -(void) keyboardWillShow: (NSNotification *) notification {
    
        // More keyboard code
    
        _window = [UIApplication sharedApplication].windows.lastObject;
    
        [NSTimer scheduledTimerWithTimeInterval:0.01
                                         target:self
                                       selector:@selector(allocateKeyboard)
                                       userInfo:nil
                                        repeats:NO];
    }
    
    - (void)allocateKeyboard {
    
        if (!_keyboard) {
            _keyboard = _window.subviews[0];
        }
    
        _keyboard.hidden = YES;
    
        [self setViewForButtonType];
    }
    

    I have already previously added my other views, hidden them and constrained them to the bottom of the main view, this means that when the keyboard rises they do too.

    - (void)viewDidLoad {
    
    [self.view addSubview:_menuView];
    [self.view addSubview:_gamesView];
    [self.view addSubview:_stickerView];
    
    }
    
    ...
    
    - (void)hideViews {
    
        _keyboard.hidden = YES;
        _menuView.hidden = YES;
        _gamesView.hidden = YES;
        _stickerView.hidden = YES;
    }
    

    When buttons get pressed I simple then unhide the view that I want to see and hide the rest of the views.

    When I say that this method doesn't work perfectly it is because if you load view main view and then click a button before the keyboard has loaded for the first time then you get a quick glimpse of the keyboard before the view appears over the top. This though only happens the first time and only if they don't click in the text field first.

    Anyway, I found this was the best way of making views look like they are in front of the keyboard. Obviously my code was a lot longer and more complex (too long for here) but this is the gist of the method I used to solve it. Comment if you have any queries and I hope this helps.