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


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

19 71

19 ответов:

модальный вид будет охватывать вид, который он нажимается сверху, а также панель навигации для вашего навигационного контроллера. Однако, если вы используете-presentModalViewController: animated: approach, то после завершения анимации только что покрытый вид фактически исчезнет, что делает любую прозрачность вашего модального вида бессмысленной. (Это можно проверить, реализовав методы-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];

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

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

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

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

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

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

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

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

Читайте также: как выглядит ваша цель-c синглтон?

У меня была такая же проблема, и для решения этой проблемы нужно добавить модальное представление с addSubview: и анимировать изменение в иерархии представлений с помощью 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;
                         }];
    }


}

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

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

эффект:

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

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

код в модальном представлении-я думаю, вы можете выяснить остальное, а именно установить свойство 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];
}
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentModalViewController:newview animated:YES];

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

self.вид.фон. = ... Альфа:0.x;

Если вы установите modalPresentationStyle для контроллера модального вида:

viewController.modalPresentationStyle = 17;

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

Я не пытался пройти обзор App Store с этим кодом, хотя

этот пост про отображение полупрозрачной " загрузки..."вид может дать несколько советов о том, как продолжить.

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

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

вы можете найти документацию в этот блог код на github

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

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

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

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

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

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

код для класса контроллера модального вида

.H-файл:

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

.файл м:

- (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) не установлен в "вертикальное покрытие", вам может не потребоваться вызывать методы анимации.

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

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

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

для 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-Проверьте этой теме.

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

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

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

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

on viewDidLoad;

self.dummyViewController = [[UIViewController alloc] init]; [личность.dummyViewController.вид setFrame:CGRectMake(0, 0, 1, 1)]; [личность.просмотр addSubView: self.dummyViewController.view];

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

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

Если вам нужен экран как крепится один, ниже код может помочь вам.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];

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

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

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

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