I have found the iPhone's keyboard bounds in the apple documentation, but I can't find the iPad's keyboard bounds. Could you please help me?
The entire answer in code looks like this. First you need to register for the notifications:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
and there are more here. Note that you'll need to get rid of them, too (use removeObserver).
Then you need a method that gets the notification to get the size. Note that the size is, at first, not rotated (since the UIWindow doesn't rotate. Its contents do).
- (void) keyboardDidShow:(NSNotification*)notification {
CGRect keyboardFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
NSLog(#"keyboard frame raw %#", NSStringFromCGRect(keyboardFrame));
UIWindow *window = [[[UIApplication sharedApplication] windows]objectAtIndex:0];
UIView *mainSubviewOfWindow = window.rootViewController.view;
CGRect keyboardFrameConverted = [mainSubviewOfWindow convertRect:keyboardFrame fromView:window];
NSLog(#"keyboard frame converted %#", NSStringFromCGRect(keyboardFrameConverted));
}
Obviously, if you have a reference to your mainSubviewOfWindow by some other means, use it.
For iPhone in portrait 216 pixels, landscape 162 pixels, for iPad in portrait it's 264 pixels and in landscape 352 pixels. This is valid for US keyboard in 2010.
These sizes can be different for other languages, and might change for US as well.
Please note that if user choose to use "split" keyboard on iPad, then UIKeyboardDidShowNotification/*UIKeyboardDidHideNotification* notifications will not be fired. Instead, UIKeyboardDidChangeFrameNotification notification will be fired on both show and hide. You will have to analyze keyboardFrame.origin.y to figure out what exactly happen (show or hide).
I just found it if somebody else needs it.
Keyboard Notification User Info Keys
Related
I have a custom view at the bottom of my screen, i want to reposition it above the keyboard when it opens up.
I know i can register for the 'KeyboardWasShown' notification and then reposition the view or as the apple documentation suggests to use a scrollview with scrollRectToVisible, but the problem i have with both options is that it is not done as part of the keyboard animation.
I can see the keyboard appear and only a second later the view is repositioned or scrolled in to view.
Another option i tried was to set this view as InputAccessory for the textView im editing, This works very well but my view will not be visible once the keyboard is closed, and i need it to be available all the time.
I suppose i can create two instances of this view and have one as inputAccessory and the other just sitting in the bottom, but i really dont like this solution and these views have a state that will have to be synced between the two instances
Can anyone suggest an alternative solution ?
You better use UIKeyboardWillChangeFrameNotification notification.
Add observer first.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardFrameChange:) name:UIKeyboardWillChangeFrameNotification object:nil];
The selector will be...
- (void)keyboardFrameChange:(NSNotification *)notification {
CGRect begin = [[notification.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
CGRect end = [[notification.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat keyboardSize= begin.size.height;
BOOL isShowing = begin.origin.y > end.origin.y;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:[notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
[UIView setAnimationCurve:[notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]];
[UIView setAnimationBeginsFromCurrentState:YES];
// do view animation here.
[UIView commitAnimations];
}
The animation of your view and the keyboard will be sync.
In my main view, I add a normal UIToolbar to the bottom of the frame, in landscape it doesn't get smaller? Is this because i dont supply landscape images or am i missing something else? All of the other toolbars in the UINavigationController's all change size in landscape.
Heres how i add this one to the screen.
toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, SCREEN_HEIGHT-64, SCREEN_WIDTH, 44)];
toolbar.translatesAutoresizingMaskIntoConstraints = YES;
[self.view addSubview:toolbar];
[self setupToolbarItems];
setupToolbarItems just creates some of the images for the bar buttons and sets them.
A UIToolbar that you add yourself will not magically change height. If you want it to do so, you must change the height yourself in response to a change in app orientation.
The behavior that you have observed, where a bar changes height, is a feature of UINavigationController; it changes the height of its navigation bar and its toolbar in response to orientation change (as explained in my book: http://www.apeth.com/iOSBook/ch25.html#SBbarMetrics). But this UIToolbar does not belong to a UINavigationController so nothing happens to its height automatically. It's up to you.
This is because you are creating the toolBar's frame but not setting it again when the view is rotated. You need to check when the screen is rotated using [[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(resize) name:UIDeviceOrientationDidChangeNotification object:nil];
and then in your -(void)resize; method, you need to resize the toolbar to the new window's size.
How to force NSScrollView to use scrollers like that:
independently from input device, because now if computer has wired mouse connected or app is running on laptop (macbook) it uses scrollers like this:
witch is always visible. It is possible to achieve my desired result if user changes settings in system preferences. But I need to have that result without changing anything. Or maybe there is some easy method to use custom NSScrollers?
Hiding scrollers would be pretty acceptable result, but when I hide them I have some scrolling issues. I use custom NSClipView witch adjusts documentView to be centered when adjusting its frame size. But when I adjust frame size, and it is scrolled to center, if I scroll anywhere it jumps to bottom left corner and then works as it should.
I'm using table view and I just put this code in awakeFormNib:
[[self.tableView enclosingScrollView] setScrollerStyle:NSScrollerStyleOverlay];
I also tried to hide scrollers but then I couldn't scroll the content using trackpad (no problem using mouse). In the other project I have similar table view with the same settings and hiding scrollers doesn't cause any issues.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(notify:) name:NSPreferredScrollerStyleDidChangeNotification object:nil];
- (void)notify:(NSNotification*)
{
__weak typeof(self) weakself = self;
dispatch_async(dispatch_get_main_queue(), ^{
weakself.scrollView.scrollerStyle = NSScrollerStyleOverlay;
});
}
I'm writing an application that is looking to draw a basic NSWindow on top of the Desktop icons (Mac OSX 10.7 Lion).
NSWindow *systemInfoWindow = [[NSWindow alloc] initWithContentRect:frame
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
systemInfoWindow.delegate = self;
[systemInfoWindow setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces];
[systemInfoWindow setBackgroundColor:backgroundColorSpace];
[systemInfoWindow makeKeyAndOrderFront:NSApp];
[systemInfoWindow setLevel:kCGDesktopIconWindowLevel];
This part of code works quite well and the NSWindow gets draw on top of the icons.
But if I switch between two spaces my NSWindow stay behind the icons.
/* === Update === */
I think i have problems with my window Level. For better understanding I have uploaded two Screenshots.
Space 1 - window stays like I want on top of the Icons
http://dl.dropbox.com/u/1503795/Space1.png
Space 2 - the window is behind the Desktop icons. They should also stay on top
http://dl.dropbox.com/u/1503795/Space2.png
A further problem I found. If I activated the App and stay on the first Space and everything looks good like on my first Screenshot. If I select the Files on the Desktop the window also jumps to the back:
Sorry, can`t post a nother Screenshot
I hope my problem is a bit more understandably.
I dont`t know how to fix this. Has anybody an idea?
Thanks!
You probably need to register for the space change notification:
NSNotificationCenter* nc = [[NSWorkspace sharedWorkspace] notificationCenter];
[nc addObserver:self
selector:#selector(activeSpaceDidChange:)
name:NSWorkspaceActiveSpaceDidChangeNotification
object:nil];
You can then respond to the notification and update your window:
- (void) activeSpaceDidChange:(NSNotification*)aNotification
{
[[self window] orderFront:self];
}
I implemented the textfield with a custom keyboard with the "setInputView" function.
But i have a problem: my keyboard frame is not a standard iphone keybord frame.
The question is:
How can i change the size of my custom keyboard?
I know some functions like: UIKeyboardFrameBeginUserInfoKey, ..etc.
Please Note:
The iPhone keyboard frame is = 0,264,320,216
My custom keyboard frame is = 0,0,320,460
Hoping for your kind collaboration,
Best regards...
P
It turns out that the default behaviour of the custom input view that you assign to the UITextField's property is to resize the view to the same frame as the default keyboard. Try setting (I use the name InputViewController for my input view, but you can use whatever you want):
inputViewController = [[InputViewController alloc] initWithNibName:#"InputViewController" bundle:nil];
inputViewController.delegate = self;
inputViewController.view.autoresizingMask = UIViewAutoresizingNone; // This is the code that will make sure the view does not get resized to the keyboards frame.
For more detailed information, you can look at this link, which is provided by Apple.:
If UIKit encounters an input view with an UIViewAutoresizingFlexibleHeight value in its autoresizing mask, it changes the height to match the keyboard.
Hope that Helps!
To set the keyboard inputView with the same size as the native keyboard just do this:
inputView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
To set your own frame do this:
inputView.autoresizingMask = UIViewAutoresizingNone;
From Apple:
You have a lot of flexibility in defining the size and content of an input view or input accessory view. Although the height of these views can be what you’d like, they should be the same width as the system keyboard. If UIKit encounters an input view with a UIViewAutoresizingFlexibleHeight value in its autoresizing mask, it changes the height to match the keyboard. There are no restrictions on the number of subviews (such as controls) that input views and input accessory views may have. For more guidance on input views and input accessory views, see iOS Human Interface Guidelines.
I had the same problem. I solved it by registering for UIKeyboardDidShowNotification (UIKeyboardWillShowNotification did not work, unfortunately) and then changing the view size after the keyboard was shown. However, it still had the white box on top of the keyboard when it was moving up. This worked fine for me because it is coming in over a UITextView with a white background. If you were coming in over any other colored objects, however, it would look a little ugly before the view was properly resized. You can solve that by setting the background color to clearColor.
// Add this while initializing your view
self.backgroundColor = [UIColor clearColor]; // Needed because we can't resize BEFORE showing the view. Otherwise you will see an ugly white box moving up w/ the keyboard
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
CGRect rect = self.frame;
rect.size.height = 164;
self.frame = rect;
}
Also if you're using a UIViewController to design your inputView, don't use the UIViewController.view... it seems to have a lot of problems getting resized incorrectly on rotate regardless of the AutoresizeMask.
What worked for me was to take my existing UI and use Editor > Embed In > View. Then create a new outlet, and pass that outlet as the inputView. Suddenly the resize on rotate bugs disappeared.
For me msgambel's solution didn't work. But the approach right, I was playing with the inputView's autoresizingMask. Former I had different setting, but the right way to avoid white extra space over the custom keyboard is:
I applied this just for the outermost view.