美文网首页tomios进阶UI
iOS 底部弹出视图正确姿势

iOS 底部弹出视图正确姿势

作者: Hanfank | 来源:发表于2019-11-24 18:53 被阅读0次

由于前段时间非常忙,很久没有更新博客了。
今天给大家带来一个从底部弹出的视图控制器容器。
此容器比较适合

  • 地址选择器
  • 性别选择器
  • 各种选择器
  • 以及从底部弹出的视图

Example

例子

How usage

简单的留给别人,复杂的留给自己
只需要在需要弹出的控制器中指定代理即可

@implementation BTPresentViewController
- (instancetype)init{
    [super init];
    if (self) {
        _aniamtion = [[BTCoverVerticalTransition alloc]initPresentViewController:self withRragDismissEnabal:YES];
        self.transitioningDelegate = _aniamtion;
    }
    return self;
}
@end

如何呈现?

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    BTPresentViewController * vc = [[BTPresentViewController alloc]init];;
    [self presentViewController:vc animated:YES completion:nil];
}

和使用系统的呈现方式一样。

如何实现的

大部分轮子使用的是创建一个view,然后添加到window或者view上,然后加上动画来实现。
这种创建方式一旦创建就会一直留在内存中,不会自动释放,只能随着被添加的控制器一起释放,需要手动进行释放内存,不能做到独立管理自己的生命周期。
我认为这种方式并不是很理想。
我们完全可以根据修改转场动画实现这样的效果。
使用modal的方式呈现,dismiss后也会从内存中释放,生命周期独立管理。

  • 自定义转场动画
    实现自定义转场动画需要指定转场代理对象,和指定呈现方式为自定义。
/// 指定遵循了UIViewControllerTransitioningDelegate的对象,当然self也可以成为其代理对象。
self.transitioningDelegate = _transitioningDelegate;
/// 指定呈现方式为自定义
self.modalPresentationStyle = UIModalPresentationCustom;
  • 转场协议UIViewControllerTransitioningDelegate包含了几个方法
/// 视图呈现时的动画方法
- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source;
/// 视图dismiss时的动画方法
- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed;
/// 视图呈现执行的手势,例如我们需要向上拖拽来呈现视图
- (nullable id <UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id <UIViewControllerAnimatedTransitioning>)animator;
/// 视图关闭执行的手势,例如需要向下拖拽来关闭视图
- (nullable id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator;
/// 视图管理控制器
- (nullable UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(nullable UIViewController *)presenting sourceViewController:(UIViewController *)source NS_AVAILABLE_IOS(8_0);

创建一个代理对象,写上初始化方法,遵循并实现协议 UIViewControllerTransitioningDelegate

/// 对象遵循 UIViewControllerTransitioningDelegate 转场协议
@interface BTCoverVerticalTransition : NSObject<UIViewControllerAnimatedTransitioning,UIViewControllerTransitioningDelegate>
/// 初始化方法 默认有拖拽dismiss关闭功能
- (instancetype)initPresentViewController:(UIViewController*)viewController;
/// 初始化方法 可以传入是否关闭dismiss关闭功能
- (instancetype)initPresentViewController:(UIViewController*)viewController withRragDismissEnabal:(BOOL)enabel;
@end

实现

@implementation BTCoverVerticalTransition
- (instancetype)initPresentViewController:(UIViewController*)viewController{
    self = [super init];
    if (self) {
        self.viewController = viewController;
        viewController.modalPresentationStyle = UIModalPresentationCustom;
    }
    return self;
}

- (instancetype)initPresentViewController:(UIViewController*)viewController withRragDismissEnabal:(BOOL)enabel{
    self = [super init];
    if (self) {
        self.viewController = viewController;
        viewController.modalPresentationStyle = UIModalPresentationCustom;
        if (enabel == YES) {
            MKInteractiveTransition * interactive = [[MKInteractiveTransition alloc]initWithViewController:viewController];
            self.interactive = interactive;
        }
    }
    return self;
}

#pragma mark - UIViewControllerAnimatedTransitioning
/// 这里返回self ,让自己成为它的实现对象。
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source{
    return self;
}
/// 这里返回self ,让自己成为它的实现对象。
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed{
    return self;
}

/// 返回遵循UIViewControllerInteractiveTransitioning协议手势的对象。
- (id<UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id<UIViewControllerAnimatedTransitioning>)animator{
    return self.interactive.interative ? self.interactive : nil;
}

/// 由于我们并不需要拖拽呈现,所以不用实现这个方法
//- (nullable id <UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id <UIViewControllerAnimatedTransitioning>)animator{
//}

- (nullable UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(nullable UIViewController *)presenting sourceViewController:(UIViewController *)source NS_AVAILABLE_IOS(8_0){
    MKPresentationController * vc = [[MKPresentationController alloc]initWithPresentedViewController:presented presentingViewController:presenting];
    return vc;
}
/// 遵循UIViewControllerAnimatedTransitioning协议
@interface BTCoverVerticalTransition : NSObject<UIViewControllerAnimatedTransitioning,...>
...
@end

然后并实现协议


#pragma mark - UIViewControllerTransitioningDelegate
/// 这里的from to 是怎么回事呢?
/// 当呈现时,呈现的对象视图就是to,
/// 当dismiss时,关闭的对象就是from
- (void)animateTransition:(nonnull id<UIViewControllerContextTransitioning>)transitionContext {
    UIViewController * to = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIViewController * from = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    if (to.isBeingPresented) {
        [self animateTransitionForPresentTransition:transitionContext];
    }
    if (from.beingDismissed) {
        [self animateTransitionForDismiss:transitionContext];
    }
}

/// 返回一个执行动画时间 
- (NSTimeInterval)transitionDuration:(nullable id<UIViewControllerContextTransitioning>)transitionContext {
    return transitionContext.isAnimated ? 0.3 : 0;
}

#pragma mark - 
- (void)animateTransitionForPresentTransition:(nonnull id<UIViewControllerContextTransitioning>)transitionContext{
    UIViewController * to = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    [transitionContext.containerView addSubview:to.view];
    CGRect finalFrame = [transitionContext finalFrameForViewController:to];
    to.view.frame = finalFrame;
    to.view.transform = CGAffineTransformMakeTranslation(0, finalFrame.size.height);
    [UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0 usingSpringWithDamping:0.9 initialSpringVelocity:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        to.view.transform = CGAffineTransformMakeTranslation(0, 0);
    } completion:^(BOOL finished) {
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];
}

- (void)animateTransitionForDismiss:(nonnull id<UIViewControllerContextTransitioning>)transitionContext{
    UIViewController *from = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    CGRect finalFrame = [transitionContext finalFrameForViewController:from];
    [UIView animateWithDuration:0.25 animations:^{
        from.view.transform = CGAffineTransformMakeTranslation(0, finalFrame.size.height);
    } completion:^(BOOL finished) {
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];
}

这是上面实现的转场动画的关键部分代码,需要了解更多转场动画

建议fork,添加修改成自己想要的转场动画。

over

相关文章

  • iOS 底部弹出视图正确姿势

    由于前段时间非常忙,很久没有更新博客了。今天给大家带来一个从底部弹出的视图控制器容器。此容器比较适合 地址选择器 ...

  • IOS底部弹出view视图

    直接上代码先,后面有截图可以参考,小白代码。 举一反三,可以实现 从左边显示,右边显示,上面显示的view。 参考...

  • iOS 自定义弹出视图的正确姿势

    前言 开发时经常会自定义一些弹出视图,比如弹框(Alert)、底部弹出框(Action Sheet)等。自定义弹出...

  • 底部弹出视图封装

    先看效果: 点击更换头像按钮,动画弹出底部视图,背景视图阴影效果,视图里的控件的touch响应事件通过block传...

  • Flutter仿ios底部弹出选择视图

    先放一张效果图 1、使用示例 2、视图源码 本文参考地址

  • Flutter实现类似iOS的模态跳转

    flutter页面跳转默认的动画为: Android:从底部弹出 (iOS - modal)iOS:从右侧弹出 (...

  • iOS常用技巧

    1、系统版本判断 2、iOS 11后获取导航栏和底部高度的正确姿势 3、在iOS中如何正确的实现行间距与行高 1、...

  • 【转载】iOS 模态视图

    iOS 模态视图 概念: ios开发中,在当前视图上再弹出一个视图(模态视图)例如登陆视图,分享视图,注册等等。 ...

  • 用 Swift 架构 iOS 应用的正确姿势

    用 Swift 架构 iOS 应用的正确姿势 用 Swift 架构 iOS 应用的正确姿势

  • 一句话搞定高仿ios底部弹出提示框

    最近项目里面用到了底部的弹出提示框,UI小姐姐本着设计样式还是ios的好看原则。设计了一个ios样式的底部弹出提示...

网友评论

    本文标题:iOS 底部弹出视图正确姿势

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