模式过渡样式,如邮件应用程序 [英] Modal transition style like in Mail app

查看:86
本文介绍了模式过渡样式,如邮件应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现模态演示效果,其中所呈现的视图仅部分覆盖父视图,如下图所示。

I am trying to achieve a modal presentation effect where the presented view covers the parent view only partially as shown in the picture below.

我知道我可以通过使用自定义转换实现此目的 UIPresentationController 。我不想重新发明轮子所以在我继续开发之前我想问一下。

I know I could achieve this by implementing custom transitions using UIPresentationController. I don't want to reinvent the wheel so before I roll on with development I would like to ask.

是否支持API中的此类转换?

我研究了所有可用的模态演示样式,在我看来,我不支持我想要的过渡,实现它的唯一方法就是编码。

I researched all available Modal Presentation Styles and it appears to me there is no support for the transition I want to make and the only way of achieving it is just to code it.

推荐答案

我遇到了同样的问题。我也沿着模态演示风格路线走下去并且不停地撞墙(特别是让它在iPhone而不是iPad上工作)。

I ran into this exact same issue. I went down the modal presentation styles route as well and kept hitting a wall (specifically getting it working on an iPhone rather than an iPad).

经过一些挖掘后,我虽然能够让它工作。我是这样做的:

After some digging around, I was able to get it working though. Here's how I did it:

首先,我们需要一个我们将要呈现的视图控制器(模态一个)来将视图的背景颜色设置为透明并设置导航控制器的视图框架到某个偏移量。

To start, we need a view controller that we will be presenting (the modal one) to set it's view's background color to transparent and set the frame of the navigation controller's view to some offset.

@import UIKit;

@class ModalViewController;

@protocol ModalViewControllerDelegate <NSObject>

- (void)modalViewControllerDidCancel:(ModalViewController *)modalViewController;

@end

@interface ModalViewController : UIViewController
@property (weak, nonatomic) id<ModalViewControllerDelegate> delegate;

- (instancetype)initWithRootViewController:(UIViewController *)rootViewController;
@end



ModalViewController.m



ModalViewController.m

static const CGFloat kTopOffset = 50.0f;

@implementation ModalViewController {
    UINavigationController *_navController;
}

- (instancetype)initWithRootViewController:(UIViewController *)rootViewController
{
    self = [super initWithNibName:nil bundle:nil];
    if (self) {
        rootViewController.navigationItem.leftBarButtonItem = [self cancelButton];
        _navController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
        self.view.backgroundColor = [UIColor clearColor];
        [self.view addSubview:_navController.view];

        // this is important (prevents black overlay)
        self.modalPresentationStyle = UIModalPresentationOverFullScreen;
    }

    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    CGRect bounds = self.view.bounds;
    _navController.view.frame = CGRectMake(0, kTopOffset, CGRectGetWidth(bounds), CGRectGetHeight(bounds) - kTopOffset);
}

- (UIBarButtonItem *)cancelButton
{
    return [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonItemStylePlain target:self action:@selector(cancelButtonClicked:)];
}

- (void)cancelButtonClicked:(id)sender
{
    [_delegate modalViewControllerDidCancel:self];
}

@end

接下来,我们需要设置显示控制器运行以下动画:

Next, we need to set up the presenting controller to run the following animation:


  • 缩小规模

  • 淡出lil 'bit

  • 使用 presentViewController呈现模态视图控制器:动画:完成

  • Scale itself down
  • Fade out a lil' bit
  • Present the modal view controller using presentViewController:animated:completion

这就是我做的事情

static const CGFloat kTransitionScale = 0.9f;
static const CGFloat kTransitionAlpha = 0.6f;
static const NSTimeInterval kTransitionDuration = 0.5;

@interface PresentingViewController <ModalViewControllerDelegate>
@end

@implementation PresentingViewController
...
...

- (void)showModalViewController
{
    self.navigationController.view.layer.shouldRasterize = YES;
    self.navigationController.view.layer.rasterizationScale = [UIScreen mainScreen].scale;

    UIViewController *controller = // init some view controller
    ModalViewController *container = [[ModalViewController alloc] initWithRootViewController:controller];
    container.delegate = self;

    __weak UIViewController *weakSelf = self;
    [UIView animateWithDuration:kTransitionDuration animations:^{
        weakSelf.navigationController.view.transform = CGAffineTransformMakeScale(kTransitionScale, kTransitionScale);
        weakSelf.navigationController.view.alpha = kTransitionAlpha;
        [weakSelf presentViewController:container animated:YES completion:nil];
    } completion:^(BOOL finished) {
        weakSelf.navigationController.view.layer.shouldRasterize = NO;
    }];
}

#pragma mark - ModalViewControllerDelegate

- (void)modalViewControllerDidCancel:(ModalViewController *)modalViewController
{
    __weak UIViewController *weakSelf = self;
    [UIView animateWithDuration:kTransitionDuration animations:^{
        weakSelf.navigationController.view.alpha = 1;
        weakSelf.navigationController.view.transform = CGAffineTransformIdentity;
        [weakSelf dismissViewControllerAnimated:YES completion:nil];
    }];
}
@end

这篇关于模式过渡样式,如邮件应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆