Я сделал кнопку, которая добавляет некоторый текст в textView, и я хочу, чтобы она автоматически прокручивалась вниз, когда она была нажата, чтобы пользователь мог видеть добавленный новый текст.
Я не могу использовать решение this в Swift, потому что я не знаю Objective-C. Кто-нибудь знает, как я могу прокручивать нижнюю часть текста в Swift? Благодарю.Прокрутите до конца текстовый файл
ответ
Так что, если вы нажмете на ссылку вы отправившим принятый ответ показывает эту Objective-C код:
-(void)scrollTextViewToBottom:(UITextView *)textView
{
if(textView.text.length > 0)
{
NSRange bottom = NSMakeRange(textView.text.length -1, 1);
[textView scrollRangeToVisible:bottom];
}
}
Так что ваша задача состоит в том, чтобы преобразовать этот код Swift.
Разбивайте их на куски и обрабатывайте их по одному. Во-первых, определение самого метода.
Метод называется scrollTextViewToBottom. В качестве параметра он принимает UITextView и не возвращает результат. Как бы вы могли написать это определение метода в Swift?
Далее посмотрите, что тело метода. Оператор if должен быть точно таким же в Swift. Создание NSRange практически идентично. Вам просто нужно изменить его немного:
let bottom = NSMakeRange(textView.text.length -1, 1)
Та часть, которая, вероятно, самым трудным для кого-то, кто не знает, Objective-C является вызов метода. Он отправляет сообщение scrollRangeToVisible на объект textView
. Прошедший параметр: bottom
. Посмотрите, можете ли вы переписать эту строку в Swift. Затем соедините все это.
Итак, кто отказался от моего ответа и почему? Я пытаюсь научить OP как решать эти проблемы для себя, а не давать ему преобразованный код. В конечном итоге изучение того, как понять это для себя, гораздо более полезно, чем иметь что-то еще, что вы закончили код. –
Я полностью согласен с вами. Сэр. Ваш ответ дает законные шаги, чтобы помочь OP.Upvoted – Korpel
Я не согласен, это очень нестандартный способ прокрутки текстового вида. Большинство iOS наиболее знакомы с использованием 'contentOffset'. Не говоря уже о том, что 'NSRange', скорее всего, будет устаревшим в будущем в пользу Swift's Range. – barndog
UITextView
имеет свойство contentOffsent
. Вы можете либо установить textView.contentOffset
или textView.setContentOffset(offset, animated: true)
Например, если contentSize
вашего зрения текста является (100, 500)
, но высота зрения текста только 100, а затем перейдите к нижней, установите contentOffset
свойство (0, 400)
(это для вертикальный текстовый вид). В более общем виде формула для прокрутки вниз - textView.contentSize.height-textView.height
. Каждый раз, когда вы нажимаете кнопку, установите смещение.
Я бы также рекомендовал прочитать документацию и попытаться понять ее. Swift и iOS достаточно хорошо документированы, и такой вопрос легко найти с помощью Google.
Редактировать: Это работает, потому что UITextView
наследует от UIScrollView
.
Sidenote: Я написал подкласс UITextView
, где вы можете установить вертикальное выравнивание текста, поэтому, если вы установите выравнивание текста на .Bottom
, текст будет выровнен в нижней части представления.
class TextView: UITextView {
enum VerticalAlignment: Int {
case Top = 0, Middle, Bottom
}
var verticalAlignment: VerticalAlignment = .Middle
//override contentSize property and observe using didSet
override var contentSize: CGSize {
didSet {
let textView = self
let height = textView.bounds.size.height
let contentHeight:CGFloat = contentSize.height
var topCorrect: CGFloat = 0.0
switch(self.verticalAlignment){
case .Top:
textView.contentOffset = CGPointZero //set content offset to top
case .Middle:
topCorrect = (height - contentHeight * textView.zoomScale)/2.0
topCorrect = topCorrect < 0 ? 0 : topCorrect
textView.contentOffset = CGPoint(x: 0, y: -topCorrect)
case .Bottom:
topCorrect = textView.bounds.size.height - contentHeight
topCorrect = topCorrect < 0 ? 0 : topCorrect
textView.contentOffset = CGPoint(x: 0, y: -topCorrect)
}
if contentHeight >= height { //if the contentSize is greater than the height
topCorrect = contentHeight - height //set the contentOffset to be the
topCorrect = topCorrect < 0 ? 0 : topCorrect //contentHeight - height of textView
textView.contentOffset = CGPoint(x: 0, y: topCorrect)
}
}
}
// MARK: - UIView
override func layoutSubviews() {
super.layoutSubviews()
let size = self.contentSize //forces didSet to be called
self.contentSize = size
}
}
В приведенном выше примере (вытащил прямо из моего подкласса), вы заметите, что я широко использовать contentOffset
собственности.Я делаю некоторые вычисления, чтобы выяснить, где смещение должно быть основано на свойстве вертикального выравнивания, а затем установить свойство смещения содержимого в соответствии с этим (как вы программно прокручиваете с просмотром прокрутки)
Просто, где является UITextView
в вопрос:
let bottom = myTextView.contentSize.height
myTextView.setContentOffset(CGPoint(x: 0, y: bottom), animated: true) // Scrolls to end
Пробовал и смещение содержимого, и прокрутки, чтобы получить смешанные результаты и изменчивую прокрутку; оглядевшись вокруг ниже, казалось, работал, и при необходимости последовательная прокрутка вниз.
В viewdidload:
self.storyTextView.layoutManager.allowsNonContiguousLayout = false
Затем, когда это необходимо:
let stringLength:Int = self.storyTextView.text.characters.count
self.storyTextView.scrollRangeToVisible(NSMakeRange(stringLength-1, 0))
Swift 4
let bottom = NSMakeRange(textLog.text.count - 1, 1)
textLog.scrollRangeToVisible(bottom)
Свифта 3
let bottom = NSMakeRange(textLog.text.characters.count - 1, 1)
textLog.scrollRangeToVisible(bottom)
Обновление: спасибо @AntoineRucquoy для Swift 4 напоминания!
С Swift 4.x и во избежание устаревшего предупреждения используйте textLog.text.count, а не textLog.text.characters.count :-) –
Я использую следующие в приложение, которое прокручивается на дно автоматически добавляется текст:
Сначала при инициализации вашего TextView, сделать следующее:
textView.layoutManager.allowsNonContiguousLayout = false
textView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
Затем добавьте следующий метод наблюдателя:
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
var bottom = textView.contentSize.height - textView.frame.size.height
if bottom < 0 {
bottom = 0
}
if textView.contentOffset.y != bottom {
textView.setContentOffset(CGPoint(x: 0, y: bottom), animated: true)
}
}
установка allowsNonContiguousLayout к ложным фиксированный контент. Проблемы для меня.
Добавление contentSize наблюдателя будет наблюдать за любые новые изменения в contentSize в TextView и вызовите функцию -observeValue (forKeyPath ...) при внесении изменений.
В -observeValue (...) функции, мы сначала получить нижней (у contentOffset когда полностью прокручивается на дно). Затем мы проверяем, является ли это значение отрицательным, что означает, что высота contentSize меньше высоты кадра textView, и вы не можете действительно прокручивать. Если вы попытаетесь программно прокрутить это отрицательное значение, это вызовет этот печально известный джиттер, который многие знают и любят. Поэтому, чтобы избежать этого дрожания, мы просто устанавливаем значение для того, что оно уже должно быть, или вы также можете просто return.
Тогда мы просто тест, чтобы увидеть, если contentOffset уже не равен нижней значения , мы даем ему, что новое значение. Это позволяет избежать установки contentOffset, когда его не нужно устанавливать.
Если вы имеете дело с attributedText имущества UITextView в:
в viewDidLoad()
self.storyTextView.layoutManager.allowsNonContiguousLayout = false
в методе прокруткой
let stringLength:Int = self.storyTextView.attributedText.string.characters.count
self.storyTextView.scrollRangeToVisible(NSMakeRange(stringLength-1, 0))
Язык: Swift
Последующие шаги как указано ниже:
// Объявляем
@IBOutlet weak var trTextDataRead: UITextView!
// Cunstom метод
func insertTextView(text: String){
//Insert text
trTextDataRead.text.append(text)
//Scroll to the end
let btm = NSMakeRange(trTextDataRead.text.lengthOfBytes(using: String.Encoding.utf8), 0)
trTextDataRead.scrollRangeToVisible(btm)
}
Многие люди объясняют, как для прокрутки вниз, но одна вещь, которую следует отметить, что это не будет работать, если вы поместите его в viewDidLoad
. Например: мне нужно было использовать это для прокрутки журнала до нижней части страницы при загрузке страницы. Для того, чтобы сделать это, я должен был осуществить следующий код
- (void) viewDidLoad {
[super viewDidLoad];
[_logTextView setText:[Logger loadLogText]];
}
- (void) viewDidLayoutSubviews {
[_logTextView
setContentOffset:CGPointMake(
0.0,
_logTextView.contentSize.height
- _logTextView.frame.size.height
)
animated:NO
];
}
Фактическая прокрутка UITextView не может быть сделано в viewDidLoad
.
В моей реализации viewDidLoad
я установил текст для текстового поля.
В моей реализации viewDidLayoutSubviews
я установил смещение содержимого для UITextView, создав CGPoint, используя высоту содержимого текстовых просмотров минус высота самого текстового представления. Таким образом, когда он прокручивается донизу, нижняя часть текста находится не в верхней части окна, а внизу текст внизу находится в нижней части окна.
Swift 4
private func textViewScrollToBottom() {
let bottomRange = NSMakeRange(self.myTextView.text.count - 1, 1)
self.myTextView.scrollRangeToVisible(bottomRange)
}
если 'textView' прокручивать вы можете прокручивать? Что именно вы имеете в виду? Вы пробовали это до публикации? Покажите какой-нибудь код :) – Korpel
какая версия os вы используете? – PK20
'self.textView.scrollRangeToVisible (NSMakeRange (0, 0))' попробуйте, где для диапазона положить конец 'textView' – Korpel