繁体   English   中英

ios - 如何在swift ios xcode中检测UIView大小何时更改?

[英]How to detect when UIView size is changed in swift ios xcode?

我正在 UIScrollView 中使用 CATiledLayer 尝试一些东西。

不知何故, UIScrollView 内的 UIView 的大小被更改为一个很大的数字。 我需要确切地找出导致这种调整大小的原因。

有没有办法检测 UIView(框架、边界)的大小或 UIScrollView 的 contentSize 何时调整大小?

我试过

override var frame: CGRect {
    didSet {
        println("frame changed");
    }
}

在 UIView 子类中,

但它只在应用程序启动时调用一次,尽管 UIView 的大小随后会调整大小。

这里有一个答案:

https://stackoverflow.com/a/27590915/5160929

只需将其粘贴到方法主体之外:

override var bounds: CGRect {
    didSet {
        // Do stuff here
    }
}

viewWillLayoutSubviews()viewDidLayoutSubviews()会在边界改变时被调用。 在视图控制器中。

您还可以使用 KVO:

您可以像这样设置 KVO ,其中view是您要观察其帧变化的view

self.addObserver(view, forKeyPath: "center", options: NSKeyValueObservingOptions.New, context: nil)

您可以通过此通知获得更改:

override func observeValueForKeyPath(keyPath: String!, ofObject object: AnyObject!, change: NSDictionary!, context: CMutableVoidPointer) {
    }

每当您观察的视图框架发生变化时,就会调用observeValueForKeyPath

还要记住在您的视图即将被释放时移除观察者:

view.removeObserver(self, forKeyPath:"center")

您可以创建一个自定义类,并使用闭包来舒适地获取更新的矩形。 在处理类时特别方便(比如CAGradientLayer想要你给它们一个CGRect ):

GView.swift

import Foundation
import UIKit

class GView: UIView {

    var onFrameUpdated: ((_ bounds: CGRect) -> Void)?

    override func layoutSublayers(of layer: CALayer) {
      super.layoutSublayers(of: layer)
      self.onFrameUpdated?(self.bounds)
    }
}

示例用法:

let headerView = GView()
let gradientLayer = CAGradientLayer()
headerView.layer.insertSublayer(gradientLayer, at: 0)
    
gradientLayer.colors = [
    UIColor.mainColorDark.cgColor,
    UIColor.mainColor.cgColor,
]
    
gradientLayer.locations = [
    0.0,
    1.0,
]
    
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)
    
headerView.onFrameUpdated = { _ in // here you have access to `bounds` and `frame` with proper values
    gradientLayer.frame = headerView.bounds
}

如果您不是通过代码添加视图,则可以将 Storyboard 中的 Custom Class 属性设置为GView

请注意,名称GView是作为公司衡量标准选择的,可能选择FrameObserverView类的FrameObserverView会更好。

答案是正确的,尽管在我的情况下,我在情节提要中设置的约束导致 UIView 大小发生变化而没有回调任何检测功能。

第 1 步:viewWillLayoutSubviews

调用以通知视图控制器其视图即将布局其子视图

当视图的边界发生变化时,视图会调整其子视图的位置。 您的视图控制器可以覆盖此方法以在视图布局其子视图之前进行更改。 此方法的默认实现不执行任何操作。

第 2 步:viewDidLayoutSubviews

调用以通知视图控制器它的视图刚刚布局了它的子视图。

当视图控制器视图的边界发生变化时,视图会调整其子视图的位置,然后系统调用此方法。 但是,调用此方法并不表示已调整视图子视图的各个布局。 每个子视图负责调整自己的布局。

您的视图控制器可以覆盖此方法以在视图布局其子视图后进行更改。 此方法的默认实现不执行任何操作。

每当UIView 的边界发生变化时,就会调用以上这些方法

对于 UIViews,就像这样简单:

    override func layoutSubviews() {
        super.layoutSubviews()

        setupYourNewLayoutHereMate()
    }

您可以使用FrameObserver Pod。

它不使用 KVO 或 Method Swizzling,因此如果UIKit的底层实现发生变化,则不会破坏您的代码。

whateverUIViewSubclass.addFrameObserver { frame, bounds in // get updates when the size of view changes
    print("frame", frame, "bounds", bounds)
}

您可以在UIView实例或其任何子类上调用它,例如UILabelUIButtonUIStackView等。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM