QMUIModalPresentationViewController
@interface QMUIModalPresentationViewController : UIViewController
一个提供通用的弹出浮层功能的控件,可以将任意UIView
或UIViewController
以浮层的形式显示出来并自动布局。
支持 3 种方式显示浮层:
推荐 新起一个
UIWindow
盖在当前界面上,将QMUIModalPresentationViewController
以rootViewController
的形式显示出来,可通过supportedOrientationMask
支持横竖屏,不支持在浮层不消失的情况下做界面切换(因为 window 会把背后的 controller 盖住,看不到界面切换)。 可通过 shownInWindowMode 属性来判断是否在用这种方式显示。[modalPresentationViewController showWithAnimated:YES completion:nil];
使用系统接口来显示,支持界面切换,注意 使用这种方法必定只能以动画的形式来显示浮层,无法以无动画的形式来显示,并且
animated
参数必须为NO
。可通过supportedOrientationMask
支持横竖屏。 可通过 shownInPresentedMode 属性来判断是否在用这种方式显示。[self presentViewController:modalPresentationViewController animated:NO completion:nil];
将浮层作为一个 subview 添加到
superview
上,从而能够实现在浮层不消失的情况下进行界面切换,但需要superview
自行管理浮层的大小和横竖屏旋转,而且QMUIModalPresentationViewController
不能用局部变量来保存,会在显示后被释放,需要自行 retain。横竖屏跟随当前界面的设置。 可通过 shownInSubviewMode 属性来判断是否在用这种方式显示。self.modalPresentationViewController.view.frame = CGRectMake(50, 50, 100, 100); [self.view addSubview:self.modalPresentationViewController.view];
默认的布局会将浮层居中显示,浮层的大小可通过接口控制:
- 如果是用
contentViewController
,则可通过preferredContentSizeInModalPresentationViewController:keyboardHeight:limitSize:
来设置 - 如果使用
contentView
,或者使用contentViewController
但没实现preferredContentSizeInModalPresentationViewController:keyboardHeight:limitSize:
,则调用contentView
的sizeThatFits:
方法获取大小。 - 浮层大小会受
maximumContentViewWidth
属性的限制,以及contentViewMargins
属性的影响。
通过layoutBlock
、showingAnimation
、hidingAnimation
可设置自定义的布局、打开及隐藏的动画,并允许你适配键盘升起时的场景。
默认提供背景遮罩dimmingView
,你也可以使用自己的遮罩 view。
默认提供多种显示动画,可通过 animationStyle
来设置。
Warning
如果使用者retain了modalPresentationViewController,注意应该在hideWithAnimated:completion:
里release
See
QMUIAlertController
See
QMUIDialogViewController
See
QMUIMoreOperationController
-
Undocumented
Declaration
Objective-C
@property(nullable, nonatomic, weak) IBOutlet id<QMUIModalPresentationViewControllerDelegate> delegate
Swift
@IBOutlet weak var delegate: QMUIModalPresentationViewControllerDelegate? { get set }
-
要被弹出的浮层
Warning
当设置了contentView
时,不要再设置contentViewController
Declaration
Objective-C
@property (nonatomic, strong, nullable) UIView *contentView;
Swift
@IBOutlet var contentView: UIView? { get set }
-
要被弹出的浮层,适用于浮层以UIViewController的形式来管理的情况。
Warning
当设置了contentViewController
时,contentViewController.view
会被当成contentView
使用,因此不要再自行设置contentView
Warning
注意contentViewController
是强引用,容易导致循环引用,使用时请注意Declaration
Objective-C
@property (nonatomic, strong, nullable) UIViewController<QMUIModalPresentationContentViewControllerProtocol> *contentViewController;
Swift
@IBOutlet var contentViewController: (UIViewController & QMUIModalPresentationContentViewControllerProtocol)? { get set }
-
设置
contentView
布局时与外容器的间距,默认为(20, 20, 20, 20)Warning
当设置了layoutBlock
属性时,此属性不生效Declaration
Objective-C
@property (nonatomic) UIEdgeInsets contentViewMargins;
Swift
var contentViewMargins: UIEdgeInsets { get set }
-
限制
contentView
布局时的最大宽度,默认为 CGFLOAT_MAX,也即无限制。Warning
当设置了layoutBlock
属性时,此属性不生效Declaration
Objective-C
@property (nonatomic) CGFloat maximumContentViewWidth;
Swift
var maximumContentViewWidth: CGFloat { get set }
-
背景遮罩,默认为一个普通的
UIView
,背景色为UIColorMask
,可设置为自己的view,注意dimmingView
的大小将会盖满整个控件。QMUIModalPresentationViewController
会自动给自定义的dimmingView
添加手势以实现点击遮罩隐藏浮层。Declaration
Objective-C
@property (nonatomic, strong, nullable) UIView *dimmingView;
Swift
@IBOutlet var dimmingView: UIView? { get set }
-
由于点击遮罩导致浮层即将被隐藏的回调
Declaration
Objective-C
@property (nonatomic, copy, nullable) void (^)(void) willHideByDimmingViewTappedBlock;
Swift
var willHideByDimmingViewTappedBlock: (() -> Void)? { get set }
-
由于点击遮罩导致浮层被隐藏后的回调(区分于
hideWithAnimated:completion:
里的completion,这里是特地用于点击遮罩的情况)Declaration
Objective-C
@property (nonatomic, copy, nullable) void (^)(void) didHideByDimmingViewTappedBlock;
Swift
var didHideByDimmingViewTappedBlock: (() -> Void)? { get set }
-
控制当前是否以模态的形式存在。如果以模态的形式存在,则点击空白区域不会隐藏浮层。
默认为NO,也即点击空白区域将会自动隐藏浮层。
Declaration
Objective-C
@property (nonatomic, getter=isModal) BOOL modal;
Swift
var isModal: Bool { get set }
-
标志当前浮层的显示/隐藏状态,默认为NO。
Declaration
Objective-C
@property (nonatomic, readonly, getter=isVisible) BOOL visible;
Swift
var isVisible: Bool { get }
-
修改当前界面要支持的横竖屏方向,默认为 SupportedOrientationMask。
Declaration
Objective-C
@property (nonatomic) UIInterfaceOrientationMask supportedOrientationMask;
Swift
var supportedOrientationMask: UIInterfaceOrientationMask { get set }
-
设置要使用的显示/隐藏动画的类型,默认为
QMUIModalPresentationAnimationStyleFade
。Warning
当使用了showingAnimation
和hidingAnimation
时,该属性无效Declaration
Objective-C
@property (nonatomic) QMUIModalPresentationAnimationStyle animationStyle;
Swift
var animationStyle: QMUIModalPresentationAnimationStyle { get set }
-
是否以 UIWindow 的方式显示,建议在显示之后才使用,否则可能不准确。
Declaration
Objective-C
@property (nonatomic, assign, unsafe_unretained, readonly, getter=isShownInWindowMode) BOOL shownInWindowMode;
Swift
var isShownInWindowMode: Bool { get }
-
是否以系统 present 的方式显示,建议在显示之后才使用,否则可能不准确。
Declaration
Objective-C
@property (nonatomic, assign, unsafe_unretained, readonly, getter=isShownInPresentedMode) BOOL shownInPresentedMode;
Swift
var isShownInPresentedMode: Bool { get }
-
是否以 addSubview 的方式显示,建议在显示之后才使用,否则可能不准确。
Declaration
Objective-C
@property (nonatomic, assign, unsafe_unretained, readonly, getter=isShownInSubviewMode) BOOL shownInSubviewMode;
Swift
var isShownInSubviewMode: Bool { get }
-
只响应 modal.view 上的 view 所产生的键盘事件,当为 NO 时,只要有键盘事件产生,浮层都会重新计算布局。 默认为 YES,也即只响应浮层上的 view 引起的键盘位置变化。
Declaration
Objective-C
@property (nonatomic) BOOL onlyRespondsToKeyboardEventFromDescendantViews;
Swift
var onlyRespondsToKeyboardEventFromDescendantViews: Bool { get set }
-
管理自定义的浮层布局,将会在浮层显示前、控件的容器大小发生变化时(例如横竖屏、来电状态栏)被调用,请在 block 内主动为 view 设置期望的 frame,设置时建议用 qmui_frameApplyTransform 取代 setFrame:,否则在有键盘的情况下,显隐动画可能有错。 @arg containerBounds 浮层所在的父容器的大小,也即
self.view.bounds
@arg keyboardHeight 键盘在当前界面里的高度,若无键盘,则为0 @arg contentViewDefaultFrame 不使用自定义布局的情况下的默认布局,会受contentViewMargins
、maximumContentViewWidth
、contentView sizeThatFits:
的影响See
contentViewMarginsSee
maximumContentViewWidthDeclaration
Objective-C
@property (nonatomic, copy, nullable) void (^) (CGRect, CGFloat, CGRect) layoutBlock;
Swift
var layoutBlock: ((CGRect, CGFloat, CGRect) -> Void)? { get set }
-
管理自定义的显示动画,需要管理的对象包括
contentView
和dimmingView
,在showingAnimation
被调用前,contentView
已被添加到界面上。若使用了layoutBlock
,则会先调用layoutBlock
,再调用showingAnimation
。在动画结束后,必须调用参数里的completion
block。 @arg dimmingView 背景遮罩的View,请自行设置显示遮罩的动画 @arg containerBounds 浮层所在的父容器的大小,也即self.view.bounds
@arg keyboardHeight 键盘在当前界面里的高度,若无键盘,则为0 @arg contentViewFrame 动画执行完后contentView
的最终frame,若使用了layoutBlock
,则也即layoutBlock
计算完后的frame @arg completion 动画结束后给到modalController的回调,modalController会在这个回调里做一些状态设置,务必调用。Declaration
Objective-C
@property (nonatomic, copy, nullable) void (^) (UIView *_Nullable, CGRect, CGFloat, CGRect, void (^_Nonnull)(BOOL)) showingAnimation;
Swift
var showingAnimation: ((UIView?, CGRect, CGFloat, CGRect, @escaping (Bool) -> Void) -> Void)? { get set }
-
管理自定义的隐藏动画,需要管理的对象包括
contentView
和dimmingView
,在动画结束后,必须调用参数里的completion
block。 @arg dimmingView 背景遮罩的View,请自行设置隐藏遮罩的动画 @arg containerBounds 浮层所在的父容器的大小,也即self.view.bounds
@arg keyboardHeight 键盘在当前界面里的高度,若无键盘,则为0 @arg completion 动画结束后给到modalController的回调,modalController会在这个回调里做一些清理工作,务必调用Declaration
Objective-C
@property (nonatomic, copy, nullable) void (^) (UIView *_Nullable, CGRect, CGFloat, void (^_Nonnull)(BOOL)) hidingAnimation;
Swift
var hidingAnimation: ((UIView?, CGRect, CGFloat, @escaping (Bool) -> Void) -> Void)? { get set }
-
请求重新计算浮层的布局
Declaration
Objective-C
- (void)updateLayout;
Swift
func updateLayout()
-
将浮层以 UIWindow 的方式显示出来
Declaration
Objective-C
- (void)showWithAnimated:(BOOL)animated completion:(void (^_Nullable)(BOOL))completion;
Swift
func showWith(animated: Bool, completion: ((Bool) -> Void)? = nil)
Parameters
animated
是否以动画的形式显示
completion
显示动画结束后的回调
-
将浮层隐藏掉
Warning
这里的completion
只会在你显式调用hideWithAnimated:completion:
方法来隐藏浮层时会被调用,如果你通过点击dimmingView
来触发hideWithAnimated:completion:
,则completion是不会被调用的,那种情况下如果你要在浮层隐藏后做一些事情,请使用delegate
提供的didHideModalPresentationViewController:
方法。Declaration
Objective-C
- (void)hideWithAnimated:(BOOL)animated completion:(void (^_Nullable)(BOOL))completion;
Swift
func hideWith(animated: Bool, completion: ((Bool) -> Void)? = nil)
Parameters
animated
是否以动画的形式隐藏
completion
隐藏动画结束后的回调
-
将浮层以 addSubview 的方式显示出来
Declaration
Objective-C
- (void)showInView:(nonnull UIView *)view animated:(BOOL)animated completion:(void (^_Nullable)(BOOL))completion;
Swift
func show(in view: UIView, animated: Bool, completion: ((Bool) -> Void)? = nil)
Parameters
view
要显示到哪个 view 上
animated
是否以动画的形式显示
completion
显示动画结束后的回调
-
将某个 view 上显示的浮层隐藏掉
Warning
这里的completion
只会在你显式调用hideInView:animated:completion:
方法来隐藏浮层时会被调用,如果你通过点击dimmingView
来触发hideInView:animated:completion:
,则completion是不会被调用的,那种情况下如果你要在浮层隐藏后做一些事情,请使用delegate
提供的didHideModalPresentationViewController:
方法。Declaration
Objective-C
- (void)hideInView:(nonnull UIView *)view animated:(BOOL)animated completion:(void (^_Nullable)(BOOL))completion;
Swift
func hide(in view: UIView, animated: Bool, completion: ((Bool) -> Void)? = nil)
Parameters
view
要隐藏哪个 view 上的浮层
animated
是否以动画的形式隐藏
completion
隐藏动画结束后的回调
-
判断当前App里是否有modalViewController正在显示(存在modalViewController但不可见的时候,也视为不存在)
Declaration
Objective-C
+ (BOOL)isAnyModalPresentationViewControllerVisible;
Swift
class func isAnyModalPresentationViewControllerVisible() -> Bool
Return Value
只要存在正在显示的浮层,则返回YES,否则返回NO
-
把所有正在显示的并且允许被隐藏的modalViewController都隐藏掉
See
shouldHideModalPresentationViewController:See
QMUIModalPresentationComponentProtocolWarning
当要隐藏一个 modalPresentationViewController 时,如果这个 modal 有实现 QMUIModalPresentationComponentProtocol 协议,则会调用它的 hideModalPresentationComponent 方法来隐藏,否则直接用 QMUIModalPresentationViewController 的 hideWithAnimated:completion:Declaration
Objective-C
+ (BOOL)hideAllVisibleModalPresentationViewControllerIfCan;
Swift
class func hideAllVisibleModalPresentationViewControllerIfCan() -> Bool
Return Value
只要遇到一个正在显示的并且不能被隐藏的浮层,就会返回NO,否则都返回YES,表示成功隐藏掉所有可视浮层
-
Undocumented
Declaration
Objective-C
+ (instancetype)appearance;
Swift
class func appearance() -> Self