Как остановить прокрутку 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, и это решало эту проблему.