UITextView не прокручивается сверху при загрузке

Когда у меня есть текст, который не заполняет UITextView, он прокручивается вверх, как нужно. Когда на экране больше текста, чем на экране, UITextView прокручивается до середины текста, а не сверху.

Вот некоторые потенциально важные детали:

В viewDidLoad, чтобы получить некоторые дополнения сверху и снизу UITextView:

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

UITextView использует автоматическую компоновку для привязки 20px сверху, снизу и каждой стороны экрана (выполняется в IB), чтобы обеспечить различные размеры и ориентации экрана.

Я все еще могу прокрутить его пальцем после его загрузки.

ИЗМЕНИТЬ Я обнаружил, что удаление ограничений автоматического макета, а затем исправление ширины, похоже, устраняет проблему, но только для этой ширины экрана.

Ответ 1

UITextView является подклассом UIScrollView, поэтому вы можете использовать его методы. Если все, что вы хотите сделать, это убедиться, что оно прокручивается вверх, а затем, где добавлен текст, попробуйте:

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

EDIT: AutoLayout с любым видом прокрутки быстро становится быстрым. То, что установка фиксированной ширины решает, не удивительно. Если он не работает в -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];
        }

Может все еще понадобиться setContentOffset в -viewDidLayoutSubviews.

(Другим методом было бы создать ограничение макета для "равных" и "равных" высот между текстовым элементом и его супервизом с константой "-40". Оно только "равно", если константа равна нулю, в противном случае она настраивается константой, но поскольку вы можете только добавить это ограничение в представление, которое ограничивает оба представления, вы не можете сделать это в IB.)

Вы можете спросить себя, если я должен это сделать, что такое AutoLayout? Я изучил AutoLayout в глубину, и это отличный вопрос.

Ответ 2

добавьте следующую функцию в класс контроллера вида...

Swift 3

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

Swift 2.1

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

Цель C

- (void)viewDidLayoutSubviews {
    [self.mainTextView setContentOffset:CGPointZero animated:NO];
}

Ответ 3

Swift

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

Objective-C

[self.textView scrollRangeToVisible:(NSMakeRange(0, 0))];

Ответ 4

У меня была такая же проблема! Reset к предложенным ограничениям и просто поместите (y offset)

@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)
    }

Ответ 5

Для iOS9 и более поздних версий textview даже на viewWillAppear: идет с CGRect (0,0,1000,1000). Чтобы это сработало, вам нужно вызвать viewWillAppear:

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

После этого текстовое представление будет иметь правильные данные CGRect, и вы можете выполнить любую операцию прокрутки, которая вам может понадобиться.

Ответ 6

Проблема с помещением кода в viewDidLayoutSubviews и viewWillLayoutSubviews заключается в том, что эти методы называются много (во время вращения устройства, изменения размеров и т.д.). Если вы читаете что-то из текстового представления и поворачиваете устройство, вы ожидаете, что часть просматриваемого вами контента останется на экране. Вы не ожидаете, что он прокрутится вверх. Вместо прокрутки содержимого вверх, попробуйте сохранить свойство scrollEnabled в текстовом представлении равным NO (false) и снова включить его в viewDidAppear.

Ответ 7

Если вы не хотите испортить ограничения:

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

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

Ответ 8

Это интересная ошибка. В нашем проекте это происходит только на устройствах с экраном iPhone 5 -size. Похоже, что textOffset contentOffset изменяется в некоторый момент в течение жизненного цикла контроллера представления. В viewDidLoad и viewWillAppear текстовое представление contentOffset равно 0,0, и с помощью viewDidAppear оно изменилось. Вы можете увидеть это в viewWillLayoutSubviews. Ограничения, кажется, установлены правильно.

Это гарантирует, что вы не вызовете метод прокрутки, если он не нужен:

if textView.contentOffset.y > 0 {
    textView.contentOffset = CGPoint(x: 0, y: 0)
    // Or use scrollRectToVisible, scrollRangeToVisible, etc.
}

Ответ 9

Для меня это работает по-другому, я попробовал все вещи, упомянутые выше, но ни одна из них не работала в 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)
}

Ответ 10

стриж

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

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    textView.isScrollEnabled = true
}

Ответ 11

Кажется ужасной идеей решить эту проблему в коде в контроллере представления, потому что: 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 в качестве дочернего элемента контроллера представления. Я не знаю, насколько хорошо это работает, если текстовое представление находится под верхними или нижними полосами, но так как никакие вставки не затрагиваются, это должно работать.