iOS 15更新
苹果公司推出了一个新的API,UISheetPresentationController,可以轻松实现半高度(.medium()
)的表单展示。如果您需要更多自定义内容,请参考最初的回答。
let vc = UIViewController()
if let sheet = vc.presentationController as? UISheetPresentationController {
sheet.detents = [.medium()]
}
self.present(vc, animated: true, completion: nil)
最初的回答
在iOS 7中,您可以呈现一个视图控制器,仍然可以看到原始视图控制器,就像表单一样。要实现这一点,您需要完成两件事:
Set the modal presentation style to custom:
viewControllerToPresent.modalPresentationStyle = UIModalPresentationCustom
Set the transitioning delegate:
viewControllerToPresent.transitioningDelegate = self
在这种情况下,我们将委托对象设置为self,但它也可以是另一个对象。委托对象需要实现协议中的两个必需方法,可能是这样的:最初的回答。
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
SemiModalAnimatedTransition *semiModalAnimatedTransition = [[SemiModalAnimatedTransition alloc] init];
semiModalAnimatedTransition.presenting = YES;
return semiModalAnimatedTransition;
}
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
SemiModalAnimatedTransition *semiModalAnimatedTransition = [[SemiModalAnimatedTransition alloc] init];
return semiModalAnimatedTransition;
}
此时,您可能会想,SemiModalAnimatedTransition
类是从哪里来的。嗯,它是从teehan+lax博客中采用的自定义实现。
这是该类的头文件:
@interface SemiModalAnimatedTransition : NSObject <UIViewControllerAnimatedTransitioning>
@property (nonatomic, assign) BOOL presenting;
@end
最初的回答
实现方式如下:
#import "SemiModalAnimatedTransition.h"
@implementation SemiModalAnimatedTransition
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
return self.presenting ? 0.6 : 0.3;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
CGRect endFrame = fromViewController.view.bounds;
if (self.presenting) {
fromViewController.view.userInteractionEnabled = NO;
[transitionContext.containerView addSubview:fromViewController.view];
[transitionContext.containerView addSubview:toViewController.view];
CGRect startFrame = endFrame;
startFrame.origin.y = endFrame.size.height;
toViewController.view.frame = startFrame;
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
fromViewController.view.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed;
toViewController.view.frame = endFrame;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
else {
toViewController.view.userInteractionEnabled = YES;
[transitionContext.containerView addSubview:toViewController.view];
[transitionContext.containerView addSubview:fromViewController.view];
endFrame.origin.y = endFrame.size.height;
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
toViewController.view.tintAdjustmentMode = UIViewTintAdjustmentModeAutomatic;
fromViewController.view.frame = endFrame;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
}
@end
这并不是最直接的解决方案,但避免了hack并且运行良好。自定义转换是必需的,因为iOS默认会在转换结束时删除第一个视图控制器。
iOS 8更新
对于iOS 8,一切又变了。你只需要使用新的展示样式.OverCurrentContext
,例如:
viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverCurrentContext
menuViewController
,只需按照自己的喜好将menuView
动画显示在屏幕上即可。 - Brian Nickel