Iphone 如何在每次更改文本时强制UITextView滚动到顶部?

Iphone 如何在每次更改文本时强制UITextView滚动到顶部?,iphone,ios,uitextview,Iphone,Ios,Uitextview,好的,我对UITextView有一些问题。问题是: 我向UITextView添加了一些文本。然后用户双击以选择某个内容。 然后我更改UITextView中的文本(编程方式如上所述),并且UITextView滚动到页面底部有光标的位置 但是,这不是用户单击的位置。它总是滚动到UITextView的底部,无论用户单击的位置如何 因此,我的问题是:如何在每次更改文本时强制UITextView滚动到顶部?我尝试了contentOffset和scrollRangeToVisible。两者都不起作用 如果您

好的,我对
UITextView
有一些问题。问题是:

我向
UITextView
添加了一些文本。然后用户双击以选择某个内容。 然后我更改
UITextView
中的文本(编程方式如上所述),并且
UITextView
滚动到页面底部有光标的位置

但是,这不是用户单击的位置。它总是滚动到
UITextView
的底部,无论用户单击的位置如何

因此,我的问题是:如何在每次更改文本时强制
UITextView
滚动到顶部?我尝试了
contentOffset
scrollRangeToVisible
。两者都不起作用


如果您有任何建议,我们将不胜感激。

请尝试将光标移至文本顶部

NSRange r  = {0,0};
[yourTextView setSelectedRange:r];

看看情况如何。确保在所有事件触发后或您正在做的任何事情完成后调用此按钮。

我不确定是否理解您的问题,但您是否只是尝试将视图滚动到顶部?如果是这样,你应该这样做


[textview scrollRectToVisible:CGRectMake(0,0,1,1)动画:是];

UITextView*注;
[注意setContentOffset:CGPointZero动画:是];
这是为我做的

Swift版本(在Xcode 9.3上安装iOS 11的Swift 4.1):

note.setContentOffset(.0,动画:true)

这行代码适合我

我在HTML中使用attributedString,文本视图不可编辑。设置内容偏移量对我也不起作用。这对我有效:禁用滚动启用,设置文本,然后再次启用滚动

[yourTextView setScrollEnabled:NO];
yourTextView.text = yourtext;
[yourTextView setScrollEnabled:YES];
override func viewWillAppear(animated: Bool) {
    dispatch_async(dispatch_get_main_queue(), {
        let desiredOffset = CGPoint(x: 0, y: -self.textView.contentInset.top)
        self.textView.setContentOffset(desiredOffset, animated: false)
    })
}

如果有人在iOS 8中遇到这个问题,我发现只需设置
UITextView的
text属性,然后使用
NSRange调用
scrollRangeToVisible
,使用
location:0
length:0
,就可以了。我的文本视图不可编辑,我测试了可选和不可选(两种设置都不影响结果)。下面是一个快速的例子:

myTextView.text = "Text that is long enough to scroll"
myTextView.scrollRangeToVisible(NSRange(location:0, length:0))

结合前面的答案,现在应该可以了:

talePageText.scrollEnabled = false
talePageText.textColor = UIColor.blackColor()
talePageText.font = UIFont(name: "Bradley Hand", size: 24.0)
talePageText.contentOffset = CGPointZero
talePageText.scrollRangeToVisible(NSRange(location:0, length:0))
talePageText.scrollEnabled = true
召唤

scrollRangeToVisible(NSMakeRange(0, 0))
工作,但打电话进来

override func viewDidAppear(animated: Bool)

这是我的解决方案

    override func viewDidLoad() {
        textView.scrollEnabled = false
        textView.text = "your text"
    }

    override func viewDidAppear(animated: Bool) {
        textView.scrollEnabled = true
    }

这就是它在iOS 9发行版上的工作原理 因此,在出现在屏幕上之前,文本视图在顶部滚动

- (void)viewDidLoad
{
    [super viewDidLoad];
    textView.scrollEnabled = NO;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    textView.scrollEnabled = YES;
}

我有一个更新的答案,这将有文本视图显示正确,没有用户体验到一个滚动动画

override func viewWillAppear(animated: Bool) {
    dispatch_async(dispatch_get_main_queue(), {
        self.introductionText.scrollRangeToVisible(NSMakeRange(0, 0))
    })

对于我来说,fine works的代码如下:

    textView.attributedText = newText //or textView.text = ...

    //this part of code scrolls to top
    textView.contentOffset.y = -64
    textView.scrollEnabled = false
    textView.layoutIfNeeded() //if don't work, try to delete this line
    textView.scrollEnabled = true
    var scrollToLocation = 50 //<needed position>
    textView.contentOffset.y = textView.contentSize.height
    textView.scrollRangeToVisible(NSRange.init(location: scrollToLocation, length: 1))
要滚动到精确位置并在屏幕顶部显示,我使用以下代码:

    textView.attributedText = newText //or textView.text = ...

    //this part of code scrolls to top
    textView.contentOffset.y = -64
    textView.scrollEnabled = false
    textView.layoutIfNeeded() //if don't work, try to delete this line
    textView.scrollEnabled = true
    var scrollToLocation = 50 //<needed position>
    textView.contentOffset.y = textView.contentSize.height
    textView.scrollRangeToVisible(NSRange.init(location: scrollToLocation, length: 1))
var scrollToLocation=50//
textView.contentOffset.y=textView.contentSize.height
textView.scrollRangeToVisible(NSRange.init(位置:scrollToLocation,长度:1))

设置contentOffset.y会滚动到文本的末尾,然后scrollRangeToVisible会滚动到scrollToLocation的值。因此,所需的位置出现在scrollView的第一行。

这对我很有用。它基于RyanTCBs答案,但它是同一解决方案的Objective-C变体:

- (void) viewWillAppear:(BOOL)animated {
    // For some reason the text view, which is a scroll view, did scroll to the end of the text which seems to hide the imprint etc at the beginning of the text.
    // On some devices it is not obvious that there is more text when the user scrolls up.
    // Therefore we need to scroll textView to the top.
    [self.textView scrollRangeToVisible:NSMakeRange(0, 0)];
}

由于这些解决方案对我都不起作用,而且我浪费了太多时间拼凑解决方案,这最终解决了我的问题

override func viewWillAppear(animated: Bool) {
    dispatch_async(dispatch_get_main_queue(), {
        let desiredOffset = CGPoint(x: 0, y: -self.textView.contentInset.top)
        self.textView.setContentOffset(desiredOffset, animated: false)
    })
}
这真的很愚蠢,因为这不是此控件的默认行为

我希望这对其他人有所帮助。

Swift 2回答:

textView.scrollEnabled = false

/* Set the content of your textView here */

textView.scrollEnabled = true

这将防止文本视图在设置后滚动到文本的末尾。

对于我来说,在iOS 9中,它停止使用属性字符串,方法为scrollRangeToVisible(第一行使用粗体字体,其他行使用常规字体)

-(void)viewWillLayoutSubviews{
    [super viewWillLayoutSubviews];

    [textview setContentOffset:CGPointZero animated:NO];
}
所以我不得不使用:

textViewMain.attributedText = attributedString
textViewMain.scrollRangeToVisible(NSRange(location:0, length:0))
delay(0.0, closure: { 
                self.textViewMain.scrollRectToVisible(CGRectMake(0, 0, 10, 10), animated: false)
            })
如果延迟是:

func delay(delay:Double, closure:()->Void) {
    dispatch_after(
        dispatch_time(
            DISPATCH_TIME_NOW,
            Int64(delay * Double(NSEC_PER_SEC))
        ),
        dispatch_get_main_queue(), closure)
}

尝试使用以下两行解决方案:

view.layoutIfNeeded()
textView.contentOffset = CGPointMake(textView.contentInset.left, textView.contentInset.top)
  • 视图将出现
    将在用户注意到之前立即显示,但
    视图消失
    部分将惰性地设置动画
  • [mytextView setContentOffset:CGPointZero动画:是]有时不起作用(我不知道为什么),所以使用scrollrangetovisible

对于iOS 10和Swift 3,我做到了:

override func viewDidLoad() {
    super.viewDidLoad()
    textview.isScrollEnabled = false
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    textView.isScrollEnabled = true
}
为我工作,不确定最新版本的Swift和iOS是否存在问题。

问题已解决: iOS=10.2 斯威夫特3 UITextView

我只是用了下面这句话:

displayText.contentOffset.y = 0

在Swift 3中:

  • 视图将布局子视图是进行更改的地方视图将出现也应该工作,但是从逻辑上讲,布局应该在视图将布局子视图中执行

  • 关于方法,scrollRangeToVisiblesetContentOffset都可以使用。但是,setContentOffset允许关闭或打开动画

假设UITextView被命名为yourUITextView。代码如下:

// Connects to the TextView in the interface builder.
@IBOutlet weak var yourUITextView: UITextView!

/// Overrides the viewWillLayoutSubviews of the super class.
override func viewWillLayoutSubviews() {

    // Ensures the super class is happy.
    super.viewWillLayoutSubviews()

    // Option 1:
    // Scrolls to a range of text, (0,0) in this very case, animated.
    yourUITextView.scrollRangeToVisible(NSRange(location: 0, length: 0))

    // Option 2:
    // Sets the offset directly, optional animation.
    yourUITextView.setContentOffset(CGPoint(x: 0, y: 0), animated: false)
}

我有这个问题,但在我的例子中,textview是一些自定义视图的子视图,并将其添加到ViewController中。没有一个解决方案对我有效。为解决此问题,添加了0.1秒延迟,然后启用滚动。这对我有用

textView.isScrollEnabled = false
..
textView.text = // set your text here

let dispatchTime = DispatchTime.now() + 0.1
DispatchQueue.main.asyncAfter(deadline: dispatchTime) {
   self.textView.isScrollEnabled = true
}

我的问题是设置textView在视图出现时滚动到顶部。适用于iOS 10.3.2和Swift 3

解决方案1: 解决方案2:
这是我的密码。它很好用

class MyViewController: ... 
{
  private offsetY: CGFloat = 0
  @IBOutlet weak var textView: UITextView!
  ...

  override viewWillAppear(...) 
  {
      ...
      offsetY = self.textView.contentOffset.y
      ...
  }
  ...
  func refreshView() {
      let offSetY = textView.contentOffset.y
      self.textView.setContentOffset(CGPoint(x:0, y:0), animated: true)
      DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
        [unowned self] in
        self.textView.setContentOffset(CGPoint(x:0, y:self.offSetY), 
           animated: true)
        self.textView.setNeedsDisplay()
      }
  }

你可以使用这个代码

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    textView.scrollRangeToVisible(NSMakeRange(0, 0))
}
我就是这样做的

Swift 4:

extension UITextView {

    override open func draw(_ rect: CGRect)
    {
        super.draw(rect)
        setContentOffset(CGPoint.zero, animated: false)
    }

 }
这对我有用

  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    DispatchQueue.main.async {
      self.textView.scrollRangeToVisible(NSRange(location: 0, length: 0))
    }
  }

我必须调用以下内部viewDidLayoutSubviews(调用内部viewDidLoad太早了):


试过了,伙计,运气不好。似乎是第一反应者的问题。还有其他建议吗?光标位置也有同样的问题,这对我很有用…很好+1。我从下到上都有动画,但我没有要求,所以如何删除它。它不会滚动到上(少几个像素)。请编辑更多细节。这很有效,但为什么这是必要的?苹果的滚动逻辑需要改进,有太多的圈套
extension UITextView {

    override open func draw(_ rect: CGRect)
    {
        super.draw(rect)
        setContentOffset(CGPoint.zero, animated: false)
    }

 }
  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    DispatchQueue.main.async {
      self.textView.scrollRangeToVisible(NSRange(location: 0, length: 0))
    }
  }
    myTextView.setContentOffset(.zero, animated: true)