ios-加载时,UITextView不会滚动到顶部

当我的文本没有填充UITextView时,它会按预期滚动到顶部。 当文本超出屏幕显示的大小时,UITextView将滚动到文本的中间而不是顶部。

以下是一些可能相关的详细信息:

在viewDidLoad中,在UITextView的顶部和底部提供一些填充:

self.mainTextView.textContainerInset = UIEdgeInsetsMake(90, 0, 70, 0);

UITextView使用自动布局将其从屏幕的顶部,底部和每一侧(在IB中完成)锚定20px,以允许使用不同的屏幕尺寸和方向。

加载后,我仍然可以用手指滚动它。

编辑我发现删除自动布局约束然后固定宽度似乎只能解决此问题,但仅适用于该屏幕宽度。

Michael Campsall asked 2020-02-29T10:13:19Z
11个解决方案
116 votes

将以下函数添加到您的视图控制器类中...

迅捷3

override func viewDidLayoutSubviews() {
    self.mainTextView.setContentOffset(.zero, animated: false)
}

斯威夫特2.1

override func viewDidLayoutSubviews() {
    self.mainTextView.setContentOffset(CGPointZero, animated: false)
}

目标C

- (void)viewDidLayoutSubviews {
    [self.mainTextView setContentOffset:CGPointZero animated:NO];
}
Muhammad Ibrahim answered 2020-02-29T10:14:26Z
18 votes

UITextView是UIScrollView的子类,因此可以使用其方法。 如果您只想确保将其滚动到顶部,那么无论在何处添加文本,请尝试:

[self.mainTextView setContentOffset:CGPointZero animated:NO];

编辑:具有任何滚动视图的自动版式很快就会变得怪异。 设置固定宽度即可解决,这并不奇怪。 如果在-viewDidLayoutSubviews中不起作用,那很奇怪。 手动设置布局约束可能会起作用。 首先在IB中创建约束:

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewWidthConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewHeightConstraint;

然后在ViewController中

    -(void)updateViewConstraints {
            self.textViewWidthConstraint.constant = self.view.frame.size.width - 40.0f;
            self.textViewHeightConstraint.constant = self.view.frame.size.height - 40.0f;
            [super updateViewConstraints];
        }

-viewDidLayoutSubviews中可能仍然需要setContentOffset。

(另一种方法是为textView及其superView之间的“等于”宽度和“等于”高度创建布局约束,常数为“ -40”。如果常数为零,则仅等于“相等”。 ,否则它会根据常数进行调整。但是由于您只能将此约束添加到同时约束两个视图的视图中,因此您无法在IB中执行此操作。)

您可能会问自己,如果我必须这样做,AutoLayout有什么意义? 我已经深入研究了AutoLayout,这是一个很好的问题。

Mike Sand answered 2020-02-29T10:13:52Z
11 votes

迅速

self.textView.scrollRangeToVisible(NSMakeRange(0, 0))

目标C

[self.textView scrollRangeToVisible:(NSMakeRange(0, 0))];
AlessandroDP answered 2020-02-29T10:14:50Z
9 votes

我有同样的问题! 重置为建议的约束,然后放置(y偏移)

@IBOutlet weak var textContent: UITextView!

    override func viewDidLoad() {
        textContent.scrollsToTop = true
        var contentHeight = textContent.contentSize.height
        var offSet = textContent.contentOffset.x
        var contentOffset = contentHeight - offSet
        textContent.contentOffset = CGPointMake(0, -contentOffset)
    }
Ruso answered 2020-02-29T10:15:10Z
7 votes

对于iOS9及更高版本,即使在viewWillAppear:上,textview也随CGRect(0,0,1000,1000)一起提供。 为了使其正常工作,您必须调用viewWillAppear:

[self.view setNeedsLayout];
[self.view layoutIfNeeded];
// * Your code here

之后,textview将具有正确的CGRect数据,您可以执行可能需要的任何滚动操作。

iPav answered 2020-02-29T10:15:36Z
2 votes

将代码放入viewDidLayoutSubviews和viewWillLayoutSubviews中的问题在于,这些方法被称为很多(在设备旋转,调整视图大小等过程中)。 如果您正在从文本视图中阅读内容,并且旋转设备,那么您希望正在查看的内容部分保留在屏幕上。 您不希望它滚动回到顶部。不要将内容滚动到顶部,而是尝试将文本视图的scrollEnabled属性设置为NO(false),然后在viewDidAppear中将其重新打开。

Jovan Stankovic answered 2020-02-29T10:16:00Z
1 votes

如果您不想惹麻烦:

override func updateViewConstraints() {
    super.updateViewConstraints()
}

override func viewDidLayoutSubviews() {
    self.textLabel.setContentOffset(CGPointZero, animated: false)
}
Gustavo Severo answered 2020-02-29T10:16:19Z
1 votes

这是一个有趣的错误。 在我们的项目中,这仅在屏幕尺寸为27688059450891970197056的设备上发生。 看来textview 27688059450891970197057在视图控制器生命周期的某个时候发生了变化。 在viewDidLoad和276880594508919701970中,textview的contentOffset0,0,而到27688059450891970197062已更改。 您可以看到它发生在276880594508919701970。约束似乎设置正确。

这将确保除非需要,否则不会调用滚动方法:

if textView.contentOffset.y > 0 {
    textView.contentOffset = CGPoint(x: 0, y: 0)
    // Or use scrollRectToVisible, scrollRangeToVisible, etc.
}
Evan R answered 2020-02-29T10:16:45Z
1 votes

对我来说,这是以不同的方式起作用的,我尝试了上面提到的所有方法,但func viewWillAppear(_ animated: Bool)中没有任何操作。最终使textView向上滚动,并在func viewDidAppear(_ animated: Bool)中,它在屏幕出现后滚动。

下面为我工作,但在键盘上下时遇到了一些与约束有关的问题。

override func viewDidLayoutSubviews() {
    self.textView.setContentOffset(.zero, animated: false)
}

下面按预期工作:

override func viewDidLoad() {
    super.viewDidLoad()

    self.textView.scrollsToTop = true
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    self.view.layoutIfNeeded()
    self.textView.setContentOffset(.zero, animated: false)
}
Swapnil Dhotre answered 2020-02-29T10:17:14Z
0 votes

迅速

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

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    textView.isScrollEnabled = true
}
Борис Лысенко answered 2020-02-29T10:17:33Z
0 votes

在视图控制器中的代码中处理此问题似乎是一个糟糕的主意,因为:A.视图控制器没有犯任何错误或做任何错误,以及B,如果您有多个视图控制器并带有错误滚动的文本 视图,您最终得到了冗余代码。 解决方案应该是编写存在于文本视图类中的代码。 我的解决方案与Interface Builder配合使用,在其中我只需为UITextView选择一个自定义类并使用该类:

import Foundation
import UIKit

class TopTextView: UITextView {
    var scrolled = false

    override func layoutSubviews() {
        super.layoutSubviews()
        if scrolled { return }
        setContentOffset(.zero, animated: false)
        scrolled = true
    }
}

这对我有用。 我碰巧有一个视图控制器,其子视图带有UITextView作为该视图的子视图,而不是UITextView作为该视图控制器的子视图。 我不知道如果文本视图位于顶部或底部条形之下,效果如何,但是由于没有边缘边缘被触摸,因此这应该可行。

David Rector answered 2020-02-29T10:17:59Z
translate from https://stackoverflow.com:/questions/28053140/uitextview-is-not-scrolled-to-top-when-loaded