用AddChildViewController自制抽屉

本文介绍了一种在iOS应用中实现抽屉菜单动画的方法,通过使用addChildViewController进行页面切换,实现了平滑过渡效果。文章提供了具体的代码示例并解决了在实现过程中遇到的警告问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以前写抽屉是在viewController上使用两个view块,先add View2 到viewController.view上,再根据需要insert View1 atIndex:0,并且同时移动view1.frame.origin.x来使界面出现抽屉菜单效果。

现在可以用的方法有了AddChildViewController,感觉挺方便的。


首先,将子controller都添加到主页上去,并指定当前页面

- (void)viewDidLoad
{
    [super viewDidLoad];

    UIStoryboard *mainSB = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    firstViewController = [mainSB instantiateViewControllerWithIdentifier:@"FirstController"];
    secondController = [mainSB instantiateViewControllerWithIdentifier:@"SecondController"];
    
    [self addChildViewController:firstViewController];
    [self addChildViewController:secondController];
    
    self.currentViewController = firstViewController;
    [self.view addSubview:firstViewController.view];
}

然后,当点击切换按钮,且新旧Controller不同时候,注意

- (IBAction)showFirstPage:(id)sender {

        UIViewController *oldViewController = self.currentViewController;
        firstViewController.view.frame =  oldViewController.view.frame;;
        [self.view addSubview:firstViewController.view];
        
        [self transitionFromViewController:self.currentViewController
                          toViewController:firstViewController
                                  duration:.3f
                                   options:UIViewAnimationOptionTransitionNone
                                animations:^{
                                    
                                    CGRect newFrame = firstViewController.view.frame;
                                    newFrame.origin.x = 0;
                                    firstViewController.view.frame = newFrame;
        
                                } completion:^(BOOL finished) {
                                    if (finished) {
                                        self.currentViewController = firstViewController;
                                    }else{
                                        self.currentViewController = oldViewController;
                                    }
                                }];
}

这样就已经能实现效果了,只是会出现一个警告:Unbalanced calls to begin/end appearance transitions for XXXX。

查阅了一些材料,发现是因为这样写可能造成一个动画还没完成就开始执行新的动画,小小修改一下就不会有警告了。

- (IBAction)showSecondPage:(id)sender {
        UIViewController *oldViewController = self.currentViewController;
        secondController.view.frame =  oldViewController.view.frame;;
        
        [self transitionFromViewController:self.currentViewController
                          toViewController:secondController
                                  duration:.3f
                                   options:UIViewAnimationOptionTransitionNone
                                animations:^{
                                    
                                    CGRect newFrame = secondController.view.frame;
                                    newFrame.origin.x = 0;
                                    secondController.view.frame = newFrame;
                                   
                                } completion:^(BOOL finished) {
                                    if (finished) {
                                        self.currentViewController = secondController;
                                        [self.view addSubview:secondController.view];
                                        [oldViewController.view removeFromSuperview];
                                    }else{
                                        self.currentViewController = oldViewController;
                                    }
                                }];
}

个人觉得贞娃儿的博客关于此bug的分析写得挺不错的,大家如果感兴趣,可以去 这里看看。

关于动画的写法,我比较推荐这篇博文:看这里



---------------------------华丽丽的分界线---------------------------

说到这里,顺便说下与addChildViewController对应的几个方法

addChildViewController不会增加内存消耗,只有addSubview会。

因此当某页面退出视图的时候应该使用[self.view removeFromSuperview];

若某Controller也不想用了,可以考虑  [self removeFromParentViewController];

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值