IOS: Modal ViewController с прозрачным фоном

Я пытаюсь представить контроллер представления по модулю с прозрачным фоном. Моя цель - одновременно отображать представление представления и представления диспетчеров представлений. Проблема в том, что когда анимация представления заканчивается, представление диспетчера представления представления исчезает.

- (IBAction)pushModalViewControllerButtonPressed:(id)sender
{
    ModalViewController *modalVC = [[ModalViewController alloc] init];
    [self presentViewController:modalVC animated:YES completion:nil];
}

Я знаю, что могу просто добавить представление в качестве подзаголовка, но по какой-то причине я бы хотел избежать этого решения. Как я могу это исправить?

Ответ 1

Этот следующий код работает только на iPad.

self.view.backgroundColor = [UIColor clearColor];
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentModalViewController:modalVC animated:YES];

Я бы добавил с дополнительным представлением.

Вот очень хорошая дискуссия. Посмотрите на комментарии конкретно. Не только ответ.

Модальный вид

Если бы я был вами, я бы этого не сделал. Я бы добавил суб-представление и сделал это. Кажется, мне лучше контролировать ситуацию.

РЕДАКТИРОВАТЬ:

Как уже упоминал Павел Линсай, с iOS 8 все, что нужно, это UIModalPresentationOverFullScreen для представленного модального презентационного элемента ViewController. Это также будет охватывать кнопки navigationBar и tabBar.

Ответ 2

Для тех, кто пытается заставить это работать в iOS 8, "одобренный Apple" способ отображать прозрачный контроллер модального представления - это установить modalPresentationStyle на представленном контроллере на UIModalPresentationOverCurrentContext.

Это можно сделать в коде или установить свойства segue в раскадровке.

Из документации UIViewController:

UIModalPresentationOverCurrentContext

Стиль презентации, в котором содержимое отображается только на родительского контроля. Представления ниже представленного содержимое не удаляется из иерархии представлений, когда презентация отделки. Поэтому, если представленный контроллер представления не заполняет экран с непрозрачным контентом, основное содержание показывает через.

При представлении контроллера представления в popover эта презентация стиль поддерживается только в том случае, если стиль перехода UIModalTransitionStyleCoverVertical. Попытка использовать другое переходный стиль вызывает исключение. Однако вы можете использовать другие стили перехода (за исключением частичного перехода с поворотом), если родительский контроллер просмотра не находится в popover.

Доступно в iOS 8.0 и более поздних версиях.

https://developer.apple.com/documentation/uikit/uiviewcontroller

Видеоролик "Просмотр контроллеров в iOS 8" от WWDC 2014 подробно рассматривается в этой статье.

Примечание:

  • Обязательно дайте представленному контроллеру представления четкий цвет фона, чтобы он не был действительно прозрачным!
  • Вы должны установить это перед представлением, т.е. установка этого параметра в viewDidLoad представленногоViewController не повлияет на

Ответ 3

В iOS 8.0 и выше это можно сделать, установив свойство modalPresentationStyle на UIModalPresentationOverCurrentContext

//Set property **definesPresentationContext** YES to avoid presenting over presenting-viewController navigation bar

self.definesPresentationContext = YES; //self is presenting view controller
presentedController.view.backgroundColor = [YOUR_COLOR with alpha OR clearColor]
presentedController.modalPresentationStyle = UIModalPresentationOverCurrentContext;

[self presentViewController:presentedController animated:YES completion:nil];

See Image Attached

Ответ 4

Этот код отлично работает на iPhone под iOS6 и iOS7:

presentedVC.view.backgroundColor = YOUR_COLOR; // can be with 'alpha'
presentingVC.modalPresentationStyle = UIModalPresentationCurrentContext;
[presentingVC presentViewController:presentedVC animated:YES completion:NULL];

В этом случае вы пропускаете слайд-анимацию. Чтобы сохранить анимацию, вы по-прежнему можете использовать следующее "неэлесное" расширение:

[presentingVC presentViewController:presentedVC animated:YES completion:^{
    [presentedVC dismissViewControllerAnimated:NO completion:^{
        presentingVC.modalPresentationStyle = UIModalPresentationCurrentContext;
        [presentingVC presentViewController:presentedVC animated:NO completion:NULL];
    }];
}];

Если наше представление V находится внутри UINavigationController или UITabbarController, вам необходимо работать с этими контроллерами как представляющие VC.

Кроме того, в iOS7 вы можете реализовать пользовательскую переходную анимацию с использованием протокола UIViewControllerTransitioningDelegate. Конечно, в этом случае вы можете получить прозрачный фон

@interface ModalViewController : UIViewController <UIViewControllerTransitioningDelegate>

Сначала перед представлением вам нужно установить modalPresentationStyle

modalViewController.modalPresentationStyle = UIModalPresentationCustom;

Затем вам нужно реализовать два метода протокола

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
    CustomAnimatedTransitioning *transitioning = [CustomAnimatedTransitioning new];
    transitioning.presenting = YES;
    return transitioning;
}

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
    CustomAnimatedTransitioning * transitioning = [CustomAnimatedTransitioning new];
    transitioning.presenting = NO;
    return transitioning;
}

Последнее, что нужно определить в пользовательском переходе в классе CustomAnimatedTransitioning

@interface CustomAnimatedTransitioning : NSObject <UIViewControllerAnimatedTransitioning>
@property (nonatomic) BOOL presenting;
@end

@implementation CurrentContextTransitionAnimator

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext 
{
    return 0.25;
}

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext 
{
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

    if (self.presenting) {
        // custom presenting animation
    }
    else {
        // custom dismissing animation
    }
}

Ответ 5

Я немного потрудился с помощью Interface Builder XCode 7, чтобы установить стиль презентации, как предлагал @VenuGopalTewari. В этой версии, по-видимому, нет режима отображения Over Current Context или Over Full Screen для сеанса. Таким образом, чтобы заставить его работать, я устанавливаю режим Default:

введите описание изображения здесь с введите описание изображения здесь

Кроме того, я установил режим презентации модально представленного контроллера представления на Over Full Screen:

введите описание изображения здесь

Ответ 6

Создайте segue для отображения модально и установите свойство Presentation этого сегмента в текущий контекст он будет работать на 100%

enter image description here

Ответ 7

PresentViewController с прозрачным фоном - в iOS 8 и iOS 9

MYViewController *myVC = [self.storyboard   instantiateViewControllerWithIdentifier:@"MYViewController"];
    myVC.providesPresentationContextTransitionStyle = YES;
    myVC.definesPresentationContext = YES;
    [myVC setModalPresentationStyle:UIModalPresentationOverCurrentContext];
    [self.navigationController presentViewController:myVC animated:YES completion:nil];

И в MYViewController установите цвет фона черный и уменьшите непрозрачность

Ответ 8

Это немного хакерский способ, но для меня этот код работает (iOS 6):

AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];

[self presentViewController:self.signInViewController animated:YES completion:^{
    [self.signInViewController dismissViewControllerAnimated:NO completion:^{
        appDelegate.window.rootViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
        [self presentViewController:self.signInViewController animated:NO completion:nil];
        appDelegate.window.rootViewController.modalPresentationStyle = UIModalPresentationFullScreen;

    }];
}];

Этот код работает и на iPhone

Ответ 9

Эта категория работала для меня (ios 7, 8 и 9)

H файл

@interface UIViewController (navigation)
- (void) presentTransparentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion;
@end

M файл

@implementation UIViewController (navigation)
- (void)presentTransparentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion
{
    if(SYSTEM_VERSION_LESS_THAN(@"8.0")) {
        [self presentIOS7TransparentController:viewControllerToPresent withCompletion:completion];

    }else{
        viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverCurrentContext;
         [self presentViewController:viewControllerToPresent animated:YES completion:completion];
    }
}
-(void)presentIOS7TransparentController:(UIViewController *)viewControllerToPresent withCompletion:(void(^)(void))completion
{
    UIViewController *presentingVC = self;
    UIViewController *root = self;
    while (root.parentViewController) {
        root = root.parentViewController;
    }
    UIModalPresentationStyle orginalStyle = root.modalPresentationStyle;
    root.modalPresentationStyle = UIModalPresentationCurrentContext;
    [presentingVC presentViewController:viewControllerToPresent animated:YES completion:^{
        root.modalPresentationStyle = orginalStyle;
    }];
}
@end

Ответ 10

Я добавил эти три строки в методе init в представленном контроллере представления и работает как шарм:

self.providesPresentationContextTransitionStyle = YES;
self.definesPresentationContext = YES;
[self setModalPresentationStyle:UIModalPresentationOverCurrentContext];

EDIT (работает на iOS 9.3):

self.modalPresentationStyle = UIModalPresentationOverFullScreen;

Согласно документации:

UIModalPresentationOverFullScreen Стиль представления представления, в котором представленный вид охватывает экран. Представления, находящиеся под представленным контентом, не удаляются из иерархии представлений, когда заканчивается презентация. Поэтому, если представленный контроллер представления не заполняет экран непрозрачным контентом, содержимое содержимого отображается.

Доступно в iOS 8.0 и более поздних версиях.

Ответ 11

Если вы используете раскадровку, вы можете выполнить этот шаг:

  1. Добавьте контроллер представления (V2), настройте пользовательский интерфейс так, как вы этого хотите
  • добавить UIView - установить фон черный и непрозрачность до 0,5
  • добавьте еще один UIView (2) - это будет служить вашим всплывающим окном (пожалуйста, обратите внимание, что UIView и UIView (2) должны иметь один и тот же уровень/иерархию. Не делайте imageview дочерним видом представления, иначе непрозрачность uiview будет влияет на UIView (2))
  1. Представьте V2 Модально

  2. Нажмите на переход. В инспекторе атрибутов установите представление как на весь экран. Удалить анимацию, если хотите

Storyboard

  1. Выберите V2. В инспекторе атрибутов установите представление как на весь экран. Проверка определяет контекст и предоставляет контекст

Storyboard

  1. Выберите MainView вашего V2 (пожалуйста, проверьте изображение). Установите backgroundColor в Clear Color

Storyboard

Ответ 12

Альтернативный способ - использовать "вид контейнера". Просто сделайте альфа ниже 1 и вставьте с помощью seque. XCode 5, целевой iOS7. Протестировано на iPhone.

enter image description here

Просмотр контейнера, доступный с iOS6. Ссылка в сообщение в блоге об этом.

Ответ 13

Решение этого ответа с использованием swift было бы следующим.

let vc = MyViewController()
vc.view.backgroundColor = UIColor.clear // or whatever color.
vc.modalPresentationStyle = .overCurrentContent
present(vc, animated: true, completion: nil)

Ответ 14

Я создал объект для обработки представления того, что я называю "наложенным модальным", что означает, что он сохраняет фоновый вид и позволяет иметь модальный с прозрачным фоном.

Он имеет один простой метод, который делает это:

- (void)presentViewController:(UIViewController *)presentedViewController
       fromViewController:(UIViewController *)presentingViewController
{
    presentedViewController.modalPresentationStyle = UIModalPresentationCustom;
    presentedViewController.transitioningDelegate = self;
    presentedViewController.modalPresentationCapturesStatusBarAppearance = YES;

    [presentedViewController setNeedsStatusBarAppearanceUpdate];

    [presentingViewController presentViewController:presentedViewController
                                       animated:YES
                                     completion:nil];
}

Важно установить свойство modalPresentationCapturesStatusBarAppearance в YES и принудительно обновить внешний вид строки состояния, если ваш представленный контроллер представления имеет другой preferredStatusBarStyle.

Этот объект должен иметь @property (assign, nonatommic) isPresenting

Вы хотите, чтобы этот объект соответствовал протоколам UIViewControllerAnimatedTransitioning и UIViewControllerTransitioningDelegate и реализовал следующие методы:

- (id)animationControllerForPresentedController:(UIViewController *)presented
                           presentingController:(UIViewController *)presenting
                               sourceController:(UIViewController *)source
{
    self.isPresenting = YES;

    return self;
}

- (id)animationControllerForDismissedController:(UIViewController *)dismissed
{
    self.isPresenting = NO;

    return self;
}

и

- (NSTimeInterval)transitionDuration:(id)transitionContext
{
    return 0.25;
}

- (void)animateTransition:(id)transitionContext
{
    UIViewController* firstVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController* secondVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView* containerView = [transitionContext containerView];
    UIView* firstView = firstVC.view;
    UIView* secondView = secondVC.view;

    if (self.isPresenting) {
        [containerView addSubview:secondView];
        secondView.frame = (CGRect){
            containerView.frame.origin.x,
            containerView.frame.origin.y + containerView.frame.size.height,
            containerView.frame.size
        };

        firstView.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed;
        [UIView animateWithDuration:0.25 animations:^{
            secondView.frame = containerView.frame;
        } completion:^(BOOL finished) {
            [transitionContext completeTransition:YES];
        }];
        } else {
        [UIView animateWithDuration:0.25 animations:^{
            firstView.frame = (CGRect){
                containerView.frame.origin.x,
                containerView.frame.origin.y + containerView.frame.size.height,
                containerView.frame.size
        };

        } completion:^(BOOL finished) {
            [transitionContext completeTransition:YES];
        }];
    }
}

Это делает анимацию слайдов в нижней части экрана, имитирующую модальную анимацию по умолчанию, но вы можете сделать ее, как хотите.

Важно то, что представление представления представления представления останется в обратном направлении, позволяя создать прозрачный эффект.

Это решение работает для iOS 7 +

Ответ 15

Очень простой способ сделать это (используя Storyboards, например):

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"SomeStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"SomeStoryboardViewController"];
// the key for what you're looking to do:
vc.modalPresentationStyle = UIModalPresentationOverCurrentContext;
vc.view.alpha = 0.50f;

[self presentViewController:vc animated:YES completion:^{
    // great success
}];

Это будет представлено UIViewController в Storyboard по модулю, но с полупрозрачным фоном.

Ответ 16

Чтобы воспроизвести все хорошие ответы и комментарии здесь и по-прежнему иметь анимацию при переходе на новый ViewController, это то, что я сделал: (поддерживает iOS 6 и выше)

Если вы используете UINavigationController\UITabBarController, это способ:

    SomeViewController *vcThatWillBeDisplayed = [self.storyboard instantiateViewControllerWithIdentifier:@"SomeVC"];

    vcThatWillBeDisplayed.view.backgroundColor = [UIColor colorWithRed: 255/255.0 green:255/255.0 blue:255/255.0 alpha:0.50];    

    self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;
    [self presentViewController:presentedVC animated:YES completion:NULL];

Если вы это сделаете, вы потеряете анимацию modalTransitionStyle. Чтобы решить эту проблему, вы можете легко добавить в свой класс SomeViewController следующее:

-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [UIView animateWithDuration:0.4 animations:^() {self.view.alpha = 1;}
       completion:^(BOOL finished){}];
}
- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.alpha = 0;
}

Ответ 17

Работа для iOS 7-10

if #available(iOS 8.0, *) {
    nextVC.modalPresentationStyle = .OverCurrentContext
    self.presentViewController(nextVC, animated: true, completion: nil)
} else {
    // Fallback on earlier version
    self.modalPresentationStyle = .Custom          
    nextVC.modalTransitionStyle = .CrossDissolve            
    self.presentViewController(nextVC, animated: false, completion: nil)
    }
}

Ответ 18

Конечно, вы должны установить UIModalPresentationCurrentContext, но место для установки clearColor также очень важно! Вы не можете установить фон в функции viewDidLoad, установите его до того, как представление загрузилось, как в корневом контроллере представления или в функции init контроллера, который будет представлен!

actionController.view.backgroundColor = [UIColor clearColor];
[self presentViewController:actionController animated:YES completion:nil];

или же

- (instancetype)init {

    self = [super initWithNibName:nil bundle:nil];

    if(self) {
        self.modalPresentationStyle = UIModalPresentationOverCurrentContext;
        [self.view setBackgroundColor:[UIColor clearColor]];
    }

    return self;
}

Ответ 19

Если вы используете modal segue, обязательно установите его как это изображение (вы можете отключить анимацию, если хотите) enter image description here

Ответ 20

Полный метод, протестированный на iOS 7 и iOS 8.

@interface UIViewController (MBOverCurrentContextModalPresenting)

/// @warning Some method of viewControllerToPresent will called twice before iOS 8, e.g. viewWillAppear:.
- (void)MBOverCurrentContextPresentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion;

@end

@implementation UIViewController (MBOverCurrentContextModalPresenting)

- (void)MBOverCurrentContextPresentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
    UIViewController *presentingVC = self;

    // iOS 8 before
    if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
        UIViewController *root = presentingVC;
        while (root.parentViewController) {
            root = root.parentViewController;
        }

        [presentingVC presentViewController:viewControllerToPresent animated:YES completion:^{
            [viewControllerToPresent dismissViewControllerAnimated:NO completion:^{
                UIModalPresentationStyle orginalStyle = root.modalPresentationStyle;
                if (orginalStyle != UIModalPresentationCurrentContext) {
                    root.modalPresentationStyle = UIModalPresentationCurrentContext;
                }
                [presentingVC presentViewController:viewControllerToPresent animated:NO completion:completion];
                if (orginalStyle != UIModalPresentationCurrentContext) {
                    root.modalPresentationStyle = orginalStyle;
                }
            }];
        }];
        return;
    }

    UIModalPresentationStyle orginalStyle = viewControllerToPresent.modalPresentationStyle;
    if (orginalStyle != UIModalPresentationOverCurrentContext) {
        viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverCurrentContext;
    }
    [presentingVC presentViewController:viewControllerToPresent animated:YES completion:completion];
    if (orginalStyle != UIModalPresentationOverCurrentContext) {
        viewControllerToPresent.modalPresentationStyle = orginalStyle;
    }
}

@end

Ответ 21

в appdelegate:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [[_window rootViewController]setModalPresentationStyle:UIModalPresentationCurrentContext];
    return YES;
}

в вашем первом контроллере просмотра, откуда вам нужно загрузить следующий вид:

  NextViewController *customvc = [[NextViewController alloc]init];
    [self presentViewController:customvc animated:YES completion:^{

    }];

в следующем контроллере nextViewController, который должен быть добавлен прозрачным:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor clearColor];
    UIView* backView = [[UIView alloc] initWithFrame:self.view.frame];
    backView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
    [self.view insertSubview:backView atIndex:0];
}

Ответ 22

Экран входа является модальным, что означает, что он находится поверх предыдущего экрана. До сих пор у нас был размытый фон, но он не размывал ничего; его просто серый фон.

Нам нужно правильно установить наш Modal.

ссылка на ссылку на изображение

  • Во-первых, нам нужно изменить фон View Controllers View для Clear color. Это просто означает, что он должен быть прозрачным. По умолчанию этот вид белый.

  • Во-вторых, нам нужно выбрать Segue, который приведет к экрану входа в систему, а в инспекторе атрибутов установите контекст презентации в текущий контекст. Эта опция доступна только при включенной автоматической компоновке и классах классов.

ссылка на графическую ссылку

Ответ 23

Настройте навигацию modalPresentationStyle на UIModalPresentationCustom

и установите цвет фона вашего контроллера представления в виде прозрачного цвета.

Ответ 24

Swift 4.2

guard let someVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "someVC") as? someVC else {
    return
}
someVC.modalPresentationStyle = .overCurrentContext

present(someVC, animated: true, completion: nil)