【问题标题】:How to get the cursor in an UITextView to reflect an updated typingAttributes for paragraph alignment?如何在 UITextView 中获取光标以反映段落对齐的更新类型属性?
【发布时间】:2014-04-29 02:23:25
【问题描述】:

我正在使用 UITextView 输入一些富文本。我创建了一个按钮来更改段落对齐方式(左、中、右)。

当用户选择一些文本并按预期工作时,我将对齐应用到属性文本。

但是,当用户点击返回并处于一个新的零长度段落中时(就在换行符之后并且没有任何内容),我相信我应该更改 typingAttributes 以反映我希望新文本接收的属性。

我使用了以下代码:

if ((paragraphRange.length == 0) && (paragraphRange.location == [mutableText length])) {

    NSMutableParagraphStyle * mutableParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];

    [mutableParagraphStyle setAlignment:textAlignment];
    [mutableParagraphStyle setLineBreakMode:NSLineBreakByWordWrapping];

    NSMutableDictionary * attributes = [self.typingAttributes mutableCopy];
    [attributes setObject:mutableParagraphStyle forKey:NSParagraphStyleAttributeName];
    self.typingAttributes = attributes;

它确实应用了段落对齐一次字符被键入,但 UITextView 中的光标直到字符被键入后才会反映更改。我正在寻找一种在输入文本之前将光标置于正确位置的机制。例如,如果用户选择“居中”,我希望光标移动到视图的中心以显示文本的位置。

有人对如何做到这一点有任何想法吗?

提前致谢,

查理

【问题讨论】:

    标签: ios uitextview nsattributedstring text-alignment


    【解决方案1】:

    对于那些跟踪此问题的人来说,这似乎是 iOS7 中的一个错误。渲染器在计算光标位置时似乎没有考虑 typingAttributes 段落对齐的状态。

    看起来这个需要向 Apple 报告错误 ;-)

    【讨论】:

    • 按照 Chen Lim 所指出的,使用 [textView setNeedsLayout] 来缓解问题。
    【解决方案2】:

    这是我的做法,这会导致光标立即移动。我认为关键是在整个段落上设置属性。似乎确实存在一个错误,有时光标不会移动,但如果您滚动文本视图,则会导致它移动。似乎只出现在 uitextview 顶部附近(第 1 - 5 行),并且如果两种样式使用相同的字体大小。

    如果您选择文本并将其更改为粗体或从粗体更改,则会出现类似的错误,所选区域的大小未调整以反映更改文本的新宽度。此外,如果您以编程方式将段落的字体更改为粗体,则光标位置不会更新以适应更改后的文本宽度。但是,如果您还更改了文本点大小,则光标会正确地重新定位以适应下一个文本宽度。

    /*! Applies the Normal style to the range returned by [self rangeForUserParagraphAttributeChange]
    
        @param sender The id of the control sending the message.
     */
    - (IBAction) styleNormal:(id)sender
    {
        FLOG(@"styleNormal called");
        NSRange charRange = [self rangeForUserParagraphAttributeChange];
        if (charRange.location == NSNotFound) return;
        NSTextStorage *myTextStorage = [self textStorage];
    
        if ([self isEditable] && charRange.location != NSNotFound)
        {
            [myTextStorage beginEditing];
            [myTextStorage setAttributes:[self normalStyle] range:charRange];
            [myTextStorage endEditing];
        }
        [self setTypingAttributes:[self normalStyle]];
    }
    - (NSRange)rangeForUserParagraphAttributeChange {
        NSRange paragaphRange = [self.textStorage.string paragraphRangeForRange: self.selectedRange];
        return paragaphRange;
    }
    

    【讨论】:

    • 这并不能真正回答我的问题。我正在查看用户选择文本输入结尾(或文本字段中还没有文本)的情况。如果使用 setAttributes 应用,这将创建一个会导致异常的范围。也许你的函数'rangeForUserParagraphAttributeChange'在输入结束时返回不同的东西(NSNotFound)。但如果是这样的话,那么这段代码就不会根据代码中间的条件返回做任何事情。
    • 当我有一个段落要应用该属性时,我会确保我使用整个段落并且该部分有效。当我没有段落可以应用更改时,我就有问题了。设置 typingAttributes 似乎不会导致光标移动,但输入的下一个字符确实获得了正确的位置(在输入字符时导致光标跳转)。
    • @Charlie,抱歉,刚刚为您添加了该方法。
    • 您能否确认光标移动到您在输入结束时拥有它的视图中间(未选择任何内容)并将段落对齐方式更改为“居中”?我已使用您的代码尝试解决此问题,但在我输入下一个字符之前它什么也不做。我走到段落的末尾,点击返回进入一个没有任何内容的新段落,然后点击“中心”按钮。光标停留在视图的左侧。键入一个空格,光标会跳到视图的中间(加一个空格)。添加 [myTextStorage endEditing] 对我没有任何影响。
    • 是的@Charlie,如果 textView 为空,它会起作用 - 选择全部并删除,因此视图为空,然后设置样式。在尚未输入文本的新段落的开头按回车键。将光标移动到段落中的最后一个字符。正如我所说,似乎确实存在错误,因此请尝试输入几行空行(例如 5 或 6),然后再试一次 - 我发现光标在前几行中的位置不正确,但在下面似乎可以正常工作。
    【解决方案3】:

    您是否尝试将 textView 作为第一响应者,然后立即使其成为第一响应者。

    [textView resignFirstResponder];
    [textView becomeFirstResponder];
    

    【讨论】:

    • 对我有用,好主意!
    【解决方案4】:

    调用 [textView setNeedsLayout] 似乎可以修复光标位置。

    【讨论】:

    • 谢谢 - 似乎更改 UITextView 的某些方面已正确反映,但理由不是其中之一,并且需要 setNeedsLayout!解决了我的问题 +1
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 2019-01-17
    相关资源
    最近更新 更多