19

我必须在滚动的 UITextView 中更新少量文本。我只会在光标当前所在的位置插入一个字符,并且我将通过按下导航栏上的按钮来执行此操作。

我的问题是,每当我调用文本视图的 setText 方法时,它都会跳到文本的底部。我试过使用 contentOffset 并重置 selectedRange 但它不起作用!这是我的例子:

// Remember offset and selection
CGPoint contentOffset = [entryTextView contentOffset];
NSRange selectedRange = [entryTextView selectedRange];
// Update text
entryTextView.text = entryTextView.text;
// Try and reset offset and selection
[entryTextView setContentOffset:contentOffset animated:NO];
[entryTextView setSelectedRange: selectedRange];

有什么方法可以更新文本而不需要任何滚动移动……就好像他们只是在键盘上输入了一些东西一样?

编辑:

我试过使用 textViewDidChange: 委托方法,但它仍然没有向上滚动到原始位置。

- (void)textViewDidChange:(UITextView *)textView {
    if (self.programChanged) {
        [textView setSelectedRange:self.selectedRange];
        [textView setContentOffset:self.contentOffset animated:NO];
        self.programChanged = NO;
    }
}

- (void)changeButtonPressed:(id)sender {
    // Remember position
    self.programChanged = YES;
    self.contentOffset = [entryTextView contentOffset];
    self.selectedRange = [entryTextView selectedRange];
    // Update text
    entryTextView.text = entryTextView.text;
}
4

13 回答 13

16

如果您使用 iPhone 3.0 或更高版本,则可以解决此问题:

textView.scrollEnabled = NO;

//You should know where the cursor will be(if you update your text by appending/inserting/deleting you can know the selected range) so keep it in a NSRange variable.

Then update text:
textView.text = yourText;

textView.scrollEnabled = YES;
textView.selectedRange = range;//you keep before

它现在应该可以工作(不再跳跃)

问候 Meir Assayag

于 2010-05-03T11:22:41.693 回答
8

基于 Meir 的建议,这里的代码以编程方式删除选择(是的,我知道有一个选择菜单按钮也可以这样做,但我正在做一些时髦的事情)而不滚动文本视图。

NSRange selectedRange = textView.selectedRange;
textView.scrollEnabled = NO;
// I'm deleting text. Replace this line with whatever insertions/changes you want
textView.text = [textView.text
                stringByReplacingCharactersInRange:selectedRange withString:@""];
selectedRange.length = 0;
// If you're inserting text, you might want to increment selectedRange.location to be
// after the text you inserted
textView.selectedRange = selectedRange;
textView.scrollEnabled = YES;
于 2010-08-15T06:21:28.543 回答
6

此决定适用于 iOS 8:

let offset = textView.contentOffset
textView.text = newText
textView.layoutIfNeeded()
textView.setContentOffset(offset, animated: false)

必须准确调用,setContentOffset:animated:因为只有这样才能取消动画。textView.contentOffset = offset不会取消动画,也无济于事。

于 2015-01-29T15:27:59.070 回答
4

以下两种解决方案不适用于 iOS 8.0。

textView.scrollEnabled = NO;
[textView.setText: text];
textView.scrollEnabled = YES;

CGPoint offset = textView.contentOffset;
[textView.setText: text];
[textView setContentOffset:offset];

我为 textview 设置了一个委托来监视滚动事件,并注意到在我恢复偏移量的操作后,偏移量再次重置为 0。所以我改为使用主操作队列来确保我的还原操作发生在“重置为 0”选项之后。

这是适用于 iOS 8.0 的解决方案。

CGPoint offset = self.textView.contentOffset;
self.textView.attributedText = replace;
[[NSOperationQueue mainQueue] addOperationWithBlock: ^{
    [self.textView setContentOffset: offset];
}];
于 2015-01-07T04:17:23.007 回答
3

没有任何建议的解决方案对我有用。-setContentOffset:animated: 由 -setText: 触发 3 次,动画 YES 和结尾的 contentOffset(减去 UITextView 的默认 8pt 边距)。我将 -setText: 包裹在警卫中:

textView.contentOffsetAnimatedCallsDisabled = YES;
textView.text = text;
textView.contentOffsetAnimatedCallsDisabled = NO;

在 -setContentOffset:animated: 中的 UITextView 子类中

if (contentOffsetAnimatedCallsDisabled) return; // early return

在你的其他逻辑中。不要忘记超级电话。这行得通。

拉斐尔

于 2010-07-20T06:05:25.877 回答
3

为了编辑 UITextView 的文本,您需要更新它的 textStorage 字段:

[_textView.textStorage beginEditing];

NSRange replace = NSMakeRange(10, 2); //enter your editing range
[_textView.textStorage replaceCharactersInRange:replace withString:@"ha ha$ "];

//if you want to edit the attributes
NSRange attributeRange = NSMakeRange(10, 5); //enter your editing attribute range
[_textView.textStorage addAttribute:NSBackgroundColorAttributeName value:[UIColor greenColor] range:attributeRange];

[_textView.textStorage endEditing];

祝你好运

于 2015-02-08T11:11:21.250 回答
2

在 iOS 7 中。 sizeThatFits 存在错误并且在 UITextView 中有换行符,我发现可行的解决方案是通过禁用滚动来包装它。像这样:

textView.scrollEnabled = NO;
CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
textView.scrollEnabled = YES;

并且奇怪的跳跃已得到修复。

于 2014-04-25T16:05:51.497 回答
2

我在IOS9中遇到了一个类似的问题,如果不一样的话。将某些文本的特征更改为 BOLD 会导致视图将所选内容滚动到视线之外。我通过在 setSelectedRange 之后添加对 scrollRangeToVisible 的调用来对此进行排序:

    [self setSelectedRange:range];
    [self scrollRangeToVisible:range];
于 2016-06-19T08:51:14.413 回答
1

看看 UITextViewDelegate,我相信 textViewDidChangeSelection 方法可以让你做你需要的。

于 2009-05-14T16:42:21.907 回答
1

老问题,但我对 iOS 7 应用程序有同样的问题。需要在运行循环之后稍微更改 contentOffset。这是一个快速的想法。

self.clueString = [self.level clueText];
CGPoint point = self.clueText.contentOffset;
self.clueText.attributedText = self.clueString;
double delayInSeconds = 0.001; // after the run loop update
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    [self.clueText setContentOffset:point animated:NO]; 
});
于 2014-02-06T06:04:08.503 回答
1

最后试试这个,在 iOS 10 上检查

let offset = textView.contentOffset
textView.attributedText = newValue
OperationQueue.main.addOperation {
    self.textView.setContentOffset(offset, animated: false)
}
于 2017-09-02T07:56:34.313 回答
0

不是那么优雅的解决方案 - 但它很有效,所以谁在乎:

- (IBAction)changeTextProgrammaticaly{
     myTextView.text = @"Some text";
     [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(rewindOffset) userInfo:nil repeats:NO];
}

- (void)rewindOffset{
    [myTextView setContentOffset:CGPointMake(0,0) animated: NO];
}
于 2010-02-03T11:28:37.040 回答
0

我找到了一个在 iOS 6 和 7(可能还有更早的版本)中可靠运行的解决方案。在 UITextView 的子类中,执行以下操作:

@interface MyTextView ()
@property (nonatomic) BOOL needToResetScrollPosition;
@end

@implementation MyTextView

- (void)setText:(NSString *)text
{
    [super setText:text];
    self.needToResetScrollPosition = YES;
}

- (void)layoutSubviews
{
    [super layoutSubviews];

    if (self.needToResetScrollPosition) {
        self.contentOffset = CGPointMake(0, 0);
        self.needToResetScrollPosition = NO;
    }
}

其他答案在 iOS 7 中都不起作用,因为它会在显示时调整滚动偏移量。

于 2013-09-21T21:26:56.670 回答