我使用自定义转换和自定义UIViewController
呈现UIPresentationController
。视图控制器的视图不会覆盖整个屏幕,因此呈现视图控制器仍然可见。
接下来,我在此视图控制器的顶部显示UIImagePickerController
的实例。问题是,当我关闭图像选择器时,呈现视图控制器的框架覆盖整个屏幕而不是我想要它覆盖的部分。 <{1}}在我的自定义frameOfPresentedViewInContainerView
中指定的框架似乎完全被忽略了。
仅当存在UIPresentationController
modalPresentationStyle
UIModalPresentationOverCurrentContext
我的帧的图像选择器保持不变时(这是有意义的,因为首先不会从视图层次结构中删除视图)。不幸的是,这不是我想要的。我希望图像选择器全屏显示,无论出于何种原因,它似乎搞乱了我的布局。我可能做错了什么或遗忘在这里?有什么建议吗?
答案 0 :(得分:14)
我尝试了两种提到的包装方法。使用这种包装方法的一个副作用是设备旋转不能很好地显示 - 在呈现的视图周围引入黑框。
尝试将呈现的modalPresentationStyle
的{{1}}设置为UIImagePickerController
,而不是执行换行技巧。这意味着在呈现/解雇期间,图像选择器下面的视图不会从视图层次结构中删除/恢复。
答案 1 :(得分:4)
这是预期的,因为全屏演示文稿不会恢复由frameOfPresentedViewInContainerView
计算的原始帧。
修复此问题的推荐方法是创建一个包装器视图,您将在其中插入显示的视图控制器视图。以下是自定义演示控制器的相关代码:
- (void)presentationTransitionWillBegin {
// wrapper is a property defined in the custom presentation controller.
self.wrapper = [UIView new];
[self.wrapper addSubview:self.presentedViewController.view];
}
- (CGRect)frameOfPresentedViewInContainerView {
CGRect result = self.containerView.frame;
// In this example we are doing a half-modal presentation
CGFloat height = result.size.height/2;
result.origin.y = height;
result.size.height = height;
return result;
}
- (UIView *)presentedView {
return self.wrapper;
}
- (BOOL)shouldPresentInFullscreen {
return NO;
}
- (void)containerViewWillLayoutSubviews {
self.wrapper.frame = self.containerView.frame;
self.presentedViewController.view.frame = [self frameOfPresentedViewInContainerView];
}
请注意,我们覆盖presentedView
以返回包装器视图而不是默认值 - 呈现的视图控制器视图。这样,即使第二个表示修改了包装器的帧,呈现的视图控制器的视图也不会改变。
答案 2 :(得分:2)
erudel's solution不能按原样为我工作,但在wrapperView
和presentedViewController.view
之间添加另一个视图可以解决问题(我不明白为什么):
- (instancetype)initWithPresentedViewController:(UIViewController *)presentedViewController
presentingViewController:(UIViewController *)presentingViewController {
if (self = [super initWithPresentedViewController:presentedViewController
presentingViewController:presentingViewController]) {
_wrapperView = [[UIView alloc] init];
_wrapperView2 = [[UIView alloc] init]; // <- new view
}
return self;
}
- (CGRect)frameOfPresentedViewInContainerView {
return self.containerView.bounds;
}
- (UIView *)presentedView {
return self.wrapperView;
}
- (BOOL)shouldPresentInFullscreen {
return NO;
}
- (void)containerViewWillLayoutSubviews {
self.wrapperView.frame = self.containerView.frame;
self.wrapperView2.frame = /* your custom frame goes here */;
self.presentedViewController.view.frame = self.wrapperView2.bounds;
}
- (void)presentationTransitionWillBegin {
[self.wrapperView addSubview:self.wrapperView2];
[self.wrapperView2 addSubview:self.presentedViewController.view];
// Set up a dimming view, etc
}
在iOS 9.3上测试过。
答案 3 :(得分:1)
这对我有用UIPresentationController
:
override func containerViewWillLayoutSubviews() {
super.containerViewWillLayoutSubviews()
presentedViewController.view.frame = frameOfPresentedViewInContainerView
}
答案 4 :(得分:1)
我尝试了containerViewWillLayoutSubviews
,但它并不是很有效。如果可能的话,我想避免额外的包装器视图。我想出了使用presentedView
修正视图框架的策略。此外,我能够删除containerViewWillLayoutSubviews
。 forceFrame
已针对我们的特定用例进行了调整。 presentedFrame
由我们的自定义动画师设置。
class CustomModalPresentationController: UIPresentationController {
var presentedFrame = CGRect.zero
var forceFrame = false
override func dismissalTransitionWillBegin() {
forceFrame = false
}
override func presentationTransitionDidEnd(_ completed: Bool) {
forceFrame = true
}
override var presentedView: UIView? {
if forceFrame {
presentedViewController.view.frame = presentedFrame
}
return presentedViewController.view
}
override var frameOfPresentedViewInContainerView: CGRect {
return presentedFrame
}
}