20

我正在展示一个UIViewController使用自定义过渡和一个自定义的UIPresentationController. 视图控制器的视图不会覆盖整个屏幕,因此呈现的视图控制器仍然可见。

UIImagePickerController接下来,我在这个视图控制器上展示一个实例。问题是当我关闭图像选择器时,呈现视图控制器的框架会覆盖整个屏幕,而不仅仅是我希望它覆盖的部分。frameOfPresentedViewInContainerView我的自定义中指定的框架UIPresentationController似乎完全被忽略了。

仅当带有我的帧的图像选择器modalPresentationStyle保持UIModalPresentationOverCurrentContext完整时(这是有道理的,因为首先没有从视图层次结构中删除视图)。不幸的是,这不是我想要的。我希望图像选择器全屏显示,这 - 无论出于何种原因 - 似乎都弄乱了我的布局。有什么我可能做错或忘记的吗?有什么建议么?

4

5 回答 5

17

我尝试了提到的两种包装方法。使用这种包装方法的一个副作用是设备旋转不能很好地显示 - 在呈现的视图周围引入黑框。

不要使用包装技巧,而是尝试将modalPresentationStyle呈现的设置UIImagePickerControllerUIModalPresentationOverFullScreen. 这意味着图像选择器下方的视图在演示/关闭期间不会从视图层次结构中删除/恢复。

于 2017-01-22T04:43:52.397 回答
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以返回包装视图而不是默认值 - 呈现的视图控制器的视图。这样,即使第二个呈现修改了包装器的框架,呈现的视图控制器的视图也不会改变。

于 2016-06-23T04:19:05.657 回答
3

这对我有用,在UIPresentationController

override func containerViewWillLayoutSubviews() {

     super.containerViewWillLayoutSubviews()
     presentedViewController.view.frame = frameOfPresentedViewInContainerView
}
于 2017-05-30T12:42:04.983 回答
2

erudel 的解决方案对我不起作用,但在两者之间添加另一个视图wrapperViewpresentedViewController.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 上对此进行了测试。

于 2016-08-08T14:05:27.400 回答
2

我试过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
        }
    }
于 2017-11-04T19:50:41.680 回答