【问题标题】:How to create a custom UIView that defines a baseline?如何创建定义基线的自定义 UIView?
【发布时间】:2013-05-06 20:48:42
【问题描述】:

使用NSLayoutConstraint 类,可以创建基于视图基线(NSLayoutAttributeBaseline)的约束。但是,我还没有看到任何描述 UIView 实际如何为自动布局系统提供基线值的文档。

如果我想创建一个定义基线的自定义UIView 子类,我该怎么做? NSView 定义了一个 baselineOffsetFromBottom 方法,我认为它在 OS X 上以某种方式涉及,但它在 iOS 中如何工作?

【问题讨论】:

    标签: uiview autolayout


    【解决方案1】:

    来自 UIView 文档:

    viewForBaselineLayout

    返回用于满足基线约束的视图。

    - (UIView *)viewForBaselineLayout

    返回值

    约束系统用于满足基线约束的视图

    【讨论】:

      【解决方案2】:

      我刚刚使用 Hopper 反汇编器查看了 iOS 8.1 中的 UILabel,它实现了方法 _baselineOffsetFromBottom_firstBaselineOffsetFromTop,而这两个方法又被 -[UIView nsli_lowerAttribute:intoExpression:withCoefficient:forConstraint:] 调用,因此 UIKit 具有类似于一个 OS 的私有方法X 有,只是没有公开。

      _baselineOffsetFromBottom_firstBaselineOffsetFromTop由UIView(返回0)、UILabel和UITextView实现。还有一个名为_UIGlintyStringView 的类实现了_baselineOffsetFromBottom;没有其他 UIKit 类有这些方法。

      顺便说一句,当视图的基线发生变化时,它会执行以下操作:

      __UITagLayoutConstraintsForConstantChangeForSelectedAttributes(self, __UILayoutAttributeIsBaselineAttribute)
      

      似乎没有什么特别的东西不能暴露给公众;也许他们觉得没有必要或不想阻止人们编写自己的标签。 UILabel 是一个相当复杂的类,涉及自定义 CoreAnimation 层 (_UILabelLayer) 和一大堆技巧,包括相当多的可访问性支持代码。

      【讨论】:

      • 这是一个很棒的发现。不幸的是,这些方法不公开。也许我会提交一个功能请求来公开它们。
      【解决方案3】:

      如果不方便与视图对齐,您还可以覆盖其中一个基线值,即firstBaselineOffsetFromTop。例如,下面的代码将第一个基线设置为视图的中间:

      override var firstBaselineOffsetFromTop: CGFloat {
          return bounds.midY
      }
      

      编辑:我的错,那是 MacOS。我相信 iOS 等价物是 firstBaselineAnchor,它返回一个 NSLayoutYAxisAnchor 对象。我没有对此进行测试,但我希望这会产生类似的效果:

      override var firstBaselineAnchor: NSLayoutYAxisAnchor {
          return NSLayoutYAxisAnchor.anchorWithOffset(bounds.midY)
      }
      

      【讨论】:

      • 这可能行得通。我记得,当我最初提出这个问题时,锚并不存在。
      • 是的,在 iOS9 中引入,是 2015 年末。
      • 不幸的是,似乎没有任何方法可以创建任意的 NSLayoutYAxisAnchor,无论是基于偏移量还是其他任何东西。上面的示例 iOS 代码无法编译。似乎在 iOS 上,我们在这里返回一个现有的锚很糟糕。
      • 是的,这似乎是一个真正的疏忽。有趣的是,我确定我在以前的操作系统版本中管理过它。
      【解决方案4】:
      viewForBaselineLayout 
      

      已弃用,因此您必须使用

      viewForFirstBaselineLayout
      

      例子

      - (UIView *)viewForFirstBaselineLayout  {
          // Use subLabel view for handling baseline layouts
          return self.subLabel;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-03
        相关资源
        最近更新 更多