美文网首页转载
iOS自定义模态present动画

iOS自定义模态present动画

作者: 帅聪哥 | 来源:发表于2019-01-21 16:26 被阅读64次

前沿

项目因为越做越大,所以为了配合模块化开发的时候,想到了如何进行展示,想起来支付宝和微信的present方式,就想到了如何操作了。

正文

想要实现不一般又炫酷的present过渡动画,则必须使用自定义动画了,主要就是UIViewControllerAnimatedTransitioning这个协议中进行具体的动画操作。
网上也看过其他人写的,虽然确实挺花俏的,但是真正导入项目的时候有些不可用,最典型的问题就是影响了原有的代码,还有就是只支持一次性展示效果,达不到多层次效果,比如present一个controllerA之后,再从controllerA present到controllerB。为了完善一下,特地整理了一下项目中的分享给大家,demo地址

当然,为这个只是针对present模态展示的,就和支付宝的效果是一样的。
总共用到的效果有定义为四种

typedef NS_ENUM(NSInteger,BDTransformType){
    /*push动画*/
    BDTransformPush,
    /**pop动画*/
    BDTransformPop,
    /**present model动画*/
    BDTransformPresent,
    /**present dismiss动画*/
    BDTransformDismiss,
};

具体步骤
1、在BDTransformPresent的时候,原来的整个背景向下缩放动画,目标页面从底部弹出,
2、在BDTransformDismiss的时候,与BDTransformPresent对应,
如果是左滑手势,,
3、在BDTransformPush的时候,页面和正常的push 类似
4、在BDTransformPop与push对应

组成部分

1、控制器分类,如果想要使用这个效果,则直接bd_present即可

@interface UIViewController (PresentAnimation)
///是否存在这个present自定义动画,如果不是调用bd_present的方式则为no
@property (nonatomic, assign,readonly)BOOL presentAnimation;
///默认为nil ,如果调用了bd_present后,则被presnent的控制器则存在这个Key值,方便在delloc的时候将animator销毁
@property (nonatomic,copy,readonly)NSString *presentKey;

/**
 特殊present样式,
 */
- (void)bd_presentViewController:(UIViewController*)controller animated:(BOOL)animated completion:(void (^)(void))completion;
@end

2、对象管理记具体实施者

/**
 每个present的操作对应的代理都是一对一的,所以只能针对单个对象
 */
@interface BDPresentAnimator : NSObject<UIViewControllerTransitioningDelegate>

@property (nonatomic,weak)UIViewController *controller;

@end

NS_ASSUME_NONNULL_END

/**
 专门管理复杂保存与删除代理,动画保持的效果必须在BDPresentAnimator生命周期内
 */
@interface BDPresentAnimatorManager : NSObject

+ (instancetype)manager;

- (void)addAnimaor:(BDPresentAnimator*)animator withKey:(NSString*)key;
/**需要在控制器销毁的时候手动remove动画对象*/
- (void)removeAnimatorWithKey:(NSString*)key;
/**需要在控制器销毁的时候手动remove动画对象*/
- (void)removeAnimatorWithController:(UIViewController*)controller;

@end

3、具体动画实现方式

/**
 针对模块化设计方案
 这个暂时只针对present类型的,因为将这些操作可以只在被present内部处理,而无需在每次都在外部处理,这样方面
 代码设计本应如此
 */
@interface BDPresentAnimatorAction : NSObject<UIViewControllerAnimatedTransitioning>

/**
 动画样式
 */
@property (nonatomic,assign)BDTransformType transformType;

@end
/**
只贴了一种实现
*/
- (void)presentAnimationWithTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
    UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
    UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
    toView.frame = transitionContext.containerView.bounds;
    [transitionContext.containerView addSubview:toView];
    
    CGFloat width = toView.bounds.size.width;
    CGFloat height = toView.bounds.size.height;
    toView.frame = CGRectMake(0, height, width, height);
    
    
    fromView.layer.zPosition = -1;
    CATransform3D scale = CATransform3DIdentity;
    scale = CATransform3DScale(scale, [UIScreen mainScreen].bounds.size.height == 812.0f?0.94:0.95, [UIScreen mainScreen].bounds.size.height == 812.0f?0.96:0.97, 1);
    
    [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
        fromView.layer.transform = scale;
        toView.frame = CGRectMake(0, 0, width, height);
    } completion:^(BOOL finished) {
        [transitionContext completeTransition:!transitionContext.transitionWasCancelled];
        fromView.layer.zPosition = 0;
        fromView.layer.transform = CATransform3DIdentity;
    }];
    
}

具体使用

第一步:

UIViewController *controller = [[NSClassFromString(@"BDStoreTabBarController") alloc]init];
    [self.navigationController bd_presentViewController:controller animated:YES completion:nil];

第二步:
在BDStoreTabBarController页面delloc的时候

-(void)dealloc
{
    [[BDPresentAnimatorManager manager] removeAnimatorWithController:self];
  或者
   [self removePresentAnimator];
}
demo演示.gif

后续将考虑弄一个bool值,设置一下页面是否支持左滑页面,如果你有点子,可以留言哈,大家一起学习。

如果感觉可以记得点个赞,在这里下载

相关文章

网友评论

    本文标题:iOS自定义模态present动画

    本文链接:https://www.haomeiwen.com/subject/bwjcjqtx.html