Как я могу исправить или обмануть этот столбец textField autolayout glitch?

Я думаю, что основная причина заключается в том, что estimatedRowHeight используется для предположения о базовом UIScrollView.contentOffset, но это всегда будет ошибочным по определению, поскольку это оценка. Действительные высоты строк полностью различаются в зависимости от содержимого ячейки и ориентации устройства.

Даже если я реализую estimatedHeightForRowAtIndexPath, чтобы обеспечить более близкие оценки, глюки все еще существуют.

Итак, когда вы начинаете вверху и прокручиваете вниз, все хорошо, потому что TableView изучает фактические высоты ячеек по мере того, как он держит содержимое в соответствии с положениями ячейки. Но как только вы вращаете все реальные высоты ячеек, чтобы UITableView теперь вышел из строя, он не знает, куда прокручиваться.

Но есть и еще более странные вещи, иногда ячейка UITextField оказывается поверх другой ячейки и остается там...

Во всяком случае, я отбросил все до простого примера.

https://github.com/trapper-/autolayout-glitch

  • Протестируйте с iPhone и, если используете симулятор, включите клавиатуру программного обеспечения.
  • Вы увидите много визуальных сбоев, просто играющих вокруг прокрутки, выбора полей и поворота.
  • Для простого повторяемого примера.
  • Прокрутите вниз.
  • Выберите одну из последних двух UITextField's, чтобы UITableView нужно прокрутить, чтобы убедиться, что поле будет видимым.
  • Поверните устройство.

Ответ 1

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

Что я могу предложить, так это то, что я действительно добился определенного прогресса.

Когда устройство вращается, вы должны реализовать методы UIViewcontroller, которые говорят вам, что это произойдет, и это произошло. Когда это произойдет, откройте видимые строки. Затем, после этого, перезагрузите таблицу и выделите эти видимые строки.

Он выглядит следующим образом:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    // Save the visible row position
    self.visibleRows = [self.tableView indexPathsForVisibleRows];
}

-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    [self.tableView reloadData];
    // Scroll to the saved position prior to screen rotate
    [self.tableView scrollToRowAtIndexPath:[self.visibleRows objectAtIndex:0] atScrollPosition:UITableViewScrollPositionBottom animated:NO];
}

visibleRows - это массив @property на вашем ViewController.

Это заставило его пойти в нужное место (я подозреваю, что если вы фактически сохранили отдельную ячейку, которую пользователь манипулировал, то каждый раз вы получите 100% в правильную ячейку.

То, что это не делало, заключается в том, что все еще есть танец UITextFields, который неправильно выведен (иногда) с несколькими поворотами устройства.

Опять же, не решение, но я хотел поделиться тем, что я видел так, надеюсь, это поможет вам найти решение.

Удачи!

Ответ 2

Я уверен, что ваша проблема связана с линией:

self.tableView.estimatedRowHeight = 44;

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

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    if (indexPath.row % 2) {

        return 44.f;

    } else {

        NSString *text = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";

        CGRect frame = [text boundingRectWithSize:CGSizeMake(350.f, CGFLOAT_MAX)
                                          options:NSStringDrawingUsesLineFragmentOrigin
                                       attributes:@{ NSFontAttributeName:[UIFont systemFontOfSize:14.f] }
                                          context:nil];

        return frame.size.height;
    }
}

Ответ 3

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

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath (NSIndexPath *)indexPath 
{
    if (indexPath.row % 2) {
        return 44.0f;
    } else {
        return 175.0f;
    }
}

Теперь, что касается странной проблемы с UITextField, я думаю, вам, возможно, придется подумать, что эти ячейки повторно используются даже при вращении, поэтому, если UITextField все еще является первым ответчиком, даже если ячейка была повторно использована, тогда это где на клавиатуре возникают проблемы с отслеживанием текстового поля.

Вы можете увидеть этот результат, просто установив тег на ячейку и посмотрев, как он случайным образом изменяет порядок при вращении так:

NSString* cellID = @"TextFieldCell";
TextFieldCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];
NSLog(@"cell %@, changing to %@", @(cell.tag), @(indexPath.row));
cell.tag = indexPath.row;
return cell;

Мое предложение состоит в том, чтобы: 1) не использовать текстовые поля в ячейках таблицы, или 2) думать о новом способе, позволяющем пользователю вводить текст для прокрутки элементов. Например, поместите копию текстового поля в представление поверх представления таблицы и управляйте этим вручную при вводе текста, а затем скопируйте текст обратно в ячейку, когда текст будет выполнен. 3) вариант 3 - попытаться выяснить, может ли библиотека диспетчера клавиатуры помочь. Мне очень нравится использовать IQKeyboardManager. Это действительно удобно для решения управления клавиатурой.