首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用文本工具包插入UITextFields和UITextView?

用文本工具包插入UITextFields和UITextView?
EN

Stack Overflow用户
提问于 2015-12-15 18:18:46
回答 2查看 405关注 0票数 13

我正在开发一个用文本视图替换占位符的UITextFields。我向它传递一个包含多个占位符令牌实例的文本的对象(结构或字典)。字典还包含一个字段数组,我们希望从这些字段中收集数据。我的目标是在文本中放置UITextFields (或其他视图),并隐藏令牌。

使用NSLayoutManager方法计算占位符标记在文本容器中的位置,将这些点转换为CGRects,然后将路径排除到文本字段中。如下所示:

代码语言:javascript
复制
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
}

// ...

代码语言:javascript
复制
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
}

在这一点上,我有三个问题:

  1. 一旦我为textContainer分配了排除路径,其他占位符计算出来的字形位置现在都是错误的。
  2. calculatePositionOfPlaceholderAtIndex方法给出了相当好的y值,但x值都是0。
  3. 我未能成功地隐藏占位符标记。

因此,为了解决列表中的第一个问题,我尝试在计算下一个路径之前添加排除路径,方法是更改createAndAssignExclusionPathsForInputTextFields

代码语言:javascript
复制
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是没有帮助的。

在添加排除路径或隐藏字形后,如何要求布局管理器重新计算屏幕上的象形文字的位置?

编辑: Per的答案,我尝试了以下几点,但没有结果:

代码语言:javascript
复制
    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
}
EN

回答 2

Stack Overflow用户

发布于 2016-01-16 04:50:39

我只能提出一些建议,因为我是TextKit的新手,但是在您的代码中有些东西盯着我,我想我应该提出来,以防有帮助。

在函数中,您将按照self.textFields数组的顺序处理字段。

当您在函数的末尾设置self.textContainer.exclusionPaths的值时,布局管理器将(可能)围绕所有的排除重新流文本,从而使您执行的一些计算无效,而不考虑其他排除的影响。

方法是对您的self.textFields数组进行排序,以便它们对应于文本流(我不知道它们可能已经按照这个顺序排列)。然后,您必须清除self.textContainer.exclusionPaths中的所有排除,并将它们逐一添加回来,这样,在计算下一个排除之前,布局管理器已经将前面添加的排它周围的文本重新填充了。(我相信每次设置排除时都会这样做,但如果没有,则可能需要调用layoutManager的ensureLayoutForManager函数)

您必须按照文本流顺序执行此操作,以便在文本区域中添加每个排除项,这样就不会使以前的排除无效。

对此进行优化以避免完全明确/重新构建排除也是可能的,但我建议在尝试之前达到一个工作基线。

票数 2
EN

Stack Overflow用户

发布于 2016-01-21 03:31:53

也许您应该使用ensureGlyphsForCharacterRange而不是ensureLayoutForManager。我需要构建一个更全面的测试程序来确定这一点(我现在没有足够的空闲时间)。

但是,我确实考虑了在UITextView中使用可编辑字段和不可编辑文本的另一种方法,并提出了一种仅文本方法(粗糙和不完整,但这是一个起点)。

这样做的目的是使用一些文本属性来标识可编辑字段,并使用UITextView的委托使其他所有内容都不可编辑。

代码语言:javascript
复制
// function to determine if attributes of a range of text allow editing
// (you decide which attributes correspond to editable text)
func editableText(attributes:[String:AnyObject]) -> Bool
{
   if let textColor = attributes[NSForegroundColorAttributeName] as? UIColor
           where textColor == UIColor.redColor() // example: red text is editable
   { return true }
   return false
}

// UITextViewDelegate's function to allow editing a specific text area (range)
func textView(textView: UITextView, var shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool
{
   // 0 length selection is an insertion point
   // will get the attibutes of the text preceding it as typing attributes
   if range.length == 0 
   && text != ""
   && editableText(textView.typingAttributes) 
   { return true }

   // in case we're on an insertion point at the very begining of an editable field
   // lets look at the next character
   range.length = max(1, range.length)

   // for non-zero ranges, all subranges must have the editable attributes to allow editing
   // (also setting typingAttributes to cover the insertion point at begining of field case)
   var canEdit = true
   textView.attributedText.enumerateAttributesInRange(range, options:[])
   { 
     if self.editableText($0.0) 
     { textView.typingAttributes = $0.0 }
     else
     { canEdit = false }          
   }       
   return canEdit      
}

这就需要管理更多的事情,例如字段之间的选项卡、初始游标位置以及格式化文本条目的一些游标行为,但它们看起来都很简单。

如果您没有走太远的排除路径,并且您的需求不受约束,那么这可能有助于清除障碍。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34296583

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档