[英]How to detect when UIView size is changed in swift ios xcode?
I am trying some stuffs out with CATiledLayer inside UIScrollView.我正在 UIScrollView 中使用 CATiledLayer 尝试一些东西。
Somehow, the size of UIView inside the UIScrollView gets changed to a large number.不知何故, UIScrollView 内的 UIView 的大小被更改为一个很大的数字。 I need to find out exactly what is causing this resize.
我需要确切地找出导致这种调整大小的原因。
Is there a way to detect when the size of UIView(either frame, bounds) or the contentSize of UIScrollView is resized?
有没有办法检测 UIView(框架、边界)的大小或 UIScrollView 的 contentSize 何时调整大小?
I tried我试过
override var frame: CGRect {
didSet {
println("frame changed");
}
}
inside UIView subclass,在 UIView 子类中,
but it is only called once when the app starts, although the size of UIView is resized afterwards.但它只在应用程序启动时调用一次,尽管 UIView 的大小随后会调整大小。
There's an answer here:这里有一个答案:
https://stackoverflow.com/a/27590915/5160929 https://stackoverflow.com/a/27590915/5160929
Just paste this outside of a method body:只需将其粘贴到方法主体之外:
override var bounds: CGRect {
didSet {
// Do stuff here
}
}
viewWillLayoutSubviews()
and viewDidLayoutSubviews()
will be called whenever the bounds change. viewWillLayoutSubviews()
和viewDidLayoutSubviews()
会在边界改变时被调用。 In the view controller.在视图控制器中。
You can also use KVO:您还可以使用 KVO:
You can set a KVO like this, where view
is the view
you want to observe frame changes for:您可以像这样设置 KVO ,其中
view
是您要观察其帧变化的view
:
self.addObserver(view, forKeyPath: "center", options: NSKeyValueObservingOptions.New, context: nil)
And you can get the changes with this notification:您可以通过此通知获得更改:
override func observeValueForKeyPath(keyPath: String!, ofObject object: AnyObject!, change: NSDictionary!, context: CMutableVoidPointer) {
}
The observeValueForKeyPath
will be called whenever the frame of the view you are observing changes.每当您观察的视图框架发生变化时,就会调用
observeValueForKeyPath
。
Also remember to remove the observer when your view is about to be deallocated:还要记住在您的视图即将被释放时移除观察者:
view.removeObserver(self, forKeyPath:"center")
You can create a custom class, and use a closure to get the updated rect comfortably.您可以创建一个自定义类,并使用闭包来舒适地获取更新的矩形。 Especially handy when dealing with classes (like
CAGradientLayer
which want you to give them a CGRect
):在处理类时特别方便(比如
CAGradientLayer
想要你给它们一个CGRect
):
GView.swift
: 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)
}
}
Example Usage:示例用法:
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
}
If you are not adding your views through code, you can set the Custom Class property in storyboard to GView
.如果您不是通过代码添加视图,则可以将 Storyboard 中的 Custom Class 属性设置为
GView
。
Please note that the name GView
was chosen as a company measure and probably choosing something like FrameObserverView
would be better.请注意,名称
GView
是作为公司衡量标准选择的,可能选择FrameObserverView
类的FrameObserverView
会更好。
答案是正确的,尽管在我的情况下,我在情节提要中设置的约束导致 UIView 大小发生变化而没有回调任何检测功能。
STEP 1:viewWillLayoutSubviews第 1 步:viewWillLayoutSubviews
Called to notify the view controller that its view is about to layout its subviews
调用以通知视图控制器其视图即将布局其子视图
When a view's bounds change, the view adjusts the position of its subviews.
当视图的边界发生变化时,视图会调整其子视图的位置。 Your view controller can override this method to make changes before the view lays out its subviews.
您的视图控制器可以覆盖此方法以在视图布局其子视图之前进行更改。 The default implementation of this method does nothing.
此方法的默认实现不执行任何操作。
STEP 2:viewDidLayoutSubviews第 2 步:viewDidLayoutSubviews
Called to notify the view controller that its view has just laid out its subviews.
调用以通知视图控制器它的视图刚刚布局了它的子视图。
When the bounds change for a view controller's view, the view adjusts the positions of its subviews and then the system calls this method.
当视图控制器视图的边界发生变化时,视图会调整其子视图的位置,然后系统调用此方法。 However, this method being called does not indicate that the individual layouts of the view's subviews have been adjusted.
但是,调用此方法并不表示已调整视图子视图的各个布局。 Each subview is responsible for adjusting its own layout.
每个子视图负责调整自己的布局。
Your view controller can override this method to make changes after the view lays out its subviews.
您的视图控制器可以覆盖此方法以在视图布局其子视图后进行更改。 The default implementation of this method does nothing.
此方法的默认实现不执行任何操作。
Above these methods are called whenever bounds of UIView is changed每当UIView 的边界发生变化时,就会调用以上这些方法
For UIViews, as easy as:对于 UIViews,就像这样简单:
override func layoutSubviews() {
super.layoutSubviews()
setupYourNewLayoutHereMate()
}
You can use the FrameObserver Pod.您可以使用FrameObserver Pod。
It is not using KVO or Method Swizzling so won't be breaking your code if the underlying implementation of UIKit
ever changes.它不使用 KVO 或 Method Swizzling,因此如果
UIKit
的底层实现发生变化,则不会破坏您的代码。
whateverUIViewSubclass.addFrameObserver { frame, bounds in // get updates when the size of view changes
print("frame", frame, "bounds", bounds)
}
You can call it on a UIView
instance or any of its subclasses, like UILabel
, UIButton
, UIStackView
, etc.您可以在
UIView
实例或其任何子类上调用它,例如UILabel
、 UIButton
、 UIStackView
等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.