Подтвердить что ты не робот

UIScrollView отключает прокрутку во время вращения на iPhone/iPad

Я использую UIScrollView и изображение в нем как пейджинговое изображение на одной странице. У меня проблема при вращении iPhone

Когда я поворачиваю iPhone, вызывается scrollViewDidScroll (метод делегата прокрутки). Из-за этого мой пейджинг нарушен и номер страницы изменяется.

Какое решение?

4b9b3361

Ответ 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
    }