UITableView мерцает/заикается при вводе текста при автоматическом изменении размера TextView
В настоящее время у меня есть UITableView
с изменением размера UITextView
. Ячейка автоматически изменяет размер, используя beginUpdates
/endUpdates
, но когда он делает это, просмотр таблицы заикается (см. Ниже gif).
Конечным результатом является UITableViewCell
, у которого есть текстовое представление, которое изменяет размер на основе его содержимого. Вот код внутри пользовательского класса UITableViewCell
, который заставляет UITableView
обновлять себя.
- (void)textViewDidChange:(UITextView *)textView {
// This is a category on UITableViewCell to get the [self superView] as the UITableView
UITableView *tableView = [self tableView];
if (tableView){
[tableView beginUpdates];
[tableView endUpdates];
}
}
Вот что я уже пробовал:
Получить текущий contentOffset
и сбросить его после endUpdates
, но не работать
Отключение прокрутки на UITableView
перед обновлениями и последующее включение впоследствии
Я пробовал возвращать NO
всегда из - (BOOL)textViewShouldEndEditing:(UITextView *)textView
Моя высота ячейки UITableView
использует UITableViewAutomaticDimension
. Любые другие идеи или мысли приветствуются.
Вот пример того, как он выглядит:
![Table View Stutter]()
Я не хочу использовать какие-либо библиотеки, поэтому, пожалуйста, никаких предложений для этого.
Спасибо
Изменить: решение
Найдено здесь: Я не хочу, чтобы анимация начала обновления, конец блока обновлений для uitableview?
Кредит @JeffBowen для отличной находки (хотя хакки он работоспособен и позволяет мне по-прежнему внедрять методы UITableViewDelegate
для поддержки iOS 7). Отключите анимацию до выполнения обновления, а затем включите после обновления, чтобы предотвратить UITableView
от заикания.
[UIView setAnimationsEnabled:NO];
[tableView beginUpdates];
[tableView endUpdates];
[UIView setAnimationsEnabled:YES];
Если вам не нужно использовать методы Delegate и хотите использовать менее хакерское решение для iOS 8+, тогда перейдите к ответу @Massmaker ниже.
Ответы
Ответ 1
Мое решение (для iOS 8) было впервые установлено в моем представленииController viewDidLoad
self.tableView.rowHeight = UITableViewAutomaticDimension;
// this line is needed to cell`s textview change cause resize the tableview`s cell
self.tableView.estimatedRowHeight = 50.0;
затем, объединив эту статью решение в Swift и некоторые грязные мысли
Я установил в своей ячейке свойство, называемое
@property (nonatomic, strong) UITableView *hostTableView;
и в ячейке -(void) textViewDidChange:(UITextView *)textView
CGFloat currentTextViewHeight = _textContainer.bounds.size.height;
CGFloat toConstant = ceilf([_textContainer sizeThatFits:CGSizeMake(_textContainer.frame.size.width, FLT_MAX)].height);
if (toConstant > currentTextViewHeight)
{
[_hostTableView beginUpdates];
[_hostTableView endUpdates];
}
то в viewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
textCell.hostTableView = self.tableView;
![after height change]()
Ответ 2
Просто отключите анимацию перед вызовом beginUpdates
и снова включите ее после вызова endUpdates
.
[UIView setAnimationsEnabled:NO];
[tableView beginUpdates];
[tableView endUpdates];
[UIView setAnimationsEnabled:YES];
Определенно взломать, но работает пока. Благодарим моего друга Бо, который указал мне на этот.
Ответ 3
Я не нашел способ добиться этого, потому что:
Когда вы запускаете [endViews таблицы tableView], таблица пересчитывает contentSize и повторно устанавливает его. И это приведет к сбросу значения contentOffset по умолчанию.
Это поведение, унаследованное от UIScrollView, и я попытался его избежать:
- Подклассификация UITableView и переопределение функций
setContentOffset:
и setContentOffset:animated
. Но они не вызывают, когда table view меняет contentSize.
- Подкласс UITableView, переопределение функции
setContentSize:
и настройка contentOffset на старое значение после обновления содержимого, но это не работает для меня
- с помощью KVO и установкой старого значения для contentOffset сразу после него reset, но в любом случае у меня есть эта анимированная проблема.
- настройка scrollEnabled для NO и scrollToTop для NO, но также не помогает
Если кто-нибудь найдет решение для этой проблемы, добро пожаловать.
Возможно, это возможное решение - отключить автоматическое отключение: iOS: setContentSize заставляет весь кадр UIScrollView перейти
UPDATE: Я нахожу решение: прямое изменение высоты ячейки, размера содержимого и смещения содержимого:
Это работает для меня (представление таблицы является делегатом ячейки UITextView)
- (void)textViewDidChange:(UITextView *)textView
{
CGFloat textHeight = [textView sizeThatFits:CGSizeMake(self.width, MAXFLOAT)].height;
if (self.previousTextHeight != textHeight && self.previousTextHeight > 0) {
CGFloat difference = textHeight - self.previousTextHeight;
CGRect cellFrame = self.editedCell.frame;
cellFrame.size.height += difference;
self.editedCell.frame = cellFrame;
self.contentSize = CGSizeMake(self.contentSize.width, self.contentSize.height + difference);
self.contentOffset = CGPointMake(self.contentOffset.x, self.contentOffset.y + difference);
}
self.editedNote.comments = textView.text;
}
Ответ 4
В Textview делегат изменения значения используйте этот код, чтобы изменить размер отдельной ячейки без каких-либо мерцаний и все такое. Но перед этим убедитесь, что вы использовали динамическую высоту ячейки таблицы.
UIView.setAnimationsEnabled(false)
DispatchQueue.main.async {
self.tableView.beginUpdates()
self.tableView.endUpdates()
self.tableView.layer.removeAllAnimations()
}
UIView.setAnimationsEnabled(true)