Как заставить UITextView прокручивать вверх каждый раз, когда я изменяю текст? - PullRequest
91 голосов
/ 05 августа 2009

ОК, у меня проблема с UITextView. Вот проблема:

Я добавляю текст к UITextView. Затем пользователь дважды щелкает, чтобы выбрать что-то. Затем я изменяю текст в UITextView (программно, как указано выше), а UITextView прокручивается вниз страницы, где находится курсор.

Однако это не то место, где пользователь нажал. Он ВСЕГДА прокручивается до нижней части UITextView независимо от того, где пользователь нажал.

Итак, вот мой вопрос: как заставить UITextView прокручивать вверх каждый раз, когда я изменяю текст? Я пробовал contentOffset и scrollRangeToVisible. Ни одна из них не работает.

Любые предложения будут оценены.

Ответы [ 36 ]

1 голос
/ 08 мая 2019

Мне пришлось вызывать следующее внутри viewDidLayoutSubviews (вызов внутри viewDidLoad был слишком ранним):

    myTextView.setContentOffset(.zero, animated: true)
1 голос
/ 24 мая 2016

Попробуйте использовать это решение для двух строк:

view.layoutIfNeeded()
textView.contentOffset = CGPointMake(textView.contentInset.left, textView.contentInset.top)
1 голос
/ 21 мая 2018

Этот код решает проблему, а также помогает избежать ненужной автоматической прокрутки до конца textView. Просто используйте метод setTextPreservingContentOffset: вместо установки текста в textView напрямую.

@interface ViewController () {
    __weak IBOutlet UITextView *textView;
    CGPoint lastContentOffset;
    NSTimer *autoscrollTimer;
    BOOL revertAnyContentOffsetChanges;
}

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [textView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
}

- (void)dealloc
{
    [textView removeObserver:self forKeyPath:@"contentOffset"];
}

- (void)setTextPreservingContentOffset:(NSString *)text
{
    lastContentOffset = textView.contentOffset;
    [autoscrollTimer invalidate];
    revertAnyContentOffsetChanges = YES;
    textView.text = text;
    autoscrollTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(enableScrolling:) userInfo:nil repeats:NO];
    autoscrollTimer.tolerance = 1;
}

- (void)enableScrolling:(NSTimer *)timer
{
    revertAnyContentOffsetChanges = NO;
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (revertAnyContentOffsetChanges && [keyPath isEqualToString:@"contentOffset"] && [[change valueForKey:@"new"] CGPointValue].y != lastContentOffset.y) {
        [textView setContentOffset:lastContentOffset animated:NO];
    }
}

@end
0 голосов
/ 17 октября 2018

Для Swift я думаю, что самый простой способ сделать это - создать подкласс UITextView и использовать этот маленький трюк

import UIKit

class MyTextView: UITextView {
    override var text: String! {
        willSet {
            isScrollEnabled = false
        } didSet {
            isScrollEnabled = true
        }
    }
}
0 голосов
/ 15 декабря 2016

Решение для Xcode 8.0. Свифт 2.3. Работает для построения интерфейса и может быть легко изменен для программной работы.

class MBTextView: UITextView
{
    required init?(coder aDecoder: NSCoder)
    {
        super.init(coder: aDecoder)
        setupView()
    }

    func setupView() {}
}

class MBStartFromTopTV: MBTextView
{
    override func setupView()
    {
        // some custom code
    }

    override func drawRect(rect: CGRect)
    {
        super.drawRect(rect)
        setContentOffset(CGPoint.zero, animated: false)
    }
}
0 голосов
/ 06 января 2018

Ответ ChallengerGuy полностью решил мою проблему, как только я добавил небольшую задержку перед повторной включением прокрутки. До добавления задержки все страницы моего PageController были исправлены, за исключением первой страницы, которая также исправлялась после любого взаимодействия пользователя со страницей. Добавление задержки также исправило положение прокрутки UITextView на этой первой странице.

override open func viewDidLoad() {
    super.viewDidLoad()
    textView.isScrollEnabled = false
    textView.text = textToScroll            
   ... other stuff
}

override open func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    Central().delay(0.5) {
        self.textView.isScrollEnabled = true
    }
}

(Функция задержки в моем файле Central ().)

func delay(_ delay: Double, closure:@escaping ()->()) {
    DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
        closure()
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...