如何创建定义基线的自定义UIView?

如何创建定义基线的自定义UIView?,uiview,autolayout,Uiview,Autolayout,使用NSLayoutConstraint类,可以创建基于视图基线的约束(NSLayoutAttributeBaseline)。但是,我没有看到任何文档描述UIView如何实际为自动布局系统提供基线值 如果我想创建一个自定义的定义基线的UIView子类,我该怎么做NSView定义了一个baselineOffsetFromBottom方法,我假设它在OS X上以某种方式涉及,但在iOS中如何工作?来自UIView文档: viewForBaselineLayout 返回用于满足基线约束的视图 -(UI

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

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

来自UIView文档:

viewForBaselineLayout

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

-(UIView*)视图用于基线布局

返回值

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


我刚刚使用Hopper反汇编程序查看了iOS 8.1中的UILabel,它实现了方法
\u baselineOffsetFromBottom
\u firstBaselineOffsetFromTop
,这两种方法依次由
-[UIView nsli\u lowerAttribute:intoExpression:with coefficient:forConstraint
调用,因此UIKit有类似于osx的私有方法,它们只是不向公众公开

\u baselineOffsetFromBottom
\u firstBaselineOffsetFromTop
由UIView(返回0)、UILabel和UITextView实现。还有一个名为
\u UIGlintyStringView
的类,它实现了
\u baselineOffsetFromBottom
;没有其他UIKit类具有这些方法

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

__UITagLayoutConstraintsForConstantChangeForSelectedAttributes(self, __UILayoutAttributeIsBaselineAttribute)

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

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

override var firstBaselineOffsetFromTop: CGFloat {
    return bounds.midY
}
编辑:我的错,那是MacOS。我相信iOS的等价物是
firstBaselineAnchor
,它返回一个
NSLayoutYAxisAnchor
对象。我还没有测试过,但我预计这会产生类似的效果:

override var firstBaselineAnchor: NSLayoutYAxisAnchor {
    return NSLayoutYAxisAnchor.anchorWithOffset(bounds.midY)
}
已弃用,因此您必须使用

viewForFirstBaselineLayout
范例

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

这是一个伟大的发现。不幸的是,这些方法并不公开。也许我会提交一个功能请求,让它们公开。这可能会奏效。我记得,当我最初提出这个问题时,锚点并不存在。是的,在2015年末的iOS9中引入了锚点。不幸的是,似乎没有任何方法可以创建任意的NSLayoutYAxisAnchor,无论是基于偏移量还是其他什么。上面的示例iOS代码无法编译。似乎在iOS上,我们在这里返回一个现有的主播是很糟糕的。是的,这似乎是一个真正的疏忽。有趣的是,我确信我在以前的操作系统版本中管理了它。
- (UIView *)viewForFirstBaselineLayout  {
    // Use subLabel view for handling baseline layouts
    return self.subLabel;
}