【问题标题】:UIScrollView Content Offset on InitializationUIScrollView 初始化时的内容偏移
【发布时间】:2020-08-18 08:20:15
【问题描述】:

我们目前正在为我们的 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,但初始化时似乎没有任何调整。如果用户选择它隐藏的按钮,然后取消隐藏它以正确显示它,没有逻辑调整它。给我的印象是这个问题在初始化。

总结: 当主视图加载时,当我需要关注第二张幻灯片时,滚动视图会向我显示索引中的第一张幻灯片。但是,如果用户隐藏然后取消隐藏滚动视图,它会按预期工作。

如何让 UIScrollView 实际加载和初始化更新滚动视图以显示第二张幻灯片而不是在第一张幻灯片上初始化?

【问题讨论】:

  • 你可以展示一些图片吗?
  • @King.lbt 我已经更新了照片,谢谢你的回复
  • 尝试在self.scrollRectToVisible(CGRect(x: frameWidth * CGFloat(scrollToIndex), y: 0, width: frameWidth, height: 1), animated: false)之前调用view.layoutIfNeeded()
  • 您是否尝试过使用 DispatchQueue.main.async {} 在主线程中显式运行 scrollRectToVisible?
  • @rs7 你能回答我的问题吗? :)

标签: ios swift uiscrollview


【解决方案1】:

尝试在主线程中显式运行scrollRectToVisible

DispatchQueue.main.async {

}

【讨论】:

    【解决方案2】:

    我的猜测是所有这些代码在视图被布局系统定位之前运行,并且第一张幻灯片的框架是默认的 0 x 0 大小。当应用程序返回此视图时,自动布局已计算出此幻灯片的大小,因此计算有效。

    点击布局循环以在布局后滚动到正确的位置。也许覆盖viewDidLayoutSubviews() 以检查它是否在初始布局中,然后设置滚动位置。

    【讨论】:

    • 我也是这么想的,于是上网查了一些博客。在加载滚动视图的父视图中,我调用了 scrollView.setContentView() 这只是调用 self.scrollRectToVisible(CGRect(x: frameWidth * CGFloat(scrollToIndex), y: 0, width: frameWidth, height: 1), animated: false) 以将其设置为可见并且它仍然位于索引 0 而不是索引 1。
    【解决方案3】:
    1. 对 contentView 使用约束,而不是设置 frame 和 autoresizingMask。
    2. 在scrollRectToVisible或setContentOffset之前调用view.layoutIfNeeded()在viewController中(我更喜欢最后一个)

    【讨论】:

      猜你喜欢
      • 2011-06-07
      • 2014-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多