Неправильная рамка при отклонении модально представленного контроллера представления
Я представляю UIViewController
с использованием настраиваемого перехода и пользовательского UIPresentationController
. Вид контроллера просмотра не охватывает весь экран, поэтому контроллер представления представления все еще отображается.
Затем я представляю экземпляр UIImagePickerController
поверх этого контроллера представления. Проблема в том, что когда я увольняю сборщик изображений, рамка контроллера представления выглядит как весь участок, который я хочу, чтобы покрыть весь экран. Кадр, указанный frameOfPresentedViewInContainerView
в моем пользовательском UIPresentationController
, кажется, полностью игнорируется.
Только если присутствует сборщик изображений с modalPresentationStyle
of UIModalPresentationOverCurrentContext
, мои кадры остаются неповрежденными (что имеет смысл, поскольку вначале не видны представления из иерархии представлений). К сожалению, это не то, что я хочу. Я хочу, чтобы сборщик изображений отображался в полноэкранном режиме, который - по какой-то причине - кажется, испортил мой макет. Что-нибудь, что я могу сделать неправильно или забыть здесь? Любые предложения?
Ответы
Ответ 1
Я попробовал оба упомянутых подхода к оболочке. Один из побочных эффектов использования этого метода обертывания заключается в том, что вращение устройства не проявляется хорошо - введение черных ящиков вокруг представленного представления.
Вместо того, чтобы делать обертку, попробуйте установить modalPresentationStyle
представленного UIImagePickerController
на UIModalPresentationOverFullScreen
. Это означает, что представления под элементом выбора изображений не будут удалены/восстановлены из иерархии представлений во время презентации/увольнения.
Ответ 2
Это ожидается, потому что полноэкранная презентация не восстанавливает исходный кадр, рассчитанный 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
, чтобы вернуть представление оболочки вместо значения по умолчанию - представленное представление контроллера представления. Таким образом, даже если второе представление изменяет рамку обертки, представленный вид контроллера представления не изменится.
Ответ 3
решение erudel не работало для меня, как есть, но добавление другого представления между 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.
Ответ 4
Это сработало для меня, в UIPresentationController
:
override func containerViewWillLayoutSubviews() {
super.containerViewWillLayoutSubviews()
presentedViewController.view.frame = frameOfPresentedViewInContainerView
}
Ответ 5
Я пробовал 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
}
}