Прозрачный модальный вид на навигационном контроллере

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

Ответ 1

Модальный вид будет охватывать вид, который он нажимает поверх, а также панель навигации для вашего навигационного контроллера. Однако, если вы используете подход -presentModalViewController: анимированный: если после завершения анимации просматриваемый вид фактически исчезнет, ​​это сделает любую прозрачность вашего модального представления бессмысленным. (Это можно проверить, реализовав методы -viewWillDisappear: и -viewDidDisappear: в контроллере корневого представления).

Вы можете добавить модальный вид непосредственно в иерархию представления, например:

UIView *modalView =
    [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
modalView.opaque = NO;
modalView.backgroundColor =
    [[UIColor blackColor] colorWithAlphaComponent:0.5f];

UILabel *label = [[[UILabel alloc] init] autorelease];
label.text = @"Modal View";
label.textColor = [UIColor whiteColor];
label.backgroundColor = [UIColor clearColor];
label.opaque = NO;
[label sizeToFit];
[label setCenter:CGPointMake(modalView.frame.size.width / 2,
                                modalView.frame.size.height / 2)];
[modalView addSubview:label];

[self.view addSubview:modalView];

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

TransparentModalViewAppDelegate *delegate = (TransparentModalViewAppDelegate *)[UIApplication sharedApplication].delegate;
[delegate.window addSubview:modalView];

Ответ 2

Самый простой способ - использовать modalPresentationStyle свойство navigationController (но вам нужно сделать анимацию самостоятельно):

self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentModalViewController:modalViewController animated:NO];
modalViewController.view.alpha = 0;
[UIView animateWithDuration:0.5 animations:^{
    modalViewController.view.alpha = 1;
}];

Ответ 3

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

Пример кода для контроллера корневого представления:

- (void)viewDidLoad {
  OverlayViewController *o = [OverlayViewController sharedOverlayViewController];
  [self.view addSubview:o.view];
}

Пример кода, который вы можете использовать для отображения вашего модального вида:

[[OverlayViewController sharedOverlayViewController] presentModalViewController:myModalViewController animated:YES];

Я не использовал -presentModalViewController:animated: с моим OverlayViewController, но я ожидаю, что это будет работать нормально.

Смотрите также: Как выглядит ваш синглтон Objective-C?

Ответ 4

У меня была такая же проблема, и для решения было добавить модальное представление с помощью addSubview: анимировать изменение в иерархии представлений с помощью UIViews animateWithDuration: delay: options: animations: completion:

Я добавил свойство и 2 метода в подкласс UIViewController (FRRViewController), который включает в себя другие функции. Я скоро опубликую весь материал на gitHub, но до тех пор вы можете увидеть соответствующий код ниже. Для получения дополнительной информации вы можете проверить мой блог: Как отобразить прозрачный контроллер модального просмотра.

#pragma mark - Transparent Modal View
-(void) presentTransparentModalViewController: (UIViewController *) aViewController 
                                     animated: (BOOL) isAnimated 
                                    withAlpha: (CGFloat) anAlpha{

    self.transparentModalViewController = aViewController;
    UIView *view = aViewController.view;

    view.opaque = NO;
    view.alpha = anAlpha;
    [view.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        UIView *each = obj;
        each.opaque = NO;
        each.alpha = anAlpha;
    }];

    if (isAnimated) {
        //Animated
        CGRect mainrect = [[UIScreen mainScreen] bounds];
        CGRect newRect = CGRectMake(0, mainrect.size.height, mainrect.size.width, mainrect.size.height);


        [self.view addSubview:view];
        view.frame = newRect;

        [UIView animateWithDuration:0.8
                         animations:^{
                             view.frame = mainrect;
                         } completion:^(BOOL finished) {
                             //nop
                         }];

    }else{
        view.frame = [[UIScreen mainScreen] bounds];
        [self.view addSubview:view];
    }






}

-(void) dismissTransparentModalViewControllerAnimated:(BOOL) animated{

    if (animated) {
        CGRect mainrect = [[UIScreen mainScreen] bounds];
        CGRect newRect = CGRectMake(0, mainrect.size.height, mainrect.size.width, mainrect.size.height);
        [UIView animateWithDuration:0.8
                         animations:^{
                             self.transparentModalViewController.view.frame = newRect;
                         } completion:^(BOOL finished) {
                             [self.transparentModalViewController.view removeFromSuperview];
                             self.transparentModalViewController = nil;
                         }];
    }


}

Ответ 5

Вот что я сделал, чтобы решить проблему - Google детали, но этот подход работал очень хорошо для меня:

  • Сделайте снимок экрана основного представления. https://devforums.apple.com/message/266836 - это приводит к готовому методу, который возвращает UIView для текущего экрана.
  • Передайте скриншот в модальный вид (я использовал свойство)
  • Представление модального представления
  • В диспетчере modal viewDidAppear установите изображение как UIImageView в индекс 0. Отрегулируйте вертикальное положение изображения по высоте строки состояния.
  • В режиме просмотра просмотра модального просмотраWillDisappear удалите изображение снова

Эффект:

  • Анимация в виде любого модального представления - полупрозрачные части модального представления скользят над существующим представлением
  • Как только анимация останавливается, фон устанавливается на скриншот - это заставляет его выглядеть так, как будто старый вид все еще находится внизу, даже если это не так.
  • Как только модальный вид исчезнет, ​​анимация начнется, изображение будет удалено. Тем временем ОС показывает старый вид навигации, поэтому модальный вид прозрачно скользит и скрывается из виду, как и следовало ожидать.

Я попробовал анимацию в своем собственном окне, но это не сработало. Я получил крах, не указав, что случилось. Вместо того, чтобы преследовать это, я сделал просмотр bg и работал очень хорошо.

Код в модальном представлении - я думаю, вы можете выяснить остальное, а именно установить свойство modalView.bgImage...

- (void)viewDidAppear:(BOOL)animated {
    // background
    // Get status bar frame dimensions
    CGRect statusBarRect = [[UIApplication sharedApplication] statusBarFrame];
    UIImageView *imageView = [[UIImageView alloc] initWithImage:self.bgImage];
    imageView.tag = 5;
    imageView.center = CGPointMake(imageView.center.x, imageView.center.y - statusBarRect.size.height);
    [self.view insertSubview:imageView atIndex:0];
}

- (void)viewWillDisappear:(BOOL)animated {
    [[self.view viewWithTag:5] removeFromSuperview];
}

Ответ 6

self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentModalViewController:newview animated:YES];

и убедитесь, что вы устанавливаете прозрачный фон модального просмотра,

self.view.background =.... alpha: 0.x;

Ответ 7

если для модального контроллера просмотра для mododPresentationStyle установлено значение:

viewController.modalPresentationStyle = 17;

Вид в фоновом режиме не удаляется. (TWTweetComposeViewController использует его).

Я не пытался передать обзор App Store с помощью этого кода, хотя

Ответ 9

Да, вам нужно добавить представление вручную, и если вы хотите скользить со дна или что бы вы сами не делали анимацию.

Я написал класс для этого и полумодальный датпикер, использующий этот класс в качестве примера.

Вы можете найти документацию в этом сообщении в блоге, код on GitHub

Ответ 10

Я, наконец, выполнил это для интерфейса навигации или панели вкладок, объединив контроллер представления наложения (см. ответ pix0r), который скрыт/не скрыт перед тем, как скрыть или показать контроллер вида на основе этого очень хорошего сообщение в блоге.

Что касается контроллера вида, подсказка должна сделать его фоновый вид clearColor, тогда полупрозрачный вид наложения будет виден и все виды добавлены в виде подзонов в контроллере представления спереди и, что наиболее важно, непрозрачны.

Ответ 11

Я изучал эту же проблему на прошлой неделе. Я попробовал все различные ответы и примеры, найденные в Google, и здесь, в StackOverflow. Ни один из них не работал так хорошо.

Будучи новичком в программировании на iOS, я не знал о чем-то, называемом UIActionSheet. Поэтому, если вы пытаетесь это сделать, чтобы показать модальное наложение кнопок (например, модальное спрашивать кого-то, как они хотят что-то поделиться), просто используйте UIActionSheet.

Вот веб-страница, на которой показан пример того, как это сделать.

Ответ 12

Я получил эту идею от https://gist.github.com/1279713

Подготовка: В модальном представлении xib (или сцене с использованием раскадровки) я настраиваю полноэкранный фон UIImageView (подключаю его к файлу .h и придаю ему свойство backgroundImageView) с 0,3 альфа. И я установил цвет фона представления (UIView) как обычный черный.

Идея: Затем в "viewDidLoad" контроллера модального просмотра я фиксирую снимок экрана из исходного состояния и устанавливаю это изображение на фон UIImageView. Установите начальную точку Y на -480 и дайте ей сдвинуться до точки Y 0 с использованием 0,4-секундной продолжительности с опцией анимации EaseInOut. Когда мы отклоняем диспетчер представлений, просто делайте обратное.

Код для класса контроллера Modal View

.h файл:

@property (weak, nonatomic) IBOutlet UIImageView *backgroundImageView;
- (void) backgroundInitialize;
- (void) backgroundAnimateIn;
- (void) backgroundAnimateOut;

.m файл:

- (void) backgroundInitialize{
    UIGraphicsBeginImageContextWithOptions(((UIViewController *)delegate).view.window.frame.size, YES, 0.0);
    [((UIViewController *)delegate).view.window.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage * screenshot = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    backgroundImageView.image=screenshot;
}
- (void) backgroundAnimateIn{
    CGRect backgroundImageViewRect = backgroundImageView.frame;
    CGRect backgroundImageViewRectTemp = backgroundImageViewRect;
    backgroundImageViewRectTemp.origin.y=-480;
    backgroundImageView.frame=backgroundImageViewRectTemp;

    [UIView animateWithDuration:0.4 delay:0.0 options:UIViewAnimationCurveEaseInOut animations:^{
        backgroundImageView.frame=backgroundImageViewRect;
    } completion:^(BOOL finished) {

    }];
}
- (void) backgroundAnimateOut{
    CGRect backgroundImageViewRect = backgroundImageView.frame;
    backgroundImageViewRect.origin.y-=480;

    [UIView animateWithDuration:0.4 delay:0.0 options:UIViewAnimationCurveEaseInOut animations:^{
        backgroundImageView.frame=backgroundImageViewRect;
    } completion:^(BOOL finished) {

    }];
}

В viewDidLoad просто вызовите:

[self backgroundInitialize];
[self backgroundAnimateIn];

В любом месте, где мы отклоняем контроллер модального представления, мы вызываем:

[self backgroundAnimateOut];

Обратите внимание, что это ВСЕГДА будет анимировать фоновое изображение. Поэтому, если этот стиль перехода модального представления (или стиль перехода segue) не установлен в "Cover Vertical", вам может не потребоваться вызвать методы анимации.

Ответ 13

Я создал открытую библиотеку soruce MZFormSheetController, чтобы представить лист модальной формы на дополнительном UIWindow. Вы можете использовать его для отображения прозрачного модального контроллера, даже отрегулируйте размер представленного контроллера представления.

Ответ 14

Для iOS 8+ вы можете использовать стиль презентации UIModalPresentationOverCurrentContext для представленного контроллера просмотра для легкого достижения желаемого поведения.

UIViewController *viewController = [[UIViewController alloc] init];
viewController.view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.9f];
viewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:viewController animated:YES completion:nil];

Если вам также нужна поддержка iOS 7 - отметьте этот поток.

Ответ 15

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

Вы можете получить доступ к панели навигации через свойство navigationBar UINavigationController.

Я обнаружил, что UIButton, в отличие от UILabel, будет захватывать события мыши, что дает правильное модальное поведение.

Ответ 16

Я только что нашел обходной путь для этого. Просто создайте 1X1 UIViewController и добавьте его в свой родительский контроллер представления. И покажите прозрачный контроллер модального представления в этом UIViewController.

в viewDidLoad;

self.dummyViewController = [[UIViewController alloc] init]; [self.dummyViewController.view setFrame: CGRectMake (0, 0, 1, 1)]; [self.view addSubView: self.dummyViewController.view];

когда вам нужно открыть transparentViewController;

[self.dummyViewController presentModalViewController: yourTransparentModalViewController animated: true];

Ответ 17

Если вам нужен экран, подобный прилагаемому, приведенный ниже код может вам помочь. enter image description here

Код:

MyViewController * myViewController = [[MyViewController alloc] initWithNibName:nibName bundle:nil];
UINavigationController * myNavigationController = [[UINavigationController alloc] initWithRootViewController: myViewController];
myNavigationController.modalPresentationStyle = UIModalPresentationPageSheet;
[self presentModalViewController: myNavigationController animated:YES];

Ответ 18

Если вы хотите наложить экран, используйте parentViewController.view, он разместит над панелью навигации ++

MyCustomViewController* myOverlayView = [[MyCustomViewController alloc] init]; [self.parentViewController.view addSubview:myOverlayView];

Ответ 19

Это сработало для меня:

UIViewController *modalViewController = [[UIViewController alloc] init];
modalViewController.view.backgroundColor = [UIColor whiteColor] colorWithAlpha:0.5];
[self showDetailViewController:modalViewController sender:nil];