使用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函数)
您必须以文本流顺序执行此操作,以便将每个排除添加到文本区域,这些区域不会使任何先前的排除项无效.
优化这一点,以避免完全清除/重建排除也是可能的,但我建议在尝试之前达到工作基线.