如果我在 运行 应用程序中使用 IBDesignable 文件,为什么自动布局不会更新?
why the autolayout is not updated if I use IBDesignable file when i run the app?
这里是这个问题在google驱动器中的项目:https://drive.google.com/file/d/1Js0t-stoerWy8O8uIOJl_bDw-bnWAZPr/view?usp=sharing
我使用下面的 IBDesignable 代码制作了一个自定义导航栏(下图中的红色视图)。我想,如果 iPhone 有像 iPhone X, iPhone XR 这样的顶级,那么自定义导航栏的高度是 88,否则高度是 64。我制作了一个 IBDesignable 代码我可以重用这段代码
import UIKit
@IBDesignable
class CustomParentNavigationBarView: UIView {
override func awakeFromNib() {
super.awakeFromNib()
self.setHeight()
}
override func layoutSubviews() {
super.layoutSubviews()
self.setHeight()
}
func setHeight() {
let deviceHasTopNotch = checkHasTopNotchOrNot()
layer.frame.size.height = deviceHasTopNotch ? 88 : 64
}
func checkHasTopNotchOrNot() -> Bool {
if #available(iOS 11.0, tvOS 11.0, *) {
// with notch: 44.0 on iPhone X, XS, XS Max, XR.
// without notch: 20.0 on iPhone 8 on iOS 12+.
return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 20
}
return false
}
}
我把这个CustomParentNavigationBarView
分配给红色view
然后,我贴上标签。应该正好位于红色视图下方(自定义导航栏,使用 IBDesignable)
如果我 运行 iPhone 中的应用程序没有像 iPhone8 这样的顶级应用程序,它看起来很棒
但是,如果我 运行 iPhone 中具有像 iPhone XR 这样一流的应用程序,标签现在在红色视图中,它似乎仍然遵循之前的自动布局之前 64 的红色视图高度(在情节提要中我使用 iPhone 8),因此当自定义导航栏在 iPhone XR 上 运行ning 更新为 88 时,标签仍然按照之前的64高度,就会定位到红色view里面
这里是自定义导航栏的自动布局(红色视图)
这里是标签的自动布局
如何解决这个问题?
这里的问题是您在 setHeight() 中指定了框架高度,但也在故事板中指定了布局约束的高度。解决此问题的一种方法是为您的视图指定一个 intrinsicContentSize,而不是将高度指定为情节提要中的布局约束。 (I.o.w。类似于你依赖标签宽度的方式给你计算)
@IBDesignable
class CustomParentNavigationBarView: UIView {
lazy var deviceHasTopNotch: Bool = {
if #available(iOS 11.0, tvOS 11.0, *) {
// with notch: 44.0 on iPhone X, XS, XS Max, XR.
// without notch: 20.0 on iPhone 8 on iOS 12+.
return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 20
}
return false
}()
override var intrinsicContentSize: CGSize {
let height:CGFloat = deviceHasTopNotch ? 88 : 64
let width = super.intrinsicContentSize.width //Use whatever you prefer here. Ex.UIScreen.main.bounds.size.width
return CGSize(width: width, height: height)
}
}
在情节提要中
删除自定义视图的当前高度限制。将 Intrinsic Size
属性 设置为 Placeholder
。
自定义导航栏的布局约束示例。
这里是这个问题在google驱动器中的项目:https://drive.google.com/file/d/1Js0t-stoerWy8O8uIOJl_bDw-bnWAZPr/view?usp=sharing
我使用下面的 IBDesignable 代码制作了一个自定义导航栏(下图中的红色视图)。我想,如果 iPhone 有像 iPhone X, iPhone XR 这样的顶级,那么自定义导航栏的高度是 88,否则高度是 64。我制作了一个 IBDesignable 代码我可以重用这段代码
import UIKit
@IBDesignable
class CustomParentNavigationBarView: UIView {
override func awakeFromNib() {
super.awakeFromNib()
self.setHeight()
}
override func layoutSubviews() {
super.layoutSubviews()
self.setHeight()
}
func setHeight() {
let deviceHasTopNotch = checkHasTopNotchOrNot()
layer.frame.size.height = deviceHasTopNotch ? 88 : 64
}
func checkHasTopNotchOrNot() -> Bool {
if #available(iOS 11.0, tvOS 11.0, *) {
// with notch: 44.0 on iPhone X, XS, XS Max, XR.
// without notch: 20.0 on iPhone 8 on iOS 12+.
return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 20
}
return false
}
}
我把这个CustomParentNavigationBarView
分配给红色view
然后,我贴上标签。应该正好位于红色视图下方(自定义导航栏,使用 IBDesignable)
如果我 运行 iPhone 中的应用程序没有像 iPhone8 这样的顶级应用程序,它看起来很棒
但是,如果我 运行 iPhone 中具有像 iPhone XR 这样一流的应用程序,标签现在在红色视图中,它似乎仍然遵循之前的自动布局之前 64 的红色视图高度(在情节提要中我使用 iPhone 8),因此当自定义导航栏在 iPhone XR 上 运行ning 更新为 88 时,标签仍然按照之前的64高度,就会定位到红色view里面
这里是自定义导航栏的自动布局(红色视图)
这里是标签的自动布局
如何解决这个问题?
这里的问题是您在 setHeight() 中指定了框架高度,但也在故事板中指定了布局约束的高度。解决此问题的一种方法是为您的视图指定一个 intrinsicContentSize,而不是将高度指定为情节提要中的布局约束。 (I.o.w。类似于你依赖标签宽度的方式给你计算)
@IBDesignable
class CustomParentNavigationBarView: UIView {
lazy var deviceHasTopNotch: Bool = {
if #available(iOS 11.0, tvOS 11.0, *) {
// with notch: 44.0 on iPhone X, XS, XS Max, XR.
// without notch: 20.0 on iPhone 8 on iOS 12+.
return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 20
}
return false
}()
override var intrinsicContentSize: CGSize {
let height:CGFloat = deviceHasTopNotch ? 88 : 64
let width = super.intrinsicContentSize.width //Use whatever you prefer here. Ex.UIScreen.main.bounds.size.width
return CGSize(width: width, height: height)
}
}
在情节提要中
删除自定义视图的当前高度限制。将 Intrinsic Size
属性 设置为 Placeholder
。
自定义导航栏的布局约束示例。