UIScrollView未正确显示子视图

时间:2018-03-25 08:43:58

标签: swift

我正在尝试向scrollView显示简单的自定义视图。这是我的代码:

struct scrollViewDataStruct {
    let title: String?
    let image: UIImage?
}

class ViewController: UIViewController {
     @IBOutlet weak var scrollView: UIScrollView!

     var scrollViewData = [scrollViewDataStruct]()

     override func viewDidLoad() {
         super.viewDidLoad()
         scrollViewData = [
         scrollViewDataStruct(title: "First", image: #imageLiteral(resourceName: "iPhone 8 Copy 2")),
        scrollViewDataStruct(title: "Second", image: #imageLiteral(resourceName: "iPhone 8 Copy 3"))
    ]
    self.scrollView.backgroundColor = .yellow
    scrollView.contentSize.width = self.scrollView.frame.width * CGFloat(scrollViewData.count)
    var i = 0
    for _ in scrollViewData {
        let view = CustomView(frame: CGRect(x: self.scrollView.frame.width * CGFloat(i), y: 0, width: scrollView.frame.width, height: self.scrollView.frame.height))
        self.scrollView.addSubview(view)
        i += 1
    }
    // Do any additional setup after loading the view, typically from a nib.
}

}

class CustomView: UIView {

let imageView: UIImageView = {
   let imageView = UIImageView()
    imageView.translatesAutoresizingMaskIntoConstraints = false
    imageView.backgroundColor = UIColor.blue
    return imageView
}()

override init(frame: CGRect) {
    super.init(frame: frame)
    self.addSubview(imageView)
    imageView.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
    imageView.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
    imageView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
    imageView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}    
}

正如您所见,CustomView's frame = scrollView's frame但是当我运行应用程序时,它并不像我预期的那样:

然后,在故事板中,我将设备从iphone8更改为iphone 8 plus并再次运行。它正确显示CustomView。我不知道,scrollView始终是正确的,但CustomView不是。 有什么建议?

2 个答案:

答案 0 :(得分:0)

  

在viewDidLoad中,UI组件将假设您具有在故事板中所采用的大小。

有两种方法可以做到这一点:

<强> 1。使用autoresizingMask属性

autoresizingMask属性将调整视图大小,如果其containerView的框架已更改

    var i = 0
    for _ in scrollViewData {
        let view = CustomView(frame: CGRect(x: self.scrollView.frame.width * CGFloat(i), y: 0, width: scrollView.frame.width, height: self.scrollView.frame.height))
        view.autoresizingMask = .flexibleHeight
        self.scrollView.addSubview(view)
        i += 1
    }

<强> 2。使用固定参数,例如UIScreen.main.bounds.size.height

只需参考屏幕高度而不是滚动视图的高度来更新自定义视图高度的代码。它会正常工作

    var i = 0
    let height = UIScreen.main.bounds.size.height
    for _ in scrollViewData {
        let view = CustomView(frame: CGRect(x: self.scrollView.frame.width * CGFloat(i), y: 0, width: scrollView.frame.width, height: height))
        self.scrollView.addSubview(view)
        i += 1
    }

答案 1 :(得分:0)

您的问题是您在自动布局运行之前访问了scrollView的frame,并确定了实际设备frame的大小。快速解决方法是将您的设置代码移到viewDidLayoutSubviews的覆盖中。 但是你必须要小心,因为与viewDidLoad不同,viewDidLayoutSubviews会运行多次,所以你必须确保多次不添加你的观点。

// property - have we set up the views yet?
var setup = false

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    if !setup {
        scrollView.contentSize.width = self.scrollView.frame.width * CGFloat(scrollViewData.count)
        var i = 0
        for _ in scrollViewData {
            let view = CustomView(frame: CGRect(x: self.scrollView.frame.width * CGFloat(i), y: 0, width: scrollView.frame.width, height: self.scrollView.frame.height))
            self.scrollView.addSubview(view)
            i += 1
        }
        setup = true
    }
}

您应该考虑使用约束将视图放在scrollView内容中而不是弄乱frame计算,然后自动布局会自动做正确的事情。