使用NSLayoutManager方法来计算文本容器中占位符标记的位置,我将这些点转换为CGRects,然后将排除路径转换为文本字段周围的文本.这就是这样的:
func createAndAssignExclusionPathsForInputTextFields () {
var index = 0
let textFieldCount = self.textFields.count
var exclusionPaths : [UIBezierPath] = []
while index < textFieldCount {
let textField : AgreementTextField = self.textFields[index]
let location = self.calculatePositionOfPlaceholderAtIndex(index)
let size = textField.intrinsicContentSize()
textField.frame = CGRectMake(location.x,location.y,size.width,size.height)
exclusionPaths.append(textField.exclusionPath())
index = index + 1
}
self.textContainer.exclusionPaths = exclusionPaths
}
// …
func calculatePositionOfPlaceholderAtIndex(textIndex : NSInteger) -> CGPoint {
let layoutManager : NSLayoutManager = self.textContainer.layoutManager!
let delimiterRange = self.indices[textIndex]
let characterIndex = delimiterRange.location
let glyphRange = self.layoutManager.glyphRangeForCharacterRange(delimiterRange,actualCharacterRange:nil)
let glyphIndex = glyphRange.location
let rect = layoutManager.lineFragmentRectForGlyphAtIndex(glyphIndex,effectiveRange: nil,withoutAdditionalLayout: true)
let remainingRect : UnsafeMutablePointer<CGRect> = nil
let textContainerRect = self.textContainer.lineFragmentRectForProposedRect(rect,atIndex: characterIndex,writingDirection: .LeftToRight,remainingRect: remainingRect)
let position = CGPointMake(textContainerRect.origin.x,textContainerRect.origin.y)
return position
}
在这一点上,我有三个问题:
>一旦我将一个排除路径分配给了textContainer,其他占位符的计算字形位置现在都是错误的.
> calculatePositionOfPlaceholderAtIndex方法给我很好的y值,但是x值都是0.
>我还没有成功地隐藏占位符令牌.
所以,为了解决我的列表中的第一个问题,我尝试添加排除路径,然后再计算下一个,通过更改createAndAssignExclusionPathsForInputTextFields:
func createAndAssignExclusionPathsForInputTextFields () {
var index = 0
let textFieldCount = self.textFields.count
while index < textFieldCount {
let textField : AgreementTextField = self.textFields[index]
let location = self.calculatePositionOfPlaceholderAtIndex(index)
let size = textField.intrinsicContentSize()
textField.frame = CGRectMake(location.x,size.height)
self.textContainer.exclusionPaths.append(textField.exclusionPath())
index = index + 1
}
}
现在,我的计算头寸全都返回0,0不是我们想要的.添加排除路径可以理解,使计算的位置无效,但为每个rect方法获得0,0没有帮助.
在添加排除路径或隐藏字形后,如何让布局管理器重新计算屏幕上字形的位置?
编辑:每阿兰T答案,我没有运气尝试以下:
func createAndAssignExclusionPathsForInputTextFields () {
var index = 0
let textFieldCount = self.textFields.count
var exclusionPaths : [UIBezierPath] = []
while index < textFieldCount {
let textField : AgreementTextField = self.textFields[index]
let location = self.calculatePositionOfPlaceholderAtIndex(index)
let size = textField.intrinsicContentSize()
textField.frame = CGRectMake(location.x,size.height)
exclusionPaths.append(textField.exclusionPath())
self.textContainer.exclusionPaths = exclusionPaths
self.layoutManager.ensureLayoutForTextContainer(self.textContainer)
index = index + 1
}
self.textContainer.exclusionPaths = exclusionPaths
}
解决方法
在你的createAndAssignExclusionPathsForInputTextFields函数中,你按照你的self.textFields数组的顺序处理你的字段.
当您在函数末尾设置self.textContainer.exclusionPaths的值时,布局管理器将(可能)重新流动所有排除的文本,从而使您的一些计算无效,而不考虑其他的影响排除.
这样做的方法是排序你的self.textFields数组,使它们对应于文本流(他们可能已经按照这个顺序,我不能告诉).然后,您必须清除self.textContainer.exclusionPath中的所有排除项,并将它们逐一添加,以便在计算下一个排除之前,布局管理器将围绕以前添加的排除的文本重新排列. (我相信它每次设置排除次数都是这样,但如果没有,则可能需要调用layoutManager的ensureLayoutForManager函数)
您必须以文本流顺序执行此操作,以便将每个排除添加到文本区域,这些区域不会使任何先前的排除项无效.
优化这一点,以避免完全清除/重建排除也是可能的,但我建议在尝试之前达到工作基线.