Próbowałem naśladować to zachowanie w sytuacji, w której potrzebowałem niestandardowego nagłówka siedzącego wokół UITableView. Założyłem własny pasek „nawigacji”, ponieważ znajduje się on poniżej kilku innych elementów na stronie i chciałem, aby nagłówki sekcji były zgodne z domyślnym zachowaniem „dokowania”. Myślę, że znalazłem całkiem sprytny i zwięzły sposób na dostosowanie UITableView / UIScrollView razem z innym obiektem w stylu podobnym do tego, który widać na Facebooku / Instagramie / Chrome / itp. aplikacje.
W moim pliku .xib moje komponenty są załadowane do widoku swobodnego: http://imgur.com/0z9yebJ (przepraszam, nie mam rep do wbudowanych obrazów)
Zwróć uwagę, że na lewym pasku bocznym tabela jest uporządkowana za głównym widokiem nagłówka. Nie widać tego na zrzucie ekranu, ale ma również tę samą pozycję y, co główny widok nagłówka. Ponieważ rozszerza się poza zasięg wzroku, właściwość contentInset w UITableView jest ustawiona na 76 (wysokość głównego widoku nagłówka).
Aby główny widok nagłówka przesuwał się w górę zgodnie z UIScrollView, używam metod scrollViewDidScroll UIScrollViewDelegate do wykonywania niektórych obliczeń i zmiany contentInset UIScrollView, a także ramki widoku głównego nagłówka.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
UIEdgeInsets insets = scrollView.contentInset;
tableViewInsetDelta = tableViewOriginalInsetValue + scrollView.contentOffset.y;
insets.top = tableViewOriginalInsetValue - tableViewInsetDelta;
if (scrollView.contentOffset.y > -76 && scrollView.contentOffset.y < 0) {
[scrollView setContentInset:insets];
self.pathTitleContainer.frame = CGRectMake(self.pathTitleContainer.frame.origin.x, 44 - tableViewInsetDelta, self.pathTitleContainer.frame.size.width, self.pathTitleContainer.frame.size.height);
} else if (scrollView.contentOffset.y > 0) {
insets.top = 0;
[scrollView setContentInset:insets];
self.pathTitleContainer.frame = CGRectMake(self.pathTitleContainer.frame.origin.x, -32, self.pathTitleContainer.frame.size.width, self.pathTitleContainer.frame.size.height);
} else if (scrollView.contentOffset.y < -76) {
insets.top = 76;
[scrollView setContentInset:insets];
self.pathTitleContainer.frame = CGRectMake(self.pathTitleContainer.frame.origin.x, 44, self.pathTitleContainer.frame.size.width, self.pathTitleContainer.frame.size.height);
}
}
Pierwsza instrukcja if wykonuje większość ciężkiego podnoszenia, ale musiałem uwzględnić dwie pozostałe, aby obsłużyć sytuacje, w których użytkownik przeciąga na siłę, a początkowe wartości contentOffset wysyłane do scrollViewDidScroll są poza zakresem pierwszego if instrukcji .
Ostatecznie to działa dla mnie naprawdę dobrze. Nienawidzę ładować moich projektów masą nadętych podklas. Nie mogę mówić, czy jest to najlepsze rozwiązanie pod względem wydajności (zawsze wahałem się przed umieszczeniem dowolnego kodu w scrollViewDidScroll, ponieważ jest on wywoływany przez cały czas), ale ślad kodu jest najmniejszy, jaki widziałem w jakimkolwiek rozwiązanie tego problemu i nie obejmuje zagnieżdżania UITableView w UIScrollView (Apple odradza to w dokumentacji, a zdarzenia dotykowe kończą się nieco dziwnie w UITableView). Mam nadzieję, że to komuś pomoże!