iOS 15 更新
Apple 引入了一个新的 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 中,您可以呈现一个视图控制器,并且在下面仍然可以看到原始视图控制器,就像一个表单一样。为此,您需要做两件事:
将模态演示样式设置为自定义:
viewControllerToPresent.modalPresentationStyle = UIModalPresentationCustom;
设置过渡委托:
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
不是最直接的解决方案,但可以避免黑客攻击并且效果很好。自定义转换是必需的,因为默认情况下 iOS 将在转换结束时删除第一个视图控制器。
iOS 8 更新
对于 iOS 8,情况再次发生了变化。您需要做的就是使用新的演示风格.OverCurrentContext
,即:
viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverCurrentContext;