วิธีการแก้ปัญหาที่ได้รับจาก @peerless เป็นการเริ่มต้นที่ยอดเยี่ยม แต่มันจะเริ่มการเคลื่อนไหวเมื่อใดก็ตามที่การลากเริ่มขึ้นโดยไม่คำนึงถึงความเร็วของการเลื่อน สิ่งนี้ส่งผลให้เกิดประสบการณ์ที่เปลี่ยนแปลงเร็วกว่าที่คุณได้รับในแอพ Facebook เพื่อให้ตรงกับพฤติกรรมของ Facebook เราจำเป็นต้อง:
- ซ่อน / แสดงแถบนำทางในอัตราที่เป็นสัดส่วนกับอัตราการลาก
- เริ่มภาพเคลื่อนไหวเพื่อซ่อนแถบทั้งหมดหากการเลื่อนหยุดลงเมื่อแถบถูกซ่อนอยู่บางส่วน
- ลบรายการของ navbar ตามที่แถบย่อ
ก่อนอื่นคุณต้องมีคุณสมบัติดังต่อไปนี้:
@property (nonatomic) CGFloat previousScrollViewYOffset;
และนี่คือUIScrollViewDelegate
วิธีการ:
- (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];
}
}
คุณจะต้องใช้วิธีการช่วยเหลือเหล่านี้ด้วย:
- (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];
}];
}
สำหรับพฤติกรรมที่แตกต่างกันเล็กน้อยให้แทนที่บรรทัดที่เปลี่ยนตำแหน่งของแถบเมื่อเลื่อน ( else
บล็อกในscrollViewDidScroll
) ด้วยอันนี้:
frame.origin.y = MIN(20,
MAX(-size, frame.origin.y -
(frame.size.height * (scrollDiff / scrollHeight))));
ซึ่งวางตำแหน่งแถบตามเปอร์เซ็นต์การเลื่อนล่าสุดแทนจำนวนสัมบูรณ์ซึ่งทำให้จางหายช้าลง พฤติกรรมดั้งเดิมนั้นเหมือน Facebook มากกว่า แต่ฉันก็ชอบสิ่งนี้เช่นกัน
หมายเหตุ: วิธีนี้เป็น iOS 7 ขึ้นไปเท่านั้น ตรวจสอบให้แน่ใจว่าได้เพิ่มการตรวจสอบที่จำเป็นหากคุณสนับสนุน iOS เวอร์ชันเก่า