【问题标题】:Storyboard Set Width / Height for Custom View in Autolayout Similar to UILabel故事板在自动布局中为自定义视图设置宽度/高度,类似于 UILabel
【发布时间】:2019-06-20 19:51:28
【问题描述】:

标签在 iOS autolayout 中非常方便,因为它们不需要 constraints 来确定大小,它们只需要 X 和 Y 位置。对于静态文本,这很棒。

我有一个自定义视图,我想为自动布局提供一个默认大小,类似于UILabels。这可能吗?我熟悉IBInspectableIBDesignable,但我不知道如何实现这一点。我在storyboards 中使用autolayout,但我想该解决方案适用于storyboards + 编程。

我知道我可以只设置heightwidth,但这是可以在任何地方使用的视图,所以最好有width / height 动态。

【问题讨论】:

    标签: ios swift xcode autolayout storyboard


    【解决方案1】:

    不幸的是,在不指定其大小值(即widthheight)的情况下,添加UIView 并没有流畅的方法。

    说到自动布局,你有两个选项,可能你也已经知道了。 1)你应该设置UIView's的大小值,或者2.你设置其他UI对象的大小,以便自动布局可以理解UIView的大小。

    以编程方式来说,在创建UIView 对象时,如果您不提供框架,则不会显示。虽然这可能是一个可以放置在任何大小的任何点的解决方案,但当您使用 xib 或情节提要时,它可能并不理想,因为这些接口上存在差距,这也可能会混淆开发。

    我的想法包括同时使用intrinsicContentSizeIBDesignable。为此,我做了一个小演示,您可以在下面找到此代码。我将分享2个例子,一个继承自UILabel,另一个继承自UIView,以便我更容易地展示intrinsicContentSize的用法。

    下面是UIView 一个。

    import UIKit
    
    @IBDesignable class UIDemoView: UIView {
    
        func setup() {
            layer.cornerRadius = frame.height / 5
            clipsToBounds = true
        }    
    
        override func awakeFromNib() {
            super.awakeFromNib()
            self.setup()
        }
    
        override func layoutSubviews() {
            super.layoutSubviews()
            self.setup()
        }
    
        override func prepareForInterfaceBuilder() {
            super.prepareForInterfaceBuilder()
            self.setup()
        }
    
        override var intrinsicContentSize: CGSize {
            let newWidth = 100
            let newHeight = 100
            let newSize = CGSize(width: newWidth, height: newHeight)
            return newSize
        }
    }
    

    下面是 UILabel 一个。

    import UIKit
    
    @IBDesignable class UIDemoLabel: UILabel {
    
        func setup() {
            layer.cornerRadius = frame.height / 2
            clipsToBounds = true
            textAlignment = .center
        }
    
        override func awakeFromNib() {
            super.awakeFromNib()
            self.setup()
        }
    
        override func layoutSubviews() {
            super.layoutSubviews()
            self.setup()
        }
    
        override func prepareForInterfaceBuilder() {
            super.prepareForInterfaceBuilder()
            self.setup()
        }
    
        override var intrinsicContentSize: CGSize {
            let superSize = super.intrinsicContentSize
            let newWidth = superSize.width + superSize.height
            let newHeight = superSize.height
            let newSize = CGSize(width: newWidth, height: newHeight)
            return newSize
        }
    }
    

    这是自动布局的输出

    我故意展示了这两个对象的约束,所以你可以检查我是否理解正确。它们都只有 2 个约束:顶部对齐和居中对齐。

    UILabels 有自己的intrinsicContentSize,所以在覆盖它们时,我们可能会使用他们已经给出的intrinsicContentSize 作为参考,作为我们想做的任何事情的指导。 UIViews intrinsicContentSize 没有设置,因此我们必须找到一种方法来给它们特定的大小。不确定,我猜测UILabelintrinsicContentSize 的实现,逻辑很可能与文本的大小有关。您可以像上面的代码一样简单地传递常量,或者您可以使用任何自定义逻辑来提供CGFloats

    只是我的一个想法:尽管我提供了这个解决方案,但我不是IBDesignables 的粉丝。从我的角度来看,他们减慢了开发速度,因为它有缺陷。因此,老实说,我宁愿 1. 将 UIView 对象放在 xibs 和 storyboards 上,2. 将其类从 UIView 更改为自定义 UIView 类,3. 设置其约束,4. 设置以编程方式从其IBOutlet 中获取剩余属性。这更像是一种传统的方式,虽然:)

    希望对您有所帮助!

    【讨论】:

    • 感谢您的详细解答!是的,我同意 IBDesignables 不值得任何潜在的好处,因为它们很慢。
    【解决方案2】:

    你可以覆盖

    var intrinsicContentSize: CGSize { get }
    

    UIView 的属性,并根据其内容计算并返回视图的高度和宽度。

    参考:intrinsicContentSize

    【讨论】:

    • 这看起来正是我想要的。但是当我在我的视图上设置这个属性时,Xcode 仍然会在情节提要中抛出一个错误,即视图需要一个高度和宽度。我尝试让课程@IBDesignable,但没有运气
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-01
    • 2018-09-11
    • 2016-03-09
    相关资源
    最近更新 更多