You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

子视图控制器滚动时隐藏父视图导航栏与侧滑菜单方案

实现滚动时隐藏父视图控制器的导航栏与侧边菜单

这个需求其实很常见,核心就是让子视图控制器把滚动状态传递给父VC,由父VC来控制导航栏和侧边菜单的显隐。下面给你一步步拆解实现方案:

1. 子VC监听滚动事件

首先要在子VC里捕捉滚动行为——因为你的层级是scrollView -> view -> textView,其实直接监听UITextView的滚动就行(它本身是UIScrollView的子类),或者监听外层的scrollView都可以。

Swift 实现示例

在子VC的viewDidLoad里设置监听:

override func viewDidLoad() {
    super.viewDidLoad()
    // 用UIScrollViewDelegate监听滚动
    textView.delegate = self
    // 或者给外层scrollView设置delegate
    // scrollView.delegate = self
}

// 记录上一次的滚动偏移量,用来判断滚动方向
private var lastScrollOffset: CGFloat = 0

extension YourChildViewController: UIScrollViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let currentOffset = scrollView.contentOffset.y
        // 判断是否向下滚动
        let isScrollingDown = currentOffset > lastScrollOffset
        
        // 加个20pt的阈值,避免轻微滚动就触发UI变化,提升体验
        if abs(currentOffset - lastScrollOffset) > 20 {
            // 把滚动状态传递给父VC
            if let parentVC = parent as? YourParentViewController {
                parentVC.toggleNavAndMenu(hide: isScrollingDown)
            }
        }
        
        // 更新上一次的偏移量
        lastScrollOffset = currentOffset
    }
}

Objective-C 实现示例

- (void)viewDidLoad {
    [super viewDidLoad];
    self.textView.delegate = self;
    // 或者 self.scrollView.delegate = self;
}

static CGFloat lastScrollOffset = 0;

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    CGFloat currentOffset = scrollView.contentOffset.y;
    BOOL isScrollingDown = currentOffset > lastScrollOffset;
    
    if (abs(currentOffset - lastScrollOffset) > 20) {
        YourParentViewController *parentVC = (YourParentViewController *)self.parentViewController;
        [parentVC toggleNavAndMenuHide:isScrollingDown];
    }
    
    lastScrollOffset = currentOffset;
}

2. 父VC实现UI显隐逻辑

在父VC里定义一个公开方法,用来处理导航栏和侧边菜单的显隐,加上动画让过渡更自然:

Swift 实现示例

// 记录当前状态,避免重复触发
private var isNavAndMenuHidden = false

func toggleNavAndMenu(hide: Bool) {
    // 如果当前状态和要设置的状态一致,直接返回,避免重复动画
    guard hide != isNavAndMenuHidden else { return }
    isNavAndMenuHidden = hide
    
    UIView.animate(withDuration: 0.3) {
        // 隐藏/显示导航栏
        self.navigationController?.setNavigationBarHidden(hide, animated: true)
        // 处理侧边菜单:假设你的侧边菜单是一个UIView实例
        self.sliderMenuView.isHidden = hide
        // 如果是自定义的抽屉式菜单,调用它的隐藏方法即可,比如:
        // self.sliderMenu.hide(animated: true)
    }
}

Objective-C 实现示例

static BOOL isNavAndMenuHidden = NO;

- (void)toggleNavAndMenuHide:(BOOL)hide {
    if (hide == isNavAndMenuHidden) return;
    isNavAndMenuHidden = hide;
    
    [UIView animateWithDuration:0.3 animations:^{
        [self.navigationController setNavigationBarHidden:hide animated:YES];
        self.sliderMenuView.hidden = hide;
        // 自定义菜单的隐藏逻辑,比如:
        // [self.sliderMenu hideAnimated:YES];
    }];
}

3. 进阶优化:用协议解耦(更优雅)

上面的写法需要子VC强转父VC类型,耦合性有点高。推荐用协议的方式来解耦,让代码更灵活:

Swift 协议实现

// 定义协议
protocol ScrollNavigationDelegate: AnyObject {
    func shouldHideNavigationAndMenu(_ hide: Bool)
}

// 子VC里添加协议属性
class YourChildViewController: UIViewController {
    weak var navigationDelegate: ScrollNavigationDelegate?
    // ...其他代码
}

// 滚动时调用协议方法
extension YourChildViewController: UIScrollViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        // ...判断滚动方向的逻辑不变
        navigationDelegate?.shouldHideNavigationAndMenu(isScrollingDown)
    }
}

// 父VC遵守协议
extension YourParentViewController: ScrollNavigationDelegate {
    func shouldHideNavigationAndMenu(_ hide: Bool) {
        toggleNavAndMenu(hide: hide)
    }
}

// 父VC添加子VC时设置delegate
func addChildViewController() {
    let childVC = YourChildViewController()
    childVC.navigationDelegate = self
    // ...添加子VC到container view的代码
}

注意事项

  • 动态加载内容时,确保滚动监听不会失效:每次从API加载完textView内容后,检查delegate是否还正确设置。
  • 调整阈值:20pt只是参考值,你可以根据实际产品体验调整,比如改成15pt或者30pt。
  • 边界情况处理:比如滚动到顶部时,应该自动显示导航栏和菜单,你可以在scrollViewDidScroll里判断contentOffset.y <= 0时强制设置为显示状态。

内容的提问来源于stack exchange,提问作者Hasnain Kanji

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:24:48