轻松实现部分背景半透明的呈现效果

实现一个简单的呈现/解散动画效果,当呈现时,呈现的主要内容和背景要明显区分,背景呈现一个半透明遮罩效果,透过背景可以看到下层 View Controller 的内容:

呈现控制器(Presenting View Controller)

呈现控制器即要弹出另外一个控制器的 View Controller。本例中即 ViewController 类。当呈现时,使用如下代码:

// 1
UIStoryboard* sb=[UIStoryboard storyboardWithName:@"Main" bundle:nil];
ModalController* vc = [sb instantiateViewControllerWithIdentifier:@"modal"];

// 2
vc.modalPresentationStyle = UIModalPresentationOverCurrentContext;
// 3
[self presentViewController:vc animated:NO completion:^{
    [vc present];
}];

代码说明:

  1. 呈现时,构造被呈现控制器(Presented View Controller)实例,本例中的被呈现控制器即 ModalController 类。
  2. 将被呈现控制器的 modalPresentationStyle 设置为 OverCurrentContext。这点很重要。
  3. 呈现控制器调用 presentViewController 方法,但 animated 参数要设置为 NO。否则会采用默认的 Transition 动画。这样动画结束后,被呈现控制器的背景色仍然不能呈现透明(或半透明)效果。在完成块中,调用 modalPresentationStyle 的 present 方法,这个方法会播放我们自定义的呈现动画(后面介绍)。

被呈现控制器(Presented View Controller)

首先,在 ModalController.m 中,找到 viewDidLoad 方法加入:

self.view.backgroundColor = [UIColor clearColor];

这是让背景一开始时透明,不然在呈现动画之前会出现一个短暂的白屏(零点几秒,不注意看不见)。

然后是实现 present 方法:

-(void)present{
    //1
    CGFloat originY = self.contentViewCenterY.constant;
    //2
    CGFloat viewHeight = self.view.bounds.size.height;
    // 3
    self.contentViewCenterY.constant = -(viewHeight);
    // 4
    [self.view layoutIfNeeded];
    // 5
    [UIView animateWithDuration:0.5 animations:^{
        // 将背景设置为半透明
        self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:0.4];
        // 再将 contentView 移入视图
        self.contentViewCenterY.constant = originY;
        [self.view layoutIfNeeded];
    }];
}

这个方法实现呈现动画。代码解释如下:

  1. contentView 是呈现内容的主要View,即呈现后不透明的内容(前景),此外的区域则是半透明的,作为背景显示。而 contentViewCenterY 是一个 IBOutlet 连接,引用了 contentView 的中心 Y 坐标这个约束(通过 IB 创建的),稍后我们会移动这个 Y 坐标的 contant 值,因此需要把原来的 contant 值保存一个备份,以便恢复。
  2. 获取根视图的高度。
  3. 修改 contentViewCenterY 的 contant 值,先将 contentView 移出视图(下方)。
  4. 每次修改约束之后,都要调用 layoutIfNeeded,使约束生效。
  5. 执行 UIView 动画,在动画块中,将背景设置为半透明(原来我们设置为透明了),这个属性不可以动画,因此一旦设置完就不会改变了。然后通过修改 contentViewCenterY 让 我们要呈现的主要内容视图上移到原来的位置(屏幕中心)。最后别忘了修改约束之后要调用 layoutIfNeeded。

然后实现解散动画:

-(void)dismiss{
    // 1
    CGFloat viewHeight = self.view.bounds.size.height;
    // 2
   [UIView animateWithDuration:0.5 animations:^{
       self.contentViewCenterY.constant = -(viewHeight);
       [self.view layoutIfNeeded];
   } completion:^(BOOL finished) {
       [self dismissViewControllerAnimated:NO completion:nil];
   }];
}

解散动画很简单:

  1. 首先获取根视图高度。
  2. 执行 UIView 动画,在动画块中,修改 contentViewCenterY 将我们要呈现的主要内容移除屏幕(下方),别忘了调用 layoutIfNeeded。

然后在关闭按钮或者背景 View 被触摸时调用 dismiss 播放解散动画:

- (IBAction)touched:(id)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值