Как остановить прокрутку UITextView при входе в нее

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

Это изображение, когда UITextView неактивно:
UITextView неактивен http://gerodt.homeip.net/uitextview-notactive.png

И это когда я нажал кнопку UITextView, чтобы сделать его активным:
UITextView active http://gerodt.homeip.net/uitextview-active.png

Я не UITextView для прокрутки вообще, он должен оставаться неподвижным. Как я могу это достичь? Я уже пробовал несколько настроек в Interface Builder, но пока не повезло.

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

Геро

Ответ 1

Вот как UITextView ведет себя в соответствии с инженером Apple, это предназначено, а UITextView предназначен для текста, который имеет по крайней мере несколько строк в высоту. Для этого нет никакой работы, используйте UITextField или увеличивайте UITextView до высоты не менее 3 строк.

Ответ 2

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

Обходной путь/решение прост: подкласс UITextView и переопределить метод contentInset, чтобы он всегда возвращал UIEdgeInsetZero. Попробуйте следующее:

//
// BCTextView
//
// UITextView seems to automatically be resetting the contentInset
// bottom margin to 32.0f, causing strange scroll behavior in our small
// textView.  Maybe there is a setting for this, but it seems like odd behavior.
// override contentInset to always be zero.
//
@interface BCZeroEdgeTextView : UITextView
@end

@implementation BCZeroEdgeTextView

- (UIEdgeInsets) contentInset { return UIEdgeInsetsZero; }

@end 

Ответ 3

Вы также можете просто сделать:

textView.contentInset=UIEdgeInsetsZero;

в файле делегата.

Ответ 4

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

YourViewController.h отключен

@interface YourViewController : UIViewController <UITextViewDelegate, UIScrollViewDelegate>

@property(nonatomic, weak) IBOutlet UITextView *textView;

@end

Снимок тэга ViewViewController.m

@implementation YourViewController {
@private
    BOOL _freezeScrolling;
    CGFloat _lastContentOffsetY;
}

// UITextViewDelegate
- (void)textViewDidBeginEditing:(UITextView *)textView {
    // tell the view to hold the scrolling
    _freezeScrolling = YES;
    _lastContentOffsetY = self.textView.contentOffset.y;
}

// UITextViewDelegate
- (void)textViewDidEndEditing:(UITextView *)textView {
    _freezeScrolling = NO;
}

// UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (_freezeScrolling) {
        // prevent the scroll view from actually scrolling when we don't want it to
        [self repositionScrollView:scrollView newOffset:CGPointMake(scrollView.contentOffset.x, _lastContentOffsetY)];
    }
}

// UIScrollViewDelegate
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    // scroll prevention should only be a given scroll event and turned back off afterward
    _freezeScrolling = NO;
}

// UIScrollViewDelegate
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
    // when the layout is redrawn, scrolling animates. this ensures that we are freeing the view to scroll
    _freezeScrolling = NO;
}

/**
 This method allows for changing of the content offset for a UIScrollView without triggering the scrollViewDidScroll: delegate method.
 */
- (void)repositionScrollView:(UIScrollView *)scrollView newOffset:(CGPoint)offset {
    CGRect scrollBounds = scrollView.bounds;
    scrollBounds.origin = offset;
    scrollView.bounds = scrollBounds;
}

Что также важно отметить в примере кода выше, это последний метод. Вызов любого типа setContentOffset: фактически вызовет прокрутку, что приведет к вызову scrollViewDidScroll:. Поэтому вызов setContentOffset: приводит к бесконечному циклу. Установка границ прокрутки является обходным способом для этого.

Вкратце, мы говорим контроллеру вида, чтобы предотвратить прокрутку UITextView, когда мы обнаруживаем, что пользователь выбрал текст для редактирования. Мы также сохраняем текущее смещение содержимого (поскольку мы знаем, что позиция - это то, что мы хотим). Если UITextView пытается выполнить прокрутку, мы удерживаем смещение содержимого на месте до тех пор, пока прокрутка не остановится (что вызывает либо scrollViewDidEndDecelerating:, либо scrollViewDidEndScrollingAnimation:). Мы также размораживаем прокрутку, когда пользователь редактирует.

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

Ответ 5

У меня возникла аналогичная проблема с нежелательной прокруткой UITextView. Я, наконец, сумел исправить это, сбросив содержимое contentize в конце моего keyboardDidShow:

- (void)keyboardDidShow:(NSNotification *)notification {
  textView.contentSize = CGSizeZero;
}

Вам также потребуется зарегистрироваться для уведомления клавиатуры, например:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];

В моем случае мне не нужна прокрутка, так как я сбросил фрейм на высоту textView contentSize, когда textViewDidChange (растущий текст внутри UIScrollView).

Ответ 6

Попробуйте помещать Redraw в текстовое окно вместо Scale to Fill. Возможно, вам придется захватить делегат и сохранить смещение содержимого, но он должен по крайней мере предотвратить прыжок в точку (0,0). Также Autoresizes subview должен быть отключен. Он тоже каждый раз перескакивал на верх над текстом, и это решило эту проблему.

enter image description here