【发布时间】:2015-12-15 18:18:46
【问题描述】:
我正在开发一个text view,它用 UITextFields 替换占位符。我将一个对象(结构或字典)传递给它,其中的文本包含占位符标记的多个实例。字典还包含我们要从中收集数据的字段数组。我的目标是在整个文本中放置 UITextFields(或其他视图),并隐藏标记。
使用 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, location.y, size.width, size.height)
self.textContainer.exclusionPaths.append(textField.exclusionPath())
index = index + 1
}
}
现在,我计算的位置都返回 0、0。这不是我们想要的。可以理解,添加排除路径会使计算的位置无效,但是为每个 rect 方法返回 0、0 并没有帮助。
添加排除路径或隐藏字形后,如何让布局管理器重新计算字形在屏幕上的位置?
编辑:根据 Alain 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, location.y, size.width, size.height)
exclusionPaths.append(textField.exclusionPath())
self.textContainer.exclusionPaths = exclusionPaths
self.layoutManager.ensureLayoutForTextContainer(self.textContainer)
index = index + 1
}
self.textContainer.exclusionPaths = exclusionPaths
}
【问题讨论】:
-
我还没弄明白。相反,我实现了 UITextField 的一个子类,它做类似的事情。
-
你能连接一个示例 xcode 项目并分享它吗?我想试试这个。
-
我目前没有示例项目,但我会看看能不能做一个。
-
@ShahiM,新的 AgreementView 在这里:gist.github.com/MosheBerman/1a990d15863737047968
-
@ShahiM 问题中描述的类的全部内容:gist.github.com/MosheBerman/d65408b75dc28a7046e0
标签: ios layout uitextview textkit