UIScrollView анимация высоты и содержимогоОффсет «прыгает» содержимое снизу

Пытаясь сделать что-то похожее на поведение Message.app, у меня есть UIScrollView и под ним текстовое поле, и пытаюсь его оживить, чтобы при появлении клавиатуры все было перемещено вверх над клавиатурой, используя ограничение, которое перемещает поле вверх ( и высота UIScrollView изменяется также из-за автовыброса), а также одновременную настройку contentOffset для прокрутки вниз.

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

Анимация такова:

 - (void)updateKeyboardConstraint:(CGFloat)height animationDuration:(NSTimeInterval)duration { self.keyboardHeight.constant = -height; [self.view setNeedsUpdateConstraints]; [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ [self.view layoutIfNeeded]; self.collectionView.contentOffset = CGPointMake(0, self.collectionView.contentSize.height - self.collectionView.bounds.size.height); } completion:nil]; } 

Видео о проблеме доступно здесь .

Благодаря!

6 Solutions collect form web for “UIScrollView анимация высоты и содержимогоОффсет «прыгает» содержимое снизу”

Это может быть ошибка в UIKit. Это происходит, когда происходит одновременное изменение size и contentOffset UIScrollView . Было бы интересно проверить, не происходит ли это поведение без автоматического макета.

Я нашел две обходные пути этой проблемы.

Использование contentInset (подход «Сообщения»)

Как видно из приложения «Сообщения», высота UIScrollView не изменяется при отображении клавиатуры – сообщения видны под клавиатурой. Вы можете сделать то же самое. Удалите ограничение между UICollectionView и представлением, которое содержит UITextField и UIButton (я буду называть его messageComposeView ). Затем добавьте ограничение между UICollectionView и Bottom Layout Guide . Удерживайте ограничение между messageComposeView и руководством по messageComposeView Bottom Layout Guide . Затем используйте contentInset чтобы визуально UICollectionView последний элемент UICollectionView над клавиатурой. Я сделал это следующим образом:

 - (void)updateKeyboardConstraint:(CGFloat)height animationDuration:(NSTimeInterval)duration { self.bottomSpaceConstraint.constant = height; [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ CGPoint bottomOffset = CGPointMake(0, self.collectionView.contentSize.height - (self.collectionView.bounds.size.height - height)); [self.collectionView setContentOffset:bottomOffset animated:YES]; [self.collectionView setContentInset:UIEdgeInsetsMake(0, 0, height, 0)]; [self.view layoutIfNeeded]; } completion:nil]; } 

Здесь self.bottomSpaceConstraint является ограничением между messageComposeView и Bottom Layout Guide . Вот видео, показывающее, как это работает. ОБНОВЛЕНИЕ 1: Вот источник моего проекта на GitHub . Этот проект немного упрощен. Я должен был учитывать параметры, переданные в уведомлении в - (void)keyboardWillShow:(NSNotification *)notif .

Выполнение изменений в очереди

Не точное решение, но прокрутка отлично работает, если вы переместите его в блок завершения:

 } completion:^(BOOL finished) { [self.collectionView setContentOffset:CGPointMake(0, self.collectionView.contentSize.height - self.collectionView.bounds.size.height) animated:YES]; }]; 

Для отображения клавиатуры требуется 0,25 с, поэтому разница между началом анимации может быть заметной. Анимация также может быть выполнена в обратном порядке.

ОБНОВЛЕНИЕ 2: Я также заметил, что код OP отлично работает с этим изменением:

 CGPoint bottomOffset = CGPointMake(0, self.collectionView.contentSize.height - (self.collectionView.bounds.size.height - height)); 

но только тогда, когда height contentSize меньше некоторого фиксированного значения ( в моем случае около 800 , но мой макет может немного отличаться).

В конце концов, я думаю, что подход, который я представил в Using contentInset (the Messages approach) , лучше, чем изменение размера UICollectionView . При использовании contentInset мы также получаем видимость элементов под клавиатурой. Это, безусловно, соответствует стилю iOS 7.

У меня была аналогичная проблема – при анимации кадра и смещении содержимое «прыгало» прямо перед анимацией в позицию – и решение UIViewAnimationOptionBeginFromCurrentState просто добавляло UIViewAnimationOptionBeginFromCurrentState к параметрам анимации. Вуаля!

setNeedsUpdateConstraints ли setNeedsUpdateConstraints ? не автоматическая компоновка делает это автоматически?

Если нет – я бы предложил вам сделать всю анимацию изменения размера без использования автоматического макета. похоже, проблема заключается в том, что вы пытаетесь объединить обе анимации (но это не в одно и то же время)

Попытайтесь удалить [self.view layoutIfNeeded] и посмотреть, не исчезла ли проблема или возникли ли другие проблемы, и если да, если они выглядят как-то связанные.

Кроме того, всегда рекомендуется сбросить позицию ваших просмотров прямо перед анимацией. Поэтому попробуйте установить нормальное смещение непосредственно перед линией анимации (и, возможно, даже вызовите метод layoutIfNeeded ). Сортировка всего в порядке перед началом анимации.

Я не уверен, что это именно то, что вы хотите, но, возможно, это может дать вам толчок в правильном направлении: проект Github

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

Затем при вызове анимации я анимацию "center" свойства обоих элементов, а не contentOffset, и я обрабатываю значение анимации и значение ограничения отдельно.

Конечный результат здесь:

YouTube видео

У меня была та же проблема, я смог ее решить, зарегистрировав NSNotifications для клавиатуры, скрывая и показывая. Я предоставляю код для этого. Надеюсь, это поможет вам.

просто объявить BOOL isMovedUp в вашем классе .h

В ViewDidLoad

 // registering notifications for keyboard/hiding and showing [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide) name:UIKeyboardWillHideNotification object:nil]; } #pragma mark-keyboard notifications - (void)keyboardWillShow { // Animate the current view out of the way if (isMovedUp==YES){ } else { [self setViewMovedUp:YES]; isMovedUp=YES; } } - (void)keyboardWillHide { if (isMovedUp==YES) { [self setViewMovedUp:NO]; isMovedUp=NO; } } //method for view transformation -(void)setViewMovedUp:(BOOL)movedUp { [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.5]; // if you want to slide up the view CGRect rect = self.winePopUpView.frame; if (movedUp) { //isKeyBoardDown = NO; // 1. move the view's origin up so that the text field that // will be hidden come above the keyboard // 2. increase the size of the view so that the area // behind the keyboard is covered up. rect.origin.y -= 100; //rect.size.height += 100; } else { // revert back to the normal state. rect.origin.y += 100; //rect.size.height -= 100; //isKeyBoardDown = YES; } self.winePopUpView.frame = rect; [UIView commitAnimations]; } 
  • Как сбросить настройки после масштабирования UIScrollView?
  • как перемещаться в одном направлении в UIScrollView при прокрутке
  • UIScrollView не будет работать
  • UIScrollView подкачки в одном направлении
  • UIScrollView блокирует все касания во время масштабирования или прокрутки
  • iOS анимация UIScrollView после анимации
  • UIButton останавливает прокрутку UIScrollView в Swift
  • UIScrollView - добавьте Subview так, чтобы он был центрирован по горизонтали и по вертикали
  • Поверните колесо на основе прокрутки в UIScrollView
  • Как предотвратить ручное масштабирование в UIScrollView
  • Как отображать полосу прокрутки UIScrollView / s навсегда, а не просто мигать?
  • PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.