Смещение содержимого UIScrollView при инициализации - PullRequest
0 голосов
/ 04 мая 2020

В настоящее время мы работаем в более старой кодовой базе для нашего приложения iOS и сталкиваемся со странной ошибкой, когда подкачка UIScrollViews не совпадает при инициализации, а только после того, как пользователь выбирает кнопку, чтобы изменить представление.

Каждый ScrollView имеет три слайда, вложенных в них. Мы инициализируем ScrollView следующим образом:

override init(frame: CGRect) {
    super.init(frame: frame)
    self.commonInit()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    self.commonInit()
}

private func commonInit() {

    Bundle.main.loadNibNamed("DIScrollView", owner: self, options: nil)
    contentView.frame = self.bounds
    addSubview(contentView)
    contentView.autoresizingMask = [.flexibleHeight,.flexibleWidth]
    contentView.layer.borderColor = UIColor.white.cgColor
    contentView.layer.borderWidth = 2.0

    scrollView.delegate = self
    setUpScrollViewer()
}

Вы видите, что мы вызываем настройку ScrollView, и это делается так:

public func setUpScrollViewer() {

    let slides = self.createSlides()
    let defaultIndex = 1
    scrollView.Initialize(slides: slides, scrollToIndex: defaultIndex)


    pageControl.numberOfPages = slides.count
    pageControl.currentPage = defaultIndex
}

Теперь, когда весь контент доступен для на каждом слайде мы хотим обрабатывать контент, и мы делаем это с расширением ScrollView:

extension UIScrollView {

//this function adds slides to the scrollview and constraints to the subviews (slides)
//to ensure the subviews are properly sized
func Initialize(slides:[UIView], scrollToIndex:Int) {

    //Take second slide to base size from
    let frameWidth = slides[1].frame.size.width

    self.contentSize = CGSize(width: frameWidth * CGFloat(slides.count), height: 1)

    for i in 0 ..< slides.count {

        //turn off auto contstraints. We will be setting our own
        slides[i].translatesAutoresizingMaskIntoConstraints = false

        self.addSubview(slides[i])

        //pin the slide to the scrollviewers edges
        if i == slides.startIndex {
            slides[i].leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
        } else { //pin each subsequent slides leading edge to the previous slides trailing anchor
            slides[i].leadingAnchor.constraint(equalTo: slides[i - 1].trailingAnchor).isActive = true
        }

        slides[i].topAnchor.constraint(equalTo: self.topAnchor).isActive = true
        slides[i].widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
        slides[i].heightAnchor.constraint(equalTo: self.heightAnchor).isActive = true
    }

    //the last slides trailing needs to be pinned to the scrollviewers trailing.
    slides.last?.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true


    self.scrollRectToVisible(CGRect(x: frameWidth * CGFloat(scrollToIndex), y: 0, width: frameWidth, height: 1), animated: false)

}

}

Я попытался вручную установить contentOffset, и, похоже, ничего не изменилось при инициализации. Если пользователь выбирает кнопку, которую он скрывает, а затем показывает ее, чтобы отобразить ее должным образом без логики c, регулирующей это. У меня сложилось впечатление, что эта проблема связана с инициализацией.

Резюме: при загрузке основного вида scrollView показывает мне первый слайд в индексе, когда мне нужно сфокусироваться на втором слайде. Однако, если пользователь скрывает, а затем показывает scrollView, он работает как задумано.

Как мне заставить UIScrollView фактически загружать и инициализировать обновление scrollView, чтобы показать второй слайд, а не инициализировать на первом слайде?

1 Ответ

0 голосов
/ 04 мая 2020

Я предполагаю, что весь этот код выполняется до того, как представления позиционируются системой компоновки, а кадр первого слайда имеет размер по умолчанию 0 x 0. Когда приложение вернется в это представление, автоматический макет вычислил размер этого слайда, поэтому расчет работает.

Нажмите в цикле макета, чтобы перейти к нужному месту после макета. Возможно, переопределите viewDidLayoutSubviews(), чтобы проверить, находится ли он в исходном макете, а затем установите положение прокрутки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...