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