Цель c - автоматическое изменение размера UIView в альбомной ориентации

У меня есть viewController с 3 представлениями: topView, tableView и textView.

Я хочу, чтобы они выглядели так:

в портретном режиме -

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

в ландшафтном режиме:

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

И когда клавиатура поднята:

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

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

(как вы можете видеть, вид сверху исчез, когда клавиатура поднята)

код для этого:

- (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) {
        //
    }];
}

Большая часть того, что мне нужно, работает хорошо, проблема в том, что когда клавиатура отображается в ландшафтном режиме, все идет не так..

Обратите внимание на свойство views autoresizingMask, потому что я не уверен, что установил его сейчас.


person Eyal    schedule 06.06.2012    source источник


Ответы (2)


Для автоматического поворота попробуйте установить для маски верхнего вида только гибкую ширину, для средней — гибкую ширину и гибкую высоту, а для текстового вида — гибкую ширину и верхнее поле. Я сомневаюсь, что это будет работать без сучка и задоринки, но стоит попробовать. Вы можете переопределить willAnimateRotationToInterfaceOrientation:duration: на своем контроллере представления для пользовательской работы. Я почти уверен, что базовые автоматически вращающиеся маски не могут справиться с таким макетом, но я хотел бы оказаться неправым.

Также проверьте ориентацию в loadView следующим образом:

if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
    // do one layout
} else {
    // do another layout
}

Я также делаю очень индивидуальную работу по вращению в своем приложении (подумайте о специальном контроллере разделенного представления с нуля - фу), и я делаю это, используя willAutorotate и UIInterfaceOrientationIsLandscape.

Это может не относиться к вам из-за того, как вы сформулировали свой вопрос: я не уверен, что проблема заключается в том, что у вас открыта клавиатура, а затем поворот в альбомную ориентацию (в этом случае этот ответ может быть полезен); или у вас есть проблемы, когда вы открываете клавиатуру в альбомной ориентации (в этом случае этот ответ может не относиться к вам так сильно).

person aopsfan    schedule 06.06.2012
comment
› есть ли у вас проблемы при открытии клавиатуры в альбомной ориентации - ДА проблема именно в этом. На самом деле кажется, что autoresizingmask достаточно для правильного отображения вида, как я уже сказал, проблема возникает, когда я открываю клавиатуру. Только что заметил, что в альбомной ориентации высота клавиатуры 460?! - person Eyal; 07.06.2012
comment
В ПОРЯДКЕ. Да, высота клавиатуры для книжной и альбомной ориентации разная. вы можете использовать функцию UIInterfaceOrientationIsLandscape в методах keyboardWillShow и keyboardWillHide, чтобы определить, как компоновать представления. - person aopsfan; 07.06.2012

Я обнаружил проблему: когда я делал анимацию вверх/вниз в клавиатуреWillShow/willHide, я не преобразовывал прямоугольник клавиатуры с экрана в координаты просмотра.

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

Теперь работает нормально :)

person Eyal    schedule 06.06.2012