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

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

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

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

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

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

Геро

6 ответов

Решение

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

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

Обходной путь / решение простое: создайте подкласс 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 

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

textView.contentInset=UIEdgeInsetsZero;

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

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

YourViewController.h отрезан

@interface YourViewController : UIViewController <UITextViewDelegate, UIScrollViewDelegate>

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

@end

Фрагмент YourViewController.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:). Мы также размораживаем прокрутку, когда пользователь закончит редактирование.

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

Я испытывал похожую проблему с нежелательным UITextView прокрутки. Мне наконец удалось это исправить, сбросив contentSize в конце моего keyboardDidShow:

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

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

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

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

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

Другие вопросы по тегам