Search code examples
iphoneobjective-ciosuiviewautoresizingmask

Objective c - UIView autoresize in landscape


I have a viewController with 3 views: topView, tableView and textView.

I want them to layout like this:

in portrait mode -

|---------------|  
|    topView    |  
|---------------|
|               |
|               |
|   tableView   |
|               |
|               |
|---------------|               
|   textView    |
|---------------|

in landscape mode:

|--------------------------|  
|         topView          |  
|--------------------------|
|                          |
|        tableView         |
|--------------------------|               
|        textView          |
|--------------------------|

And when keyboard is up:

|---------------|  
|               |
|   tableView   |
|               |
|---------------|               
|   textView    |
|---------------|  
|               |
|   keyboard    |
|               | 
|---------------|  

|--------------------------|  
|        tableView         |
|--------------------------|               
|        textView          |
|--------------------------| 
|                          |
|        keyboard          |
|--------------------------|  

(as you can see the top view is gone when keyboard is up)

the code for doing this is:

- (void)loadView
{
    [super loadView];

    // load top view
    _topView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, TOP_VIEW_HEIGHT)];
    _topView.autoresizingMask =  UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
    _topView.backgroundColor = [UIColor redColor];
    [self.view addSubview:_topView];

    // load table view (at the middle)
    CGRect tableFrame = CGRectMake(0, TOP_VIEW_HEIGHT, self.view.bounds.size.width, self.view.bounds.size.height - TOP_VIEW_HEIGHT - TEXT_VIEW_HEIGHT);
    _tableView = [[UITableView alloc] initWithFrame:tableFrame style:UITableViewStylePlain];
    _tableView.autoresizingMask =  UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    _tableView.delegate = self;
    _tableView.dataSource = self;
    [self.view addSubview:_tableView];

    // load text view (at the bottom)
    CGRect textViewFrame = CGRectMake(0, tableFrame.size.height + TOP_VIEW_HEIGHT, self.view.bounds.size.width, TEXT_VIEW_HEIGHT);
    _textView = [[UITextView alloc] initWithFrame:textViewFrame];
    _textView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
    _textView.backgroundColor = [UIColor yellowColor];
    [self.view addSubview:_textView];
}  



- (void)keyboardWillShow:(NSNotification *)notification 
{
    NSDictionary *userInfo = [notification userInfo];

    // Get animation info from userInfo
    NSTimeInterval animationDuration;
    UIViewAnimationCurve animationCurve;


    [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
    [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];

    CGSize kbSize = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    CGRect textViewFrame = self.textView.frame;
    textViewFrame.origin.y -= kbSize.height;

    CGRect topViewFrame = self.topView.frame;
    topViewFrame.origin.y -= topViewFrame.size.height;

    CGRect tableFrame = self.tableView.frame;
    tableFrame.origin.y -= topViewFrame.size.height;
    tableFrame.size.height -= (kbSize.height - topViewFrame.size.height);

    [UIView animateWithDuration:animationDuration delay:0.0 options:animationCurve animations:^{
        self.textView.frame = textViewFrame;
        self.tableView.frame = tableFrame;
        self.topView.frame = topViewFrame;
    }completion:^(BOOL finished) {

    }];
}

- (void)keyboardWillHide:(NSNotification *)notification 
{
    NSDictionary *userInfo = [notification userInfo];

    // Get animation info from userInfo
    NSTimeInterval animationDuration;
    UIViewAnimationCurve animationCurve;


    [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
    [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];

    CGSize kbSize = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    CGRect textViewFrame = self.textView.frame;
    textViewFrame.origin.y += kbSize.height;

    CGRect topViewFrame = self.topView.frame;
    topViewFrame.origin.y += topViewFrame.size.height;

    CGRect tableFrame = self.tableView.frame;
    tableFrame.origin.y += topViewFrame.size.height;
    tableFrame.size.height += kbSize.height - topViewFrame.size.height;

    [UIView animateWithDuration:animationDuration delay:0.0 options:animationCurve animations:^{
        self.textView.frame = textViewFrame;
        self.tableView.frame = tableFrame;
        self.topView.frame = topViewFrame;
    }completion:^(BOOL finished) {
        //
    }];
}

Most of what I want works well, the problem is when keyboard is shown in landscape mode, then things goes wrong..

Please pay attention to the views autoresizingMask property, because I'm not sure I set it currently.


Solution

  • I found the problem, When I did the view's up/down animation in keyboardWillShow/willHide I didn't converted the keyboard rect from screen to view coordinates

    CGRect kbRect = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
    kbRect = [self.view convertRect:kbRect fromView:nil];
    CGSize kbSize = kbRect.size; 
    

    Now it's working fine :)