自定义带动画效果的模态框

栏目: IOS · 发布时间: 5年前

内容简介:如上图,常见的实现方式是把模态框作为一个View,需要的时候通过动画从底部弹出来。这样做起来很方便,但可扩展性往往不够,弹框的内容可能会是任何控件或者组合。如果弹框是个控制器,扩展性就不会是个问题了。如何根据文本内容的高度设置控制器的frame?

1. 自定义弹框

自定义带动画效果的模态框

如上图,常见的实现方式是把模态框作为一个View,需要的时候通过动画从底部弹出来。这样做起来很方便,但可扩展性往往不够,弹框的内容可能会是任何控件或者组合。如果弹框是个控制器,扩展性就不会是个问题了。

如何根据文本内容的高度设置控制器的frame?

在弹框控制器的构造方法中设置好label的约束,然后在UIPresentationController中重写frameOfPresentedViewInContainerView属性,在其中通过UIView.systemLayoutSizeFitting计算出内容的高度。

这边弹框的半径在presentationTransitionWillBegin中设置。

具体实现 猛击

2. 自定义UIAlertController

按照这个思路,我们可以自定义任何形式的弹框,包括系统的UIAlertController的alert和actionSheet,下图就是自定义了系统的actionSheet。

自定义带动画效果的模态框

与上面自定义弹框不同的,自定义UIAlertController需要把背景颜色设置为透明灰色,这个我们也是在UIPresentationController中设置。

override func presentationTransitionWillBegin() {
    super.presentationTransitionWillBegin()
    
    presentedView?.layer.cornerRadius = 24
    containerView?.backgroundColor = .clear
    
    // 弹框出现的时候设置透明灰度
    if let coordinator = presentingViewController.transitionCoordinator {
        coordinator.animate(alongsideTransition: { [weak self] _ in
            self?.containerView?.backgroundColor = UIColor.black.withAlphaComponent(0.3)
            }, completion: nil)
    }
}
    
override func dismissalTransitionWillBegin() {
    super.dismissalTransitionWillBegin()
    
    // 弹框消失的时候把背景颜色置为clear
    if let coordinator = presentingViewController.transitionCoordinator {
        coordinator.animate(alongsideTransition: { [weak self] _ in
            self?.containerView?.backgroundColor = .clear
            }, completion: nil)
    }
}

这边在自定义UIAlertController的过程中,有个bug。

当点击UIAlertController上的确认按钮跳转到一个新的控制器,然后再返回到当前页面的时候,自定义UIAlertController会出现一闪的情况,可以把PresentationController中所有的代码注释掉就能重复这个bug,造成这种现象的原因是因为,在自定义尺寸的控制器上present一个全屏控制器的时候,系统会自动把当前层级下的自定义尺寸的控制器的View移除掉,当我们对全屏控制器做dismiss操作后又会添加回去。

这个bug的最优解决办法是给UIPresentationController设置一个子类,在子类中添加一个属性保存自定义尺寸的控制器的frame。

class PresentationController: UIPresentationController {
    
    private var calculatedFrameOfPresentedViewInContainerView = CGRect.zero
    private var shouldSetFrameWhenAccessingPresentedView = false
    
    // 如果弹框存在,设置弹框的frame
    override var presentedView: UIView? {
        if shouldSetFrameWhenAccessingPresentedView {
            super.presentedView?.frame = calculatedFrameOfPresentedViewInContainerView
        }
        return super.presentedView
    }
    
    // 弹框存在
    override func presentationTransitionDidEnd(_ completed: Bool) {
        super.presentationTransitionDidEnd(completed)
        shouldSetFrameWhenAccessingPresentedView = completed
    }
    
    // 弹框消失
    override func dismissalTransitionWillBegin() {
        super.dismissalTransitionWillBegin()
        shouldSetFrameWhenAccessingPresentedView = false
    }
    
    // 获取弹框的frame
    override func containerViewDidLayoutSubviews() {
        super.containerViewDidLayoutSubviews()
        calculatedFrameOfPresentedViewInContainerView = frameOfPresentedViewInContainerView
    }
}

具体实现 猛击

更多内容欢迎关注 iOSTips

作者:Dariel

链接:https://www.jianshu.com/p/0635f5b2223b


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

复杂网络理论及其应用

复杂网络理论及其应用

汪小帆、李翔、陈关荣 / 清华大学出版社 / 2006 / 45.00元

国内首部复杂网络专著 【图书目录】 第1章 引论 1.1 引言 1.2 复杂网络研究简史 1.3 基本概念 1.4 本书内容简介 参考文献 第2章 网络拓扑基本模型及其性质 2.1 引言 2.2 规则网络 2.3 随机图 2.4 小世界网络模型 2.5 无标度网络模型 ......一起来看看 《复杂网络理论及其应用》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试