UIScrollView корректирует contentOffset при изменении contentSize - PullRequest
36 голосов
/ 29 июня 2011

Я настраиваю состояние контроллера подробного вида, непосредственно перед тем, как оно выдвигается на navigationController:

[self.detailViewController detailsForObject:someObject];
[self.navigationController pushViewController:self.detailViewController
                                     animated:YES];

В DetailViewController находится scrollView.Какое содержимое я изменяю в зависимости от переданного объекта:

- (void)detailsForObject:(id)someObject {
    // set some textView's content here
    self.contentView.frame = <rect with new calculated size>;

    self.scrollView.contentSize = self.contentView.frame.size;
    self.scrollView.contentOffset = CGPointZero;
}

Теперь все это работает, но scrollView корректирует его contentOffset во время анимации вставки навигационного контроллера.contentOffset будет установлен на разницу между последним contentSize и новым вычисленным.Это означает, что во второй раз, когда вы открываете DetailsView, детали будут прокручиваться в какое-то нежелательное место.Даже при том, что я явно устанавливаю contentOffset в CGPointZero.

Я обнаружил, что сброс contentOffset в - viewWillAppear не имеет никакого эффекта.Лучшее, что я мог придумать, это сбросить contentOffset в viewDidAppear, вызывая заметное движение вверх и вниз контента:

- (void)viewDidAppear:(BOOL)animated {
    self.scrollView.contentOffset = CGPointZero;
}

Есть ли способ, чтобы UIScrollView не смог настроить contentOffset когда его contentSize изменяется?

Ответы [ 7 ]

58 голосов
/ 02 декабря 2013

Происходит при нажатии UIViewController, содержащем UIScrollView, с использованием UINavigationController.

iOS 7

Решение 1 (код)

Установить @property(nonatomic, assign) BOOL automaticallyAdjustsScrollViewInsets на NO.

Решение 2 (Раскадровка)

Снять отметку Adjust Scroll View Insets

Adjust Scroll View Insets

iOS 6

Решение (код)

Установить UIScrollView собственность contentOffset и contentInset в viewWillLayoutSubviews.Пример кода:

- (void)viewWillLayoutSubviews{
  [super viewWillLayoutSubviews];
  self.scrollView.contentOffset = CGPointZero;
  self.scrollView.contentInset = UIEdgeInsetsZero;
}
15 голосов
/ 11 июля 2011

Причина этой проблемы остается неясной, хотя я нашел решение. Сбрасывая размер содержимого и смещение перед их настройкой, UIScrollView не анимирует:

- (void)detailsForObject:(id)someObject {
    // These 2 lines solve the issue:
    self.scrollView.contentSize = CGSizeZero;
    self.scrollView.contentOffset = CGPointZero;

    // set some textView's content here
    self.contentView.frame = <rect with new calculated size>;

    self.scrollView.contentSize = self.contentView.frame.size;
    self.scrollView.contentOffset = CGPointZero;
}
2 голосов
/ 23 сентября 2013

У меня была такая же проблема с UIScrollview, где проблема была вызвана не установкой contentSize.После установки для contentSize количества элементов эта проблема была решена.

self.headerScrollView.mainScrollview.contentSize = CGSizeMake(320 * self.sortedMaterial.count, 0);
1 голос
/ 13 июля 2018

Вот что сработало для меня:
В раскадровке в инспекторе размеров для scrollView установите для параметра «Корректировка вставок содержимого» значение «Никогда».

enter image description here

0 голосов
/ 17 июля 2018

У меня возникла похожая проблема, когда UIKit устанавливал contentOffset моего scrollView во время анимации push.

Ни одно из этих решений не работало для меня, возможно, потому что я поддерживал iOS 10 и iOS 11.

Мне удалось исправить мою проблему путем создания подкласса моего прокрутки, чтобы UIKit не мог изменить мои смещения после удаления прокрутки из окна:

/// A Scrollview that only allows the contentOffset to change while it is in the window hierarchy. This can keep UIKit from resetting the `contentOffset` during transitions, etc.
class LockingScrollView: UIScrollView {
    override var contentOffset: CGPoint {
        get {
            return super.contentOffset
        }
        set {
            if window != nil {
                super.contentOffset = newValue
            }
        }
    }
}
0 голосов
/ 16 августа 2012

Я столкнулся с проблемой, и для конкретного случая - я не регулирую размер - я использовал следующее:

float position = 100.0;//for example

SmallScroll.center = CGPointMake(position + SmallScroll.frame.size.width / 2.0, SmallScroll.center.y);

То же самое будет работать с y: anotherPosition + SmallScroll.frame.size.height / 2.0

Так что, если вам не нужно изменять размер, это быстрое и безболезненное решение.

0 голосов
/ 29 июня 2011

Является ли ваш scrollView корневым представлением DetailViewController?Если да, попробуйте обернуть scrollView в простой UIView и сделать последний корневым представлением DetailViewController.Поскольку UIView s не имеют свойства contentOffset, они не защищены от корректировок смещения содержимого, выполняемых контроллером навигации (из-за панели навигации и т. Д.).

...