it-roy-ru.com

UITableView contentOffSet не работает должным образом

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

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

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

Но иногда contentOffSet не скрывает заголовок. В чем может быть ошибка.

19
JiteshW

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

// 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

28
maz

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

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

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

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

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

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

Цель C

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

Swift 3

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

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

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];
3
Kishor

Это может быть из-за атрибута «Настроить вставки вида прокрутки» на контроллере представления . Смотрите это: https://stackoverflow.com/a/22022366

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

2
techniao

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

 [_myGreatTableView reloadData];

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

Поэтому я поменял порядок этих методов и теперь он работает.

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

2
Mexx

После одного часа испытаний единственный способ, который работает на 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];
}

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

2
Kappe

Я исправил это с помощью layoutIfNeeded ()

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

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

enter image description here

0
Dhara

Строка кода работает как надо.

Объяснение contentOffset из UITableView:

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

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

0
Abdurrahman Mubeen Ali

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

0
Saumil Shah

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

[searchBar sizeToFit];
0
uranpro

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

0
parilogic

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

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

self.tableView.selectRowAtIndexPath (firstIndexPath, animated: false, scrollPosition: .Top)

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

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

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

Сначала определите переменную с именем 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
}
0
drdrdrdr