在Swift中进行布局后获取UIScrollView的高度 [英] Get the height of the UIScrollView after layout in Swift

查看:474
本文介绍了在Swift中进行布局后获取UIScrollView的高度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在某些情况下,我正在使用UIScrollView来帮助使用较小手机的用户在窗口中看到全文.而且我想显示一个图像图标,如果他们需要滚动(只是为了让他们知道窗口内还有更多东西),但是我在使用Swift查找滚动视图的高度时遇到了问题.

I have a situation where I'm using a UIScrollView to help users with smaller phones see the full text inside a window. And I was wanting to show an image icon if they needed to scroll (just so that they know there is more inside the window) but I'm having a problem finding the height of the scrollview using Swift.

这是我对象的层次结构

基本上,这4个标签可放入4.7英寸iPhone内,但不能放入4英寸iPhone内.我尝试设置一些逻辑以检查UIScrollView内容是否大于窗口,但似乎无法正常工作.我不断得到高度为零.

Basically, those 4 labels fit inside a 4.7" iPhone but not the 4" iPhone. I tried setting some logic to check if the UIScrollView content is larger than the window, but it doesn't seem to be working. I keep getting that the height is zero.

我正在使用scrollHeight = scrollView.contentSize.height,并尝试将其放在viewDidLoad()viewWillAppear()viewDidLayoutSubviews()内,但每次最终都为0时.

I'm using scrollHeight = scrollView.contentSize.height and have tried putting that inside of viewDidLoad(), viewWillAppear(), and viewDidLayoutSubviews() but every time it ends up being 0.

contentSize是我应该用来检查高度的正确物品吗?

Is contentSize the right thing I should be using to check the height?

推荐答案

TL; DR;

作为一般指南,在调用viewDidLoad时,自动布局"并没有完成为视图提供尺寸的功能(在viewDidLayoutSubviews内部也不正确).要在查询其boundsframe之前确保所有视图及其子视图的大小正确,请执行以下操作:

As a general guide, Auto Layout does not finish giving views their size by the time viewDidLoad is called (neither is it correct inside viewDidLayoutSubviews). To make sure all views and their subviews have their correct sizes before querying their bounds or frame, do:

self.view.setNeedsLayout()
self.view.layoutIfNeeded()
print(self.someSubview.frame) // gives correct frame

说明

以某种与直觉相反的方式,将您的代码放入viewDidLayoutSubviews并不意味着所有子视图都已通过自动布局"获得了正确的大小.引用此方法的文档:

Somewhat counterintuitively, putting your code inside viewDidLayoutSubviews does not mean all sub-views have been given their correct size by Auto Layout. To quote the docs for this method:

但是,调用此方法并不表示该视图的子视图的各个布局已调整.

However, this method being called does not indicate that the individual layouts of the view's subviews have been adjusted.

这是什么意思:在viewDidLayoutSubviews中,只有子视图的第一个层次级别才具有正确的大小(即子视图,但没有子视图").

What this means is that: inside viewDidLayoutSubviews, only the first hierarchical-level of sub-views will have their correct size (i.e. child views but not "grandchild views").

这是我创建的示例布局(红色视图是子视图,蓝色视图是孙子视图).

Here is an example layout I created (the red view is the child, the blue view is the grandchild).

有关此示例的一些要点:

A few important points about this example:

  • 所有视图均使用自动布局"约束定位到其父视图(固定边距,但不固定宽度),这允许它们根据模拟器的屏幕尺寸来增大或缩小.在.
  • 我在情节提要中使用了iPhone 7大小的视图控制器,并在iPhone 7 Plus Simulator上运行了该示例.这意味着我可以确定视图会有所增长,并以此来确定视图是否具有原始大小或最终大小.
  • All views are positioned using Auto Layout constraints to their parent view (fixed margins, but not fixed widths), this allows them to grow or shrink depending on the screen size of the simulator I run this on.
  • I've used an iPhone 7 sized view controller in my storyboard, and ran the example on an iPhone 7 Plus Simulator. This means I can be sure the views will grow somewhat and use this to determine whether or not a view has its original size or its final size.

请注意,在Interface Builder中,子视图(红色)的原始宽度为240点,孙子视图(蓝色)的原始宽度为200点.

Note that in Interface Builder, the original width of the child view (red) is 240 points and the original width of the grandchild view (blue) is 200 points.

这是代码:

class ViewController: UIViewController {

    @IBOutlet weak var childView: UIView!
    @IBOutlet weak var grandchildView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        print("child     ", #function, childView.frame.size.width)
        print("grandchild", #function, grandchildView.frame.size.width)
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        print("child     ", #function, childView.frame.size.width)
        print("grandchild", #function, grandchildView.frame.size.width)
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        print("child     ", #function, childView.frame.size.width)
        print("grandchild", #function, grandchildView.frame.size.width)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        print("child     ", #function, childView.frame.size.width)
        print("grandchild", #function, grandchildView.frame.size.width)
    }
}

这是输出:

child      viewDidLoad() 240.0
grandchild viewDidLoad() 200.0
child      viewWillAppear 240.0
grandchild viewWillAppear 200.0
child      viewDidLayoutSubviews() 271.0 // `child` has it's final width now
grandchild viewDidLayoutSubviews() 200.0 // `grandchild` still has it's original width!

// By now, in MOST cases, all views will have their correct sizes.
child      viewDidAppear 271.0
grandchild viewDidAppear 231.0

从此输出中可以看到,viewDidLayoutSubviews 不能保证视图控制器主视图的直接子视图之外的任何内容都具有正确的大小.

What you can see from this output is that viewDidLayoutSubviews does not guarantee that anything past the immediate sub-views of the View Controller's principal view have their correct size.

注意:通常在调用viewDidAppear时,视图具有正确的大小,但是我要说这是绝对不能保证.

Note: Usually by the time viewDidAppear is called, views have their correct size, but I'd say this is by no means guaranteed.

这篇关于在Swift中进行布局后获取UIScrollView的高度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆