我必须在滚动的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:delegate方法,但它仍然没有滚动到原始位置。
- (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;
}
答案 0 :(得分:14)
如果使用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
答案 1 :(得分: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;
答案 2 :(得分:6)
此决定适用于iOS 8:
let offset = textView.contentOffset
textView.text = newText
textView.layoutIfNeeded()
textView.setContentOffset(offset, animated: false)
必须准确调用setContentOffset:animated:
因为只有这会取消动画。 textView.contentOffset = offset
不会取消动画,也不会有帮助。
答案 3 :(得分: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];
}];
答案 4 :(得分:3)
没有建议的解决方案适合我。 -setContentOffset:animated:由-setText触发:带动画YES的3次和end的contentOffset(减去UITextView的默认8pt边距)。我把-setText:包装成一个警卫:
textView.contentOffsetAnimatedCallsDisabled = YES;
textView.text = text;
textView.contentOffsetAnimatedCallsDisabled = NO;
在-setContentOffset的UITextView子类中:animated:put
if (contentOffsetAnimatedCallsDisabled) return; // early return
在你的其他逻辑中。不要忘记超级电话。这很有效。
圣拉斐尔
答案 5 :(得分: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];
祝你好运
答案 6 :(得分:2)
在iOS 7中。接口是sizeThatFits的错误,并且在UITextView中有换行符我找到的解决方案是通过禁用滚动来包装它。像这样:
textView.scrollEnabled = NO;
CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
textView.scrollEnabled = YES;
奇怪的跳跃已被修复。
答案 7 :(得分:1)
看看UITextViewDelegate,我相信textViewDidChangeSelection方法可以让你做你需要的。
答案 8 :(得分: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];
});
答案 9 :(得分:1)
我在IOS9中遇到了类似的问题,如果不是相同的话。将某些文本的特征更改为BOLD会导致视图将选择滚动到视线之外。我通过在setSelectedRange:
之后添加对scrollRangeToVisible的调用来对此进行排序 [self setSelectedRange:range];
[self scrollRangeToVisible:range];
答案 10 :(得分:1)
最后试试这个,在iOS 10上查看
let offset = textView.contentOffset
textView.attributedText = newValue
OperationQueue.main.addOperation {
self.textView.setContentOffset(offset, animated: false)
}
答案 11 :(得分: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];
}
答案 12 :(得分: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,因为它会在显示时调整滚动偏移。