UIScrollView отключает прокрутку во время вращения на iPhone/iPad
Я использую UIScrollView и изображение в нем как пейджинговое изображение на одной странице. У меня проблема при вращении iPhone
Когда я поворачиваю iPhone, вызывается scrollViewDidScroll (метод делегата прокрутки).
Из-за этого мой пейджинг нарушен и номер страницы изменяется.
Какое решение?
Ответы
Ответ 1
Ответ Raphaël - отличное описание проблемы и аккуратное исправление. У меня была такая же проблема, и я решил установить с флагом scrollingLocked
, который я установил для YES (заблокирован) до начала вращения, и NO (разблокирован), когда он закончится. Возможно, немного менее взломанный, чем временное изменение contentSize:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)orientation
duration:(NSTimeInterval)duration
{
self.photoViewer.scrollingLocked = YES;
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromOrientation
{
self.photoViewer.scrollingLocked = NO;
}
- (void)scrollViewDidScroll:(UIScrollView*)scrollView
{
if (self.scrollingLocked)
{
return;
}
/* do normal scrollViewDidScroll: stuff */
}
Ответ 2
Я обнаружил странное недокументированное поведение при вращении страничного UIScrollView
.
Когда прокрутка отображается на последней странице, и пользователь меняет ориентацию, ОС прокручивает UIScrollView
несколько пикселей назад, чтобы компенсировать разницу между высотой и шириной.
В основном я получил следующие вызовы для любой страницы.
willRotateToInterfaceOrientation:duration
willAnimateRotationToInterfaceOrientation:duration:
didRotateFromInterfaceOrientation:
И для последней страницы:
willRotateToInterfaceOrientation:duration
scrollViewDidScroll:
willAnimateRotationToInterfaceOrientation:duration:
didRotateFromInterfaceOrientation:
Это перепуталось с моими страницами тоже. Проблема в том, что в willRotate
границы еще не обновлены ОС, а в willAnimate
у вас есть новые границы и вы можете вычислить новый размер, но это слишком поздно...
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
CGSize tempSize = [self.pagingScrollView contentSize];
NSUInteger padding = abs(pagingScrollView.frame.size.width - pagingScrollView.frame.size.height);
tempSize.width += padding;
[self.pagingScrollView setContentSize:tempSize];
[...]
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration{
CGSize newSize = ... // Compute new content size based on new orientation
[self.pagingScrollView setContentSize:newSize];
}
Это всего лишь обходной путь, но я потратил бесчисленные часы на эту проблему и не смог найти элегантное решение.
Ответ 3
Моя задача - разрешить прокрутку ландшафта. Дизайн предназначен для portait. Я придумал добавить ScrollView к компонентам или в "Вставить в список прокрутки" в Interface Builder. Я ожидал, что это сработает, но нет. Я использую Xcode 4.4, iOS 5.1 (для поддержки офисного проекта также требуется 4.2), но проблема такая же.
В вопросе iPhone SDK: UIScrollView не прокручивает, есть одна строка, которая решает проблему.
Другая попытка в вопросе iOS - UIScrollView не работает (он не прокручивается вообще - изображение остается фиксированным), и это помогло мне, в сочетании с другими, так что вот мой пейзаж-прокручиваемый ландшафтный код:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromOrientation
{
if( UIInterfaceOrientationIsPortrait( [[UIApplication sharedApplication] statusBarOrientation] ) ){
scrollView.contentSize = portaitScrollSize;
}
else{//statusbar is Landscape
scrollView.contentSize = landscapeScrollSize;
}
}
ScrollView привязан к представлению iVar в Interface Builder. portaitScrollSize
и landscapeScrollSize
являются частными переменными. Они инициализируются и не меняются.
В файле my.h
:
IBOutlet UIScrollView *scrollView;
В my.m
файле:
CGSize portaitScrollSize, landscapeScrollSize;
...
portaitScrollSize = CGSizeMake(320,440);
landscapeScrollSize = CGSizeMake(480,480);
Я надеюсь, что это поможет кому-то добавить вращающуюся + прокрутку в проект portait.
Не забудьте разрешить portait + landscape на верхнем компоненте:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return TRUE;
}
Ответ 4
В дополнение к ответу Рафаэля Мор. Если вы переключаетесь с портрета на пейзаж, содержимое и структура страницы будут тормозить. Поэтому, чтобы поддерживать текущую структуру страницы, просто добавьте дополнительный размер содержимого в ширину:
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
[self.scrollView setContentSize:CGSizeMake(self.scrollView.contentSize.width + 400, self.scrollView.contentSize.height)];
}
И убедитесь, что вы изменили размер содержимого и смещение после изменения ориентации:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[self.scrollView setContentSize:CGSizeMake(self.scrollView.bounds.size.width *3, self.scrollView.bounds.size.height)];
[self.scrollView setContentOffset:CGPointMake(self.scrollView.bounds.size.width * self.pageControl.currentPage, 0) animated:NO];
}
Ответ 5
Решение Swift 4:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
lui.l("apply previousTraitCollection: \(previousTraitCollection)")
canScroll = true
}