Отключение автоматической прокрутки UITableView при редактировании UITextField внутри UITableViewCell
Я использую пользовательский UITableViewCell
внутри моего UITableView
. Каждый из этих UITableViewCell
довольно высок и содержит UITextField
вверху.
Когда пользователь отбирает UITextField
для его редактирования, появляется клавиатура, а UITableView
автоматически прокручивается, чтобы ячейка находилась в верхней части экрана.
Проблема в том, что это прокручивает UITableView
до нижней части UITableViewCell
, а не сверху. Когда UITableViewCell
высок и отредактирован, UITextField
находится вверху, поэтому вы не видите UITextField
. Я знаю, как прокручивать UITableView
программно, но я просто не знаю, как отключить эту автоматическую прокрутку, чтобы я мог прокручивать UITableView
самостоятельно. Как я могу это сделать?
Ответы
Ответ 1
Поведение autoscroll находится в функциональности UITableViewController
.
Чтобы отключить автоматическую прокрутку, я нашел два способа:
- Используйте вместо
UITableViewController
просто a UIViewController
- установите источник данных и делегат самостоятельно.
- Отмените метод
viewWillAppear
и не вызывайте [super viewWillAppear: animated]
В обоих решениях вы отключите не только Autoscroll, но и некоторые другие приятные, но не существенные функции, описанные в обзоре ссылки на класс Apple:
https://developer.apple.com/documentation/uikit/uitableviewcontroller
Ответ 2
Определите свойства для UITableViewController
:
@property (nonatomic) BOOL scrollDisabled;
@property (nonatomic) CGFloat lastContentOffsetY;
Перед вызовом becomeFirstResponder
:
// Save the table view y content offset
lastContentOffsetY = tableViewController.tableView.contentOffset.y;
// Enable scrollDisabled
scrollDisabled = YES;
Добавьте следующий код в контроллер табличного представления:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (self.scrollDisabled) {
[self.tableView setContentOffset:CGPointMake(0, lastContentOffsetY)];
}
...
}
После вызова resignFirstResponder
установите scrollDisabled = NO
.
Ответ 3
Вы можете сделать следующее:
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardDidShow:)
name:UIKeyboardDidShowNotification object:nil];
}
- (void)unregisterForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification
{
self.tableView.scrollEnabled = NO;
}
- (void)keyboardDidShow:(NSNotification *)notification
{
double delayInSeconds = 0.3;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
self.tableView.scrollEnabled = YES;
});
}
Затем реализуем этот метод UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (! self.tableView.scrollEnabled)
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
}
!!! Но будьте осторожны, если пользователь закроет место в UITextField, которое будет закрыто клавиатурой, тогда оно не будет прокручиваться.
С моей точки зрения, самое лучшее, что нужно сделать, это убедиться, что все ячейки сверху до одного с включенным UITextField будут видны, когда появится Keyboard.
Ответ 4
Проблема для меня была не столько в том, что она прокручивалась, а в том, что редактирование текста редактировалось с экрана.
Поэтому вместо того, чтобы препятствовать прокрутке, я просто пересказываю табличное представление туда, где хочу, когда запускается редактирование, например:
public func textViewShouldBeginEditing(textView: UITextView) -> Bool {
dispatch_async(dispatch_get_main_queue()) {
tableViewController.tableView.scrollToRowAtIndexPath(self.indexPath!, atScrollPosition: UITableViewScrollPosition.Middle, animated: true)
}
return true
}
Ответ 5
К сожалению, переопределение -viewWillAppear: не работает для меня в iOS 8.
Вот мое решение (как в реализации UITableViewController):
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] removeObserver:self.tableView name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self.tableView name:UIKeyboardWillHideNotification object:nil];
}
Так как поведение автоматической прокрутки вызывается оповещениями show/hide уведомлений UIKeyboard, поэтому просто НЕ наблюдайте их.
Ответ 6
Лучший способ заключается в подклассе UITableView
, а затем переопределить setContentOffset(_ contentOffset: CGPoint, animated: Bool)
, а не называть super.setContentOffset(_ contentOffset: CGPoint, animated: Bool)
. В этом методе контроллер просмотра выполняет автоматический прокрутка.
override func setContentOffset(_ contentOffset: CGPoint, animated: Bool)
{
//Do nothing
}
Ответ 7
Вы пытались установить значение "scrollsToTop" - tableview в значение NO. По умолчанию это ДА.
Ответ 8
Вы можете попробовать сделать следующее:
self.tableView.scrollEnabled = NO;
Это должно отключить прокрутку в представлении таблицы.