以编程方式设置文本时阻止 UITextView 跳转
我必须更新滚动 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;
}
I have to update a small amount of text in a scrolling UITextView. I'll only be inserting a character where the cursor currently is, and I'll be doing this on a press of a button on my navigation bar.
My problem is that whenever I call the setText method of the text view, it jumps to the bottom of the text. I've tried using contentOffset and resetting the selectedRange but it doesn't work! Here's my example:
// 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];
Is there any way you can update the text without any scroll movement at all... as if they'd just typed something on the keyboard?
Edit:
I've tried using the textViewDidChange: delegate method but it's still not scrolling up to the original location.
- (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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
以下两种解决方案在 iOS 8.0 上不适用于我。
我
设置了一个委托给textview来监视滚动事件,并注意到在我执行恢复偏移量的操作后,偏移量再次重置为0。 因此,我改为使用主操作队列来确保我的恢复操作在“重置为 0”选项之后发生。
这是我的适用于 iOS 8.0 的解决方案。
The following two solutions don't work for me on iOS 8.0.
and
I setup a delegate to the textview to monitor the scroll event, and noticed that after my operation to restore the offset, the offset is reset to 0 again. So I instead use the main operation queue to make sure my restore operation happens after the "reset to 0" option.
Here's my solution that works for iOS 8.0.
为了编辑 UITextView 的文本,您需要更新它的 textStorage 字段:
祝你好运
In order to edit the text of a UITextView, you need to update it's textStorage field:
Good luck
建议的解决方案都不适合我。 -setContentOffset:animated: 由 -setText: 触发 3 次,并带有动画 YES 和结束的 contentOffset(减去 UITextView 的默认 8pt 边距)。 我将 -setText: 包装在guard:
中的 UITextView 子类中 -setContentOffset:animated: 放在
其他逻辑中。 不要忘记超级电话。 这有效。
拉斐尔
No of the suggested solutions worked for me. -setContentOffset:animated: gets triggered by -setText: 3 times with animated YES and a contentOffset of the end (minus the default 8pt margin of a UITextView). I wrapped the -setText: in a guard:
In a UITextView subclass in -setContentOffset:animated: put
among your other logic. Don’t forget the super call. This works.
Raphael
在 iOS 7 中。在 UITextView 中存在 sizeThatFits 和换行符的错误,我发现有效的解决方案是通过禁用滚动来包装它。 像这样:
奇怪的跳跃已被修复。
in iOS 7. There seams to be a bug with sizeThatFits and having linebreaks in your UITextView the solution I found that works is to wrap it by disabling scrolling. Like this:
and weird jumping has been fixed.
我在 IOS9 中遇到了类似(如果不是相同)的问题。 将某些文本的特征更改为粗体会导致视图将所选内容滚动到视线之外。 我通过在setSelectedRange之后添加对scrollRangeToVisible的调用来对此进行排序:
I hit a a similar, if not the same, problem in IOS9. Changing the characteristics of some text to, say, BOLD caused the view to scroll the selection out of sight. I sorted this by adding a call to scrollRangeToVisible after the setSelectedRange:
看看 UITextViewDelegate,我相信 textViewDidChangeSelection 方法可以让您做您需要的事情。
Take a look at the UITextViewDelegate, I believe the textViewDidChangeSelection method may allow you to do what you need.
老问题,但我对 iOS 7 应用程序也有同样的问题。 需要在运行循环后稍微更改 contentOffset。 这是一个快速的想法。
Old question but I had the same issue with iOS 7 app. Requires changing the contentOffset a little bit after the run loop. Here is a quick idea.
最后试试这个,在 iOS 10 上检查过
Finally try this, checked on iOS 10
不是那么优雅的解决方案 - 但它有效,所以谁在乎:
Not so elegant solution- but it works so who cares:
我找到了一个在 iOS 6 和 7(可能还有更早版本)中可靠工作的解决方案。 在 UITextView 的子类中,执行以下操作:
其他答案在 iOS 7 中均不起作用,因为它将在显示时调整滚动偏移。
I found a solution that works reliably in iOS 6 and 7 (and probably earlier versions). In a subclass of UITextView, do the following:
None of the other answers work in iOS 7 because it will adjust the scroll offsets at display time.
如果您使用iPhone 3.0或更高版本,您可以解决这个问题:
现在应该可以工作了(不再跳跃)
问候
梅厄·阿萨亚格
If you use iPhone 3.0 or later, you can solve this problem:
It should work now (no more jumping)
Regards
Meir Assayag
根据梅尔的建议,这里的代码以编程方式删除选择(是的,我知道有一个选择菜单按钮也可以这样做,但我正在做一些有点时髦的事情),而无需滚动文本视图。
Building on Meir's suggestion, here's code that removes the selection programmatically (yes I know there's a selection menu button that does it too, but I'm doing something a bit funky) without scrolling the text view.
此决定适用于 iOS 8:
有必要准确调用
setContentOffset:animated:
因为只有这样才会取消动画。textView.contentOffset = offset
不会取消动画,也没有帮助。This decision works for iOS 8:
It is necessary to call exactly
setContentOffset:animated:
because only this will cancel animation.textView.contentOffset = offset
will not cancel the animation and will not help.