Solusi yang diberikan oleh @peerless adalah awal yang baik, tetapi itu hanya memulai animasi setiap kali menyeret dimulai, tanpa mempertimbangkan kecepatan gulir. Ini menghasilkan pengalaman choppier daripada yang Anda dapatkan di aplikasi Facebook. Untuk mencocokkan perilaku Facebook, kita perlu:
- sembunyikan / tampilkan navbar pada kecepatan yang sebanding dengan laju hambatan
- mulai animasi untuk sepenuhnya menyembunyikan bilah jika gulir berhenti ketika bilah disembunyikan sebagian
- pudar item navbar saat bilah menyusut.
Pertama, Anda membutuhkan properti berikut:
@property (nonatomic) CGFloat previousScrollViewYOffset;
Dan berikut adalah UIScrollViewDelegate
metodenya:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGRect frame = self.navigationController.navigationBar.frame;
CGFloat size = frame.size.height - 21;
CGFloat framePercentageHidden = ((20 - frame.origin.y) / (frame.size.height - 1));
CGFloat scrollOffset = scrollView.contentOffset.y;
CGFloat scrollDiff = scrollOffset - self.previousScrollViewYOffset;
CGFloat scrollHeight = scrollView.frame.size.height;
CGFloat scrollContentSizeHeight = scrollView.contentSize.height + scrollView.contentInset.bottom;
if (scrollOffset <= -scrollView.contentInset.top) {
frame.origin.y = 20;
} else if ((scrollOffset + scrollHeight) >= scrollContentSizeHeight) {
frame.origin.y = -size;
} else {
frame.origin.y = MIN(20, MAX(-size, frame.origin.y - scrollDiff));
}
[self.navigationController.navigationBar setFrame:frame];
[self updateBarButtonItems:(1 - framePercentageHidden)];
self.previousScrollViewYOffset = scrollOffset;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self stoppedScrolling];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView
willDecelerate:(BOOL)decelerate
{
if (!decelerate) {
[self stoppedScrolling];
}
}
Anda juga akan memerlukan metode pembantu ini:
- (void)stoppedScrolling
{
CGRect frame = self.navigationController.navigationBar.frame;
if (frame.origin.y < 20) {
[self animateNavBarTo:-(frame.size.height - 21)];
}
}
- (void)updateBarButtonItems:(CGFloat)alpha
{
[self.navigationItem.leftBarButtonItems enumerateObjectsUsingBlock:^(UIBarButtonItem* item, NSUInteger i, BOOL *stop) {
item.customView.alpha = alpha;
}];
[self.navigationItem.rightBarButtonItems enumerateObjectsUsingBlock:^(UIBarButtonItem* item, NSUInteger i, BOOL *stop) {
item.customView.alpha = alpha;
}];
self.navigationItem.titleView.alpha = alpha;
self.navigationController.navigationBar.tintColor = [self.navigationController.navigationBar.tintColor colorWithAlphaComponent:alpha];
}
- (void)animateNavBarTo:(CGFloat)y
{
[UIView animateWithDuration:0.2 animations:^{
CGRect frame = self.navigationController.navigationBar.frame;
CGFloat alpha = (frame.origin.y >= y ? 0 : 1);
frame.origin.y = y;
[self.navigationController.navigationBar setFrame:frame];
[self updateBarButtonItems:alpha];
}];
}
Untuk perilaku yang sedikit berbeda, ganti baris yang memposisikan ulang bar saat menggulir ( else
blokir scrollViewDidScroll
) dengan yang ini:
frame.origin.y = MIN(20,
MAX(-size, frame.origin.y -
(frame.size.height * (scrollDiff / scrollHeight))));
Ini memposisikan bilah berdasarkan persentase gulir terakhir, bukan jumlah absolut, yang menghasilkan pudar yang lebih lambat. Perilaku aslinya lebih seperti Facebook, tapi saya juga suka yang ini.
Catatan: Solusi ini hanya untuk iOS 7+. Pastikan untuk menambahkan cek yang diperlukan jika Anda mendukung versi iOS yang lebih lama.