UITableView contentOffSet работает неправильно

В viewWillAppear я добавил UISearchBar в качестве моего заголовка UITableView. При просмотре нагрузки я скрываю UISearchBar под UINavigationBar, используя contentOffSet UITableView. Когда пользователь вытаскивает таблицу, открывается панель поиска.

После добавления headerview я скрываю его, используя код ниже.

self.tableView.contentOffset = CGPointMake(0, 40); //My searhbar height is 40

Но время contentOffSet не скрывает headerview. Какая может быть ошибка.

Ответ 1

Это сработало для меня:

// contentOffset will not change before the main runloop ends without queueing it, for iPad that is
dispatch_async(dispatch_get_main_queue(), ^{
    // The search bar is hidden when the view becomes visible the first time
    self.tableView.contentOffset = CGPointMake(0, CGRectGetHeight(self.searchBar.bounds));
});

Поместите его в свой -viewDidLoad или -viewWillAppear

Ответ 2

Не уверен, в чем причина (у меня нет времени исследовать ее прямо сейчас), но я решил эту проблему, используя performSelector после задержки 0. Пример:

- (void)viewWillAppear:(BOOL)animated {
    ...
    [self performSelector:@selector(hideSearchBar) withObject:nil afterDelay:0.0f];
}

- (void)hideSearchBar {
    self.tableView.contentOffset = CGPointMake(0, 44);
}

Ответ 3

В более ранних версиях iOS SDK такие методы, как viewWillAppear выполнялись в основном потоке, теперь они выполняются в фоновом потоке, поэтому проблема возникает сейчас.

Большинство обратных вызовов имеют тенденцию запускаться в фоновом потоке, поэтому всегда проверяйте безопасность потока при выполнении вызовов пользовательского интерфейса.

Отправьте изменение в смещении содержимого в главном потоке:

Цель С

dispatch_async(dispatch_get_main_queue(), ^{
    CGPoint offset = CGPointMake(0, self.searchBar.bounds.height)
    [self.tableView setContentOffset:offset animated:NO];
});

Свифт 3

DispatchQueue.main.async {
            let offset = CGPoint.init(x: 0, y: self.searchBar.bounds.height)
            self.tableView.setContentOffset(offset, animated: false)
        }

Ответ 4

Это сработало для меня.

self.tableView.beginUpdates()
self.tableView.setContentOffset( CGPoint(x: 0.0, y: 0.0), animated: false)
self.tableView.endUpdates()

Цель-C:

[_tableView beginUpdates];
[_tableView setContentOffset:CGPointMake(0, 0)];
[_tableView endUpdates];

Ответ 5

Это может быть из-за атрибута "Настроить прокрутку" в контроллере просмотра. Смотрите это: fooobar.com/questions/70263/...

EDIT: Обязательно проверьте значение "contentInset", чтобы узнать, что происходит, поскольку это также влияет на вид прокрутки. Это значение изменяется после viewWillAppear: когда установлено "Настроить прокрутки", похоже, что другие пытаются избежать, используя очереди отправки и т.п.

Ответ 6

После одного часа тестов единственный способ, который работает на 100%, следующий:

-(void)hideSearchBar
{
    if([self.tableSearchBar.text length]<=0 && !self.tableSearchBar.isFirstResponder)
    {
        self.tableView.contentOffset = CGPointMake(0, self.tableSearchBar.bounds.size.height);
        self.edgesForExtendedLayout = UIRectEdgeBottom;
    }
}

-(void)viewDidLayoutSubviews
{
    [self hideSearchBar];
}

при таком подходе вы всегда можете скрыть панель поиска, если она пуста

Ответ 7

В моем случае проблема заключалась в том, что я назвал

 [_myGreatTableView reloadData];

до получения _tableView.contentOffset.y. Это всегда возвращалось "0".

Итак, я переключил порядок этих методов, и теперь он работает.

Это довольно странное поведение, на мой взгляд, потому что offset возвратил 0, но пользовательский интерфейс по-прежнему сохранял положение прокрутки таблицы.

Ответ 8

Вам нужно скрыть панель поиска самостоятельно, когда вы прокручиваете таблицу. Поэтому не ставьте его как заголовок UITableView. Вы можете скрыть его, установив его высоту в ноль. Таким образом, если в вашем представлении таблицы задано автоматическое изменение размера, оно будет расширяться.

Ответ 9

Проблема заключается в автоматической маскировке. Выберите таблицу и убедитесь, что вы выбрали все строки, как показано на изображении ниже.

enter image description here

Ответ 10

Проблема может быть с размером строки поиска. Попробуйте следующую строку кода.

[searchBar sizeToFit];

Ответ 11

Строка кода работает так, как должна.

Объяснение contentOffset для UITableView:

Например, если у вас есть представление таблицы высотой 100. Его содержимое может быть больше, чем показано, например, 150. contentOffset сообщит таблицу, с которой в исходном тексте. Скажем contentOffset = (0, 40), содержимое будет показано после 40 из его высоты.

Примечание. После прокрутки содержимого не влияет на ранее установленный contentOffset.

Ответ 12

Если ваша таблица всегда будет иметь хотя бы одну строку, просто прокрутите ее до первой строки таблицы, и панель поиска будет скрыта автоматически.

let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0)

self.tableView.selectRowAtIndexPath(firstIndexPath, анимированный: false, scrollPosition:.Top)

Если вы поместите вышеуказанный код в viewDidLoad, он выдает ошибку, потому что tableView еще не загружен, поэтому вы должны поместить его в viewDidAppear, потому что этот пункт tableView уже загружен.

Если вы положили его на viewDidAppear, каждый раз, когда вы открываете tableView, он будет прокручиваться вверх.

Может быть, вы не хотите этого поведения, если tableView остается открытым, например, когда он является UITabBar View Controller или когда вы выполняете segue, а затем возвращаетесь. Если вы просто хотите, чтобы он прокручивался вверху начальной загрузки, вы можете создать переменную, чтобы проверить, является ли она начальной нагрузкой, чтобы она прокручивалась вверху только один раз.

Сначала определите переменную с именем isInitialLoad в классе контроллера представления и установите для нее значение "true":

var isInitialLoad = true

И затем проверьте, истинна ли isInitialLoad в viewDidAppear, и если это правда, прокрутите вверх и установите для переменной isInitialLoad значение false:

if isInitialLoad {
    let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0)
    self.tableView.selectRowAtIndexPath(firstIndexPath, animated: false, scrollPosition: .Top)
    isInitialLoad = false
}

Ответ 13

В iOS 7/8/9 простой self.automaticallyAdjustsScrollViewInsets = NO; решил проблему в моем случае

Ответ 14

Я исправил это с layoutIfNeeded()

    self.articlesCollectionView.reloadData()
    self.articlesCollectionView.layoutIfNeeded()
    self.articlesCollectionView.setContentOffset(CGPoint(x: 0, y: 40), animated: false)

Ответ 15

self.tableView.contentInset = UIEdgeInsetsMake(self.navigationController.navigationBar.frame.size.height -80, 0, 0, 0);