如何在UINavigationBar实现随UITableView滚动的渐进式收缩动画?
实现导航栏随滚动渐变收缩的方案
你原有代码的核心问题是通过滚动方向触发固定时长的显隐动画,无法和滚动进度实时绑定,直接替换为以下逻辑即可:
第一步:新增所需属性
在当前类的头文件或者类扩展中添加以下属性:
/// 导航栏最大高度(包含状态栏) @property (nonatomic, assign) CGFloat maxNavBarHeight; /// 导航栏最小收缩高度 @property (nonatomic, assign) CGFloat minNavBarHeight; /// 触发完整收缩效果需要滚动的距离,数值越大收缩节奏越慢 @property (nonatomic, assign) CGFloat scrollTriggerDistance;
第二步:初始化属性参数
在viewDidLoad中初始化配置,可根据自身需求调整数值:
- (void)viewDidLoad { [super viewDidLoad]; // 动态获取当前设备状态栏高度 CGFloat statusBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height; // 普通导航栏总高度=状态栏高度+44,开启大标题的话改为 statusBarHeight + 96 self.maxNavBarHeight = statusBarHeight + 44; // 最小高度可自定义,设为状态栏高度则收缩后仅保留状态栏,设为0则完全隐藏 self.minNavBarHeight = statusBarHeight; // 滚动100pt距离完成整个收缩动画 self.scrollTriggerDistance = 100; }
第三步:重写scrollViewDidScroll逻辑
删除你原有滚动监听的代码,替换为实时绑定滚动偏移量的逻辑,不需要固定时长的动画即可实现跟手效果:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView { CGFloat offsetY = scrollView.contentOffset.y; // 下拉到顶部回弹时限制偏移量,避免异常拉伸 if (offsetY < 0) offsetY = 0; // 计算收缩进度,范围固定在0~1之间,0=完全展开,1=完全收缩 CGFloat progress = offsetY / self.scrollTriggerDistance; progress = MAX(0, MIN(1, progress)); // 用transform调整导航栏位置实现收缩效果,比直接改frame性能更优 CGFloat moveUpDistance = (self.maxNavBarHeight - self.minNavBarHeight) * progress; self.navigationController.navigationBar.transform = CGAffineTransformMakeTranslation(0, -moveUpDistance); // 同步调整导航栏透明度,不需要渐变的话可以删掉这部分 self.navigationController.navigationBar.alpha = 1 - progress; // 同步调整导航栏上的按钮、标题等子控件透明度 for (UIView *subview in self.navigationController.navigationBar.subviews) { subview.alpha = 1 - progress; } }
第四步:页面退出时重置导航栏状态
避免跳转到其他页面时导航栏显示异常:
- (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; // 重置导航栏的形变和透明度 self.navigationController.navigationBar.transform = CGAffineTransformIdentity; self.navigationController.navigationBar.alpha = 1; }
注意事项
如果你是iOS 11及以上版本,并且使用系统自带的大标题导航栏,不需要手动写上述逻辑,只要开启
self.navigationController.navigationBar.prefersLargeTitles = YES,同时将UITableView的顶部约束到父视图顶部而非安全区,系统会自动实现导航栏随滚动收缩的原生效果,流畅度更高。
内容的提问来源于stack exchange,提问作者stefanosn
相关产品推荐
相关产品推荐

