Skip to content

Commit

Permalink
1. QMUIModalPresentationViewController 增加 3 个属性用于区分当前使用哪种方式显示浮层;
Browse files Browse the repository at this point in the history
2. 修复以 present 方式使用 QMUIModalPresentationViewController 时,进行界面切换后再回来 QMUIModalPresentationViewController,内容不见了
  • Loading branch information
MoLice committed Dec 4, 2017
1 parent 7e8f3e2 commit 2e07871
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 13 deletions.
14 changes: 13 additions & 1 deletion QMUIKit/QMUIComponents/QMUIModalPresentationViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,20 @@ typedef NS_ENUM(NSUInteger, QMUIModalPresentationAnimationStyle) {
*
* 支持 3 种方式显示浮层:
*
* 1. **推荐** 新起一个 `UIWindow` 盖在当前界面上,将 `QMUIModalPresentationViewController` 以 `rootViewController` 的形式显示出来,可通过 `supportedOrientationMask` 支持横竖屏,不支持在浮层不消失的情况下做界面切换(因为 window 会把背后的 controller 盖住,看不到界面切换)
* 1. **推荐** 新起一个 `UIWindow` 盖在当前界面上,将 `QMUIModalPresentationViewController` 以 `rootViewController` 的形式显示出来,可通过 `supportedOrientationMask` 支持横竖屏,不支持在浮层不消失的情况下做界面切换(因为 window 会把背后的 controller 盖住,看不到界面切换)。
* 可通过 shownInWindowMode 属性来判断是否在用这种方式显示。
* @code
* [modalPresentationViewController showWithAnimated:YES completion:nil];
* @endcode
*
* 2. 使用系统接口来显示,支持界面切换,**注意** 使用这种方法必定只能以动画的形式来显示浮层,无法以无动画的形式来显示,并且 `animated` 参数必须为 `NO`。可通过 `supportedOrientationMask` 支持横竖屏。
* 可通过 shownInPresentMode 属性来判断是否在用这种方式显示。
* @code
* [self presentViewController:modalPresentationViewController animated:NO completion:nil];
* @endcode
*
* 3. 将浮层作为一个 subview 添加到 `superview` 上,从而能够实现在浮层不消失的情况下进行界面切换,但需要 `superview` 自行管理浮层的大小和横竖屏旋转,而且 `QMUIModalPresentationViewController` 不能用局部变量来保存,会在显示后被释放,需要自行 retain。横竖屏跟随当前界面的设置。
* 可通过 shownInSubviewMode 属性来判断是否在用这种方式显示。
* @code
* self.modalPresentationViewController.view.frame = CGRectMake(50, 50, 100, 100);
* [self.view addSubview:self.modalPresentationViewController.view];
Expand Down Expand Up @@ -164,6 +167,15 @@ typedef NS_ENUM(NSUInteger, QMUIModalPresentationAnimationStyle) {
*/
@property(nonatomic, assign) QMUIModalPresentationAnimationStyle animationStyle UI_APPEARANCE_SELECTOR;

/// 是否以 UIWindow 的方式显示,建议在显示之后才使用,否则可能不准确。
@property(nonatomic, assign, readonly, getter=isShownInWindowMode) BOOL shownInWindowMode;

/// 是否以系统 present 的方式显示,建议在显示之后才使用,否则可能不准确。
@property(nonatomic, assign, readonly, getter=isShownInPresentMode) BOOL shownInPresentMode;

/// 是否以 addSubview 的方式显示,建议在显示之后才使用,否则可能不准确。
@property(nonatomic, assign, readonly, getter=isShownInSubviewMode) BOOL shownInSubviewMode;

/**
* 管理自定义的浮层布局,将会在浮层显示前、控件的容器大小发生变化时(例如横竖屏、来电状态栏)被调用
* @arg containerBounds 浮层所在的父容器的大小,也即`self.view.bounds`
Expand Down
32 changes: 20 additions & 12 deletions QMUIKit/QMUIComponents/QMUIModalPresentationViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ - (void)viewDidLayoutSubviews {

- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (self.containerWindow) {
if (self.shownInWindowMode) {
// 只有使用showWithAnimated:completion:显示出来的浮层,才需要修改之前就记住的animated的值
animated = self.appearAnimated;
}
Expand Down Expand Up @@ -194,7 +194,7 @@ - (void)viewWillDisappear:(BOOL)animated {
}

[super viewWillDisappear:animated];
if (self.containerWindow) {
if (self.shownInWindowMode) {
animated = self.disappearAnimated;
}

Expand All @@ -204,7 +204,7 @@ - (void)viewWillDisappear:(BOOL)animated {

void (^didHiddenCompletion)(BOOL finished) = ^(BOOL finished) {

if (self.containerWindow) {
if (self.shownInWindowMode) {
// 恢复 keyWindow 之前做一下检查,避免这个问题 https://github.com/QMUI/QMUI_iOS/issues/90
if ([[UIApplication sharedApplication] keyWindow] == self.containerWindow) {
[self.previousKeyWindow makeKeyWindow];
Expand All @@ -215,14 +215,13 @@ - (void)viewWillDisappear:(BOOL)animated {
[self endAppearanceTransition];
}

if (self.view.superview) {
if (self.shownInSubviewMode) {
// 这句是给addSubview的形式显示的情况下使用,但会触发第二次viewWillDisappear:,所以要搭配self.hasAlreadyViewWillDisappear使用
[self.view removeFromSuperview];
self.hasAlreadyViewWillDisappear = NO;
}

[self.contentView removeFromSuperview];
self.contentView = nil;
if (self.contentViewController) {
[self.contentViewController endAppearanceTransition];
}
Expand Down Expand Up @@ -321,23 +320,20 @@ - (void)handleDimmingViewTapGestureRecognizer:(UITapGestureRecognizer *)tapGestu
return;
}

if (self.containerWindow) {
// 认为是以 UIWindow 的形式显示出来
if (self.shownInWindowMode) {
__weak __typeof(self)weakSelf = self;
[self hideWithAnimated:YES completion:^(BOOL finished) {
if (weakSelf.didHideByDimmingViewTappedBlock) {
weakSelf.didHideByDimmingViewTappedBlock();
}
}];
} else if (self.presentingViewController && self.presentingViewController.presentedViewController == self) {
// 认为是以 presentViewController 的形式显示出来
} else if (self.shownInPresentMode) {
[self dismissViewControllerAnimated:YES completion:^{
if (self.didHideByDimmingViewTappedBlock) {
self.didHideByDimmingViewTappedBlock();
}
}];
} else {
// 认为是 addSubview 的形式显示出来
} else if (self.shownInSubviewMode) {
__weak __typeof(self)weakSelf = self;
[self hideInView:self.view.superview animated:YES completion:^(BOOL finished) {
if (weakSelf.didHideByDimmingViewTappedBlock) {
Expand Down Expand Up @@ -457,7 +453,7 @@ - (void)hideWithAnimated:(BOOL)animated completion:(void (^)(BOOL))completion {
}

// window模式下,通过手动触发viewWillDisappear:来做界面消失的逻辑
if (self.containerWindow) {
if (self.shownInWindowMode) {
[self beginAppearanceTransition:NO animated:animated];
}
}
Expand Down Expand Up @@ -495,6 +491,18 @@ - (CGRect)contentViewFrameForShowing {
return contentViewFrame;
}

- (BOOL)isShownInWindowMode {
return !!self.containerWindow;
}

- (BOOL)isShownInPresentMode {
return !self.shownInWindowMode && self.presentingViewController && self.presentingViewController.presentedViewController == self;
}

- (BOOL)isShownInSubviewMode {
return !self.shownInPresentMode && self.view.superview;
}

#pragma mark - Keyboard

- (void)handleKeyboardWillShow:(NSNotification *)notification {
Expand Down

0 comments on commit 2e07871

Please sign in to comment.