Как представить полумодальный контроллер представления поверх с пользовательскими переходами iOS 7
Как бы я мог представить контроллер "половинного обзора" поверх контроллера основного вида?
Требования: - Представьте второй контроллер вида, который скользит поверх контроллера основного вида. - Контроллер второго вида должен показывать только более половины контроллера основного вида - Контроллер основного вида должен оставаться видимым за контроллером второго вида (прозрачный фон, не показывать черный снизу) - Контроллер второго вида должен анимироваться с анимацией, аналогичной модальной вертикальной обложке, или Пользовательский переход iOS 7 - пользователь по-прежнему может взаимодействовать с кнопками на контроллере основного вида, когда контроллер второго вида активен (т. е. контроллер второго вида не охватывает весь контроллер основного вида). r - Контроллер второго вида имеет собственную сложную логику (не может быть простой вид) - раскадровки, сегы, только iOS 7 - только iPhone, а не iPad.
Я попытался с модальным контроллером представления, но это не позволяет взаимодействие с главным контроллером представления. Может кто-нибудь привести пример того, как сделать это с помощью пользовательского перехода iOS7 или другим методом.
2 ответа
Один из способов сделать это - добавить "полумодальный" контроллер в качестве дочернего контроллера представления и анимировать его представление на месте. В этом примере я создал "полумодальный" контроллер в раскадровке с рамкой, равной половине высоты 4-дюймового экрана iPhone. Вы можете использовать более динамичные методы для учета различных размеров экрана, но это должно помочь вам начать.
@interface ViewController ()
@property (strong,nonatomic) UIViewController *modal;
@end
@implementation ViewController
- (IBAction)toggleHalfModal:(UIButton *)sender {
if (self.childViewControllers.count == 0) {
self.modal = [self.storyboard instantiateViewControllerWithIdentifier:@"HalfModal"];
[self addChildViewController:self.modal];
self.modal.view.frame = CGRectMake(0, 568, 320, 284);
[self.view addSubview:self.modal.view];
[UIView animateWithDuration:1 animations:^{
self.modal.view.frame = CGRectMake(0, 284, 320, 284);;
} completion:^(BOOL finished) {
[self.modal didMoveToParentViewController:self];
}];
}else{
[UIView animateWithDuration:1 animations:^{
self.modal.view.frame = CGRectMake(0, 568, 320, 284);
} completion:^(BOOL finished) {
[self.modal.view removeFromSuperview];
[self.modal removeFromParentViewController];
self.modal = nil;
}];
}
}
Новый способ отображения контроллера на половине экрана — это контроллер собственного стиля ios.
Ниже фрагмент кода поможет вам для обеих версий
controller.modalPresentationStyle = .pageSheet
if #available(iOS 15.0, *) {
if let sheet = controller.sheetPresentationController {
sheet.detents = [.medium()]
}
} else {
controller.modalPresentationStyle = .custom
controller.transitioningDelegate = self
}
self.present(controller, animated: true, completion: nil)
// ПОМЕТКА: - UIViewControllerTransitioningDelegate
extension CPPdfPreviewVC: UIViewControllerTransitioningDelegate {
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
PresentationController(presentedViewController: presented, presenting: presenting)
}
}
и добавьте контроллер презентации, как указано
class PresentationController: UIPresentationController {
let blurEffectView: UIVisualEffectView!
var tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer()
override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) {
let blurEffect = UIBlurEffect(style: .dark)
blurEffectView = UIVisualEffectView(effect: blurEffect)
super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissController))
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.blurEffectView.isUserInteractionEnabled = true
self.blurEffectView.addGestureRecognizer(tapGestureRecognizer)
}
override var frameOfPresentedViewInContainerView: CGRect {
CGRect(origin: CGPoint(x: 0, y: self.containerView!.frame.height * 0.4),
size: CGSize(width: self.containerView!.frame.width, height: self.containerView!.frame.height *
0.6))
}
override func presentationTransitionWillBegin() {
self.blurEffectView.alpha = 0
self.containerView?.addSubview(blurEffectView)
self.presentedViewController.transitionCoordinator?.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) in
self.blurEffectView.alpha = 0.7
}, completion: { (UIViewControllerTransitionCoordinatorContext) in })
}
override func dismissalTransitionWillBegin() {
self.presentedViewController.transitionCoordinator?.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) in
self.blurEffectView.alpha = 0
}, completion: { (UIViewControllerTransitionCoordinatorContext) in
self.blurEffectView.removeFromSuperview()
})
}
override func containerViewWillLayoutSubviews() {
super.containerViewWillLayoutSubviews()
presentedView!.roundCorners([.topLeft, .topRight], radius: 22)
}
override func containerViewDidLayoutSubviews() {
super.containerViewDidLayoutSubviews()
presentedView?.frame = frameOfPresentedViewInContainerView
blurEffectView.frame = containerView!.bounds
}
@objc func dismissController(){
self.presentedViewController.dismiss(animated: true, completion: nil)
}
}
extension UIView {
func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners,
cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
layer.mask = mask
}
}