5

I'm trying to resize a UITextView when the keyboard shows. On iPhone it works beautifully. When the the system dispatches a keyboard notification, the text view resizes. When it's done editing, I resize it to fill in the initial space. (Yes, I'm assuming the keyboard is gone when the editing stops. I should change that. However, I don't think that's my issue.)

When I resize the textview on the iPad, the frame resizes correctly, but the app seems to reset the Y value of the frame to zero. Here's my code:

- (void) keyboardDidShowWithNotification:(NSNotification *)aNotification{

//
//  If the content view being edited
//  then show shrink it to fit above the keyboard.
//

if ([self.contentTextView isFirstResponder]) {

    //
    //  Grab the keyboard size "meta data"
    //

    NSDictionary *info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    //
    //  Calculate the amount of the view that the keyboard hides.
    //
    //  Here we do some confusing math voodoo.
    //
    //  Get the bottom of the screen, subtract that 
    //  from the keyboard height, then take the 
    //  difference and set that as the bottom inset 
    //  of the content text view.
    //

    float screenHeightMinusBottom = self.contentTextView.frame.size.height + self.contentTextView.frame.origin.y;

    float heightOfBottom = self.view.frame.size.height - screenHeightMinusBottom;


    float insetAmount = kbSize.height - heightOfBottom;

    //
    //  Don't stretch the text to reach the keyboard if it's shorter.
    //

    if (insetAmount < 0) {
        return;
    }

    self.keyboardOverlapPortrait = insetAmount;

    float initialOriginX = self.contentTextView.frame.origin.x;
    float initialOriginY = self.contentTextView.frame.origin.y;

    [self.contentTextView setFrame:CGRectMake(initialOriginX, initialOriginY, self.contentTextView.frame.size.width, self.contentTextView.frame.size.height-insetAmount)];


}

Why would this work on iPhone, and not work on iPad? Also, can my autoresize masks be making an unexpected change?

Moshe
  • 57,511
  • 78
  • 272
  • 425
  • is the view a modalView? – WrightsCS Sep 18 '11 at 20:31
  • No, it is a UITextView, presented in a UINavigationController. – Moshe Sep 18 '11 at 20:39
  • but is the `UINavigationController` presented modally? – WrightsCS Sep 18 '11 at 20:59
  • @WrightCS No, it's part of a `UITabBarController`, which is loaded from a NIB. – Moshe Sep 18 '11 at 21:16
  • Yes, there can be problem in property `autoresizeMask`. What value do you set to your text view? – Nekto Sep 20 '11 at 14:06
  • @Nekto - I use interface builder to set it. Should I manually clear it in code? How? – Moshe Sep 20 '11 at 14:59
  • No, you can do it via IB. What value did you set? – Nekto Sep 20 '11 at 17:54
  • 2
    You realise that UIKeyboardFrameBeginUserInfoKey doesn't account for the orientation of your iPad. Could that be something to do with it? – bandejapaisa Sep 20 '11 at 18:15
  • @bandejapaisa - What are my alternatives? – Moshe Sep 21 '11 at 02:32
  • Well I'm not guaranteeing this is your problem. You can still use it, but you have to take into account the orientation of the device. The UIWindow API docs give a little guidance on it's usage: "These coordinates do not take into account any rotation factors applied to the window’s contents as a result of interface orientation changes. Thus, you may need to convert the rectangle to window coordinates (using the convertRect:fromWindow: method) or to view coordinates (using the convertRect:fromView: method) before using it.". – bandejapaisa Sep 21 '11 at 09:12
  • Alternatively, you can use [[UIDevice currentDevice] orientation]; and then switch the height and width, but this can be cumbersome - and watch out of FaceUpOrientation's which are waiting to catch you out.... – bandejapaisa Sep 21 '11 at 09:25

1 Answers1

3

Like said @bandejapaisa, I found that the orientation was a problem, at least during my tests.

The first thing, is about the use of kbSize.height being misleading, because in Landscape orientation it represents the width of the keyboard. So, as your code is in a UIViewController you can use it this way:

float insetAmount = (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)?kbSize.height:kbSize.width) - heightOfBottom;

The self.interfaceOrientation gives the orientation of the Interface (can be different from the Device orientation) and the macro UIInterfaceOrientationIsPortrait returns YES if the given orientation is Portrait (top or bottom). So as the keyboard height is in the kbSize.height when the interface is Portrait, and in the kbSize.width when the interface is Landscape, we simply need to test the orientation to get the good value.

But that's not enough, cause I've discovered the same problem with the self.view.frame.size.height value. So I used the same workaround:

float heightOfBottom = (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)?self.view.frame.size.height:self.view.frame.size.width) - screenHeightMinusBottom;

Hope this helps...

Zaphod
  • 6,758
  • 3
  • 40
  • 60
  • This seems to have solved it on the simulator. I'm going to test it and get back to you. Thanks! – Moshe Sep 21 '11 at 19:45
  • Works on the device too! I am sending this out to test soon and I'll award the bounty shortly thereafter. If you don't mind, please explain the first line of code though, I'm a little unsure how it helps. – Moshe Sep 22 '11 at 02:18
  • I think that checking `UIInterfaceOrientationIsPortrait ` is not correct. I'd rather advice to check using macros `UIInterfaceOrientationIsLandscape`. This is because first return `true` only for one orientation (button is at the bottom - portrait mode too) while second returns yes to both landscape orientations. – Nekto Sep 22 '11 at 13:29
  • Sorry @Nekto, but what you've said seems wrong. In fact `UIInterfaceOrientationIsPortrait` checks both portrait orientations. _cf._ `UIApplication.h` `#define UIInterfaceOrientationIsPortrait(orientation) ((orientation) == UIInterfaceOrientationPortrait || (orientation) == UIInterfaceOrientationPortraitUpsideDown)` see http://developer.apple.com/LIBRARY/IOS/#documentation/UIKit/Reference/UIKitFunctionReference/Reference/reference.html – Zaphod Sep 22 '11 at 14:38
  • Oh, i was mistaken. Sorry. Thanx +1 =) – Nekto Sep 22 '11 at 14:48