0
votes

I have an iPhone application (Six Things) that I wrote in iOS 6 which has a screen where the user enters text into a UITextView. When the keyboard is shown, the size of the UITextView was automatically shortened so that as the user was typing, the cursor was not hidden behind the keyboard (see picture).

enter image description here

I used the following handlers to do this:

When the keyboard was shown:

- (void)keyboardDidShow:(id)sender
{
   NSDictionary* info = [sender userInfo];
   CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;  
   _txtSizeBase = self._txtInfo.frame;
   float offset = kbSize.height < kbSize.width?kbSize.height:kbSize.width;
    _txtSizeKeyboard = CGRectMake(_txtSizeBase.origin.x, _txtSizeBase.origin.y, _txtSizeBase.size.width, _txtSizeBase.size.height-offset+60);
   self._txtInfo.frame = _txtSizeKeyboard;   
...
}

When the "Done" button was pressed and the keyboard dismissed:

- (void)keyboardDidHide:(id)sender
{
   self._txtInfo.frame = _txtSizeBase;
...
}

This worked well in iOS 6. But in iOS 7, I don't know of a way to force the view to change its size AFTER the viewDidLoad has already been called. Changing the size of the frame does not cause it to resize.

I've turned off auto-layout on this form so that I can have the screen adjust elements properly (y position) for both iOS 6/7 (using deltas in interface builder).

Any helpful suggestions would be appreciated.

---------------------- EDIT WITH SOLUTION -----------------------------

Because the solution to this was a bit tricky, I thought it would be helpful to post it.

  1. I added a second .xib file for IOS6 (I only release for IOS 6+) with autolayout turned off and the positions adjusted as needed. Then I do the following:

    -(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { if(![DeviceInfo isIOSAfter70]) { self = [super initWithNibName:@"CreateRecordViewControllerIOS6" bundle:nibBundleOrNil]; } else { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; } }

** This is not the most elegant solution, but it works and I just want to support IOS 6 users, not move forward with IOS 6 dev, so there it is. **

  1. I turned on Auto Layout for the form:

enter image description here

  1. I set a bottom constraint on the text view and tied it to a an IBOutlet called _bottomConstraint.

  2. I modified the handlers for the KeyboardDidShow/Hide as follows:

-(void)keyboardDidHide:(id)sender { ... if([DeviceInfo isIOSAfter70]) { // IOS7+ if(_bottomConstraint != nil) { _bottomConstraint.constant = _bottomConstraintConstant; [self.view layoutIfNeeded]; } } ... }

-(void)keyboardDidShow:(id)sender { ... if([DeviceInfo isIOSAfter70]) { // IOS7+ if(_bottomConstraint != nil) { _bottomConstraintConstant = _bottomConstraint.constant; _bottomConstraint.constant += kbSize.height; [self.view layoutIfNeeded]; } } ... }

1
There is nothing changed about changing a view's frame in iOS 7. Your code will work as it did. I think you did something else wrong.ismailgulek
Hmmm....it doesn't seem to work in the simulator correctly...I'll try it on a real phone, perhaps the simulator is fibbing to me...FuzzyBunnySlippers
I checked it on a real device, iPhone 4 with iOS 7. It is broken there, but works as expected in iOS 6 for simulator (and did previously in iOS 6 on iPhone).FuzzyBunnySlippers

1 Answers

1
votes

I had similar issues with settings frames under iOS7. I think that it is not very wise to fight auto-constrains. Just enable auto-constrains (if you can) and animate constrains. You can create IBOutlet from constrain with Interface builder, or if you are creating constrains programatically leave reference to it. Than use code similar to this:

[self.view layoutIfNeeded];
self.constrainVertical.constant = 10;
[UIView animateWithDuration:0.3 animations:^{
    [self.view layoutIfNeeded];
} completion:^(BOOL finished) {
    //put some finalizing code here if needed
}];

I am moving just one constrain, just to show you how it can be done. Also, when using constrains, forget about setting frames directly.

Hope it helps.