简体   繁体   English

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

[英]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实例或其任何子类上调用它,例如UILabelUIButtonUIStackView等。

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

相关问题 Xamarin Form - IOS:如何检测 UIView 大小已更改 - Xamarin Form - IOS: How to detect the UIView size changed 更改方向后如何更新uiview大小? - How to update uiview size when orientation is changed? Swift iOS-检测触摸拖动从UIView外部输入UIView - Swift iOS - Detect Touch Drag Enter UIView from outside UIView 如何以及在何处检测到自定义UIView大小动态更改并相应地调整滚动视图? - How and where to detect that a custom UIView size dynamically changed and adjust a scrollview accordingly? 更改父级(UIView)大小时的布局不更改 - Layout not changing when parent (UIView) size is changed iOS:在制作动画时,UIView会更改大小,如何防止这种情况发生? - iOS: UIView changes size when animating, how do I prevent that? 如果使用多任务处理时视图大小发生变化,如何设置通知 | 斯威夫特 - How to set Notification if view size changed when using multitasking | Swift 不使用键盘快速键检测何时更改UITextField - Detect when UITextField is changed not using the keyboard swift iOS:更改单元格背景时,UITableViewCell的侧面显示不同的颜色(Xcode 8,Swift 3) - iOS: Sides of UITableViewCell showing a different color when cell background is changed (Xcode 8, Swift 3) Xcode如何检测视图的属性已更改? - Xcode how to detect a view's properties changed?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM