Отображение clearColor UIViewController поверх UIViewController

150

У меня есть UIViewControllerпредставление как подпредставление / модал поверх другого UIViewControllerпредставления, например, что подпредставление / модал должно быть прозрачным, и все компоненты, добавленные в подпредставление, должны быть видимыми. Проблема в том, что у меня есть подпредставление показывает черный фон вместо того, чтобы иметь clearColor. Я пытаюсь сделать UIViewкак clearColor не черный фон. Кто-нибудь знает, что с ним не так? Любое предложение приветствуется.

FirstViewController.m

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"SecondViewController"];

[vc setModalPresentationStyle:UIModalPresentationFullScreen];
[self presentModalViewController:vc animated:NO];  

SecondViewController.m

- (void)viewDidLoad 
{
     [super viewDidLoad];
     self.view.opaque = YES;
     self.view.backgroundColor = [UIColor clearColor];
}

РЕШЕНО : Я исправил проблемы. Это работает так хорошо для iPhone и iPad. Модальный View Controller без черного фона просто прозрачный / прозрачный. Единственное, что мне нужно изменить, я заменил UIModalPresentationFullScreenна UIModalPresentationCurrentContext. Как это просто!

FirstViewController.m

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"SecondViewController"];
vc.view.backgroundColor = [UIColor clearColor];
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:vc animated:NO completion:nil];

ВНИМАНИЕ: Если вы используете modalPresentationStyleсвойство navigationController:

FirstViewController.m

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"SecondViewController"];
vc.view.backgroundColor = [UIColor clearColor];
self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:vc animated:NO completion:nil];

ЗАМЕЧАНИЕ. Плохая новость заключается в том, что вышеуказанное решение не работает на iOS 7. Хорошая новость заключается в том, что я исправил проблему с iOS7! Я попросил кого-то о помощи, и вот что он сказал:

Представляя контроллер представления модально, iOS удаляет контроллеры представления под ним из иерархии представления на время, которое это представлено. Хотя вид вашего модально представленного контроллера представления прозрачен, под ним нет ничего, кроме окна приложения, которое является черным. iOS 7 представила новый модальный стиль представления UIModalPresentationCustom, который заставляет iOS не удалять представления под представленным контроллером представления. Однако, чтобы использовать этот модальный стиль презентации, вы должны предоставить свой собственный делегат перехода для обработки презентации и отклонения анимации. Это изложено в докладе «Пользовательские переходы с использованием контроллеров представления» из WWDC 2013 https://developer.apple.com/wwdc/videos/?id=218, в котором также описывается, как реализовать свой собственный делегат перехода.

Вы можете увидеть мое решение для указанной выше проблемы в iOS7: https://github.com/hightech/iOS-7-Custom-ModalViewController-Transitions

высокие технологии
источник
1
убедитесь, что вы установили modalPresentationStyle для rootViewController, иначе он не будет работать
Thorsten
Пожалуйста, взгляните на комментарий к этому ответу stackoverflow.com/a/25990081/1418457 , он работает
onmyway133
Этот stackoverflow.com/q/27598846/1603234 заставляет меня улыбаться, теперь ваша очередь :)
Hemang
Я должен был сделать self.modalPresentationStyle = UIModalPresentationCurrentContext; с представленным контроллером представления, чтобы он работал, а не с существующим.
Туллеб
1
Проверьте ответ Броди ниже. modalViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext; решит проблему,
GoodSp33d

Ответы:

143

iOS8 +

В iOS8 + теперь вы можете использовать новый modalPresentationStyle UIModalPresentationOverCurrentContext, чтобы представить контроллер представления с прозрачным фоном:

MyModalViewController *modalViewController = [[MyModalViewController alloc] init];
modalViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;           
[self presentViewController:modalViewController animated:YES completion:nil];    
Броди Робертсон
источник
5
Должен быть принятый ответ. Ранее принятый ответ все еще действителен по старым причинам, но это рекомендуемый метод.
Томаш Бек
3
Если вы разрабатываете только для ios 8, идите с этим ответом! Это работает
Марио Карвалью
2
Это хорошо, но не должна быть последняя строка [self presentViewController:modalViewController animated:YES completion:nil];? (вместо targetController)?
SuperDuperTango
3
Чтобы работать для меня, я добавил modalViewController.view.backgroundColor = UIColor.clearColor (), спасибо за решение
Pramod
Может ли кто-нибудь предоставить мне код для pushviewcontroller тоже (я имею в виду для контроллера навигации).
Alok
140

РЕШЕНО : Я исправил проблемы. Это работает так хорошо для iPhone и iPad. Модальный View Controller без черного фона просто прозрачный / прозрачный. Единственное, что мне нужно изменить - я заменил UIModalPresentationFullScreen на UIModalPresentationCurrentContext. Как это просто!

FirstViewController.m

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"SecondViewController"];
    vc.view.backgroundColor = [UIColor clearColor];
    self.modalPresentationStyle = UIModalPresentationCurrentContext;
    [self presentViewController:vc animated:NO completion:nil];

ЗАМЕЧАНИЕ. Если вы используете свойство modalPresentationStyle для navigationController:

FirstViewController.m

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"SecondViewController"];
    vc.view.backgroundColor = [UIColor clearColor];
    self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;
    [self presentViewController:vc animated:NO completion:nil];

ЗАМЕЧАНИЕ. Плохая новость заключается в том, что вышеуказанное решение не работает на iOS 7. Хорошая новость заключается в том, что я исправил проблему с iOS7! Я попросил кого-то о помощи, и вот что он сказал:

Представляя контроллер представления модально, iOS удаляет контроллеры представления под ним из иерархии представления на время, которое это представлено. Хотя вид вашего модально представленного контроллера представления прозрачен, под ним нет ничего, кроме окна приложения, которое является черным. iOS 7 представила новый модальный стиль представления, UIModalPresentationCustom, который заставляет iOS не удалять представления под представленным контроллером представления. Однако, чтобы использовать этот модальный стиль презентации, вы должны предоставить свой собственный делегат перехода для обработки презентации и отклонения анимации. Это изложено в докладе «Пользовательские переходы с использованием контроллеров представления» из WWDC 2013 https://developer.apple.com/wwdc/videos/?id=218, в котором также описывается, как реализовать свой собственный делегат перехода.

Вы можете увидеть мое решение для указанной выше проблемы в iOS7: https://github.com/hightech/iOS-7-Custom-ModalViewController-Transitions

высокие технологии
источник
1
self.modalPresentationStyle = UIModalPresentationCurrentContext;сделал это.
Адриано Лукас
4
Кстати, я заметил, что из-за self.modalPresentationStyle = UIModalPresentationCurrentContext; он не представляет modalViewController с анимацией ... есть идеи?
Деварши
1
@Miraaj Затем установите modalPresentationStyle обратно в UIModalPresentationFullScreen, прежде чем показывать, что UIViewController должен работатьself.modalPresentationStyle = UIModalPresentationFullScreen; [self performSegueWithIdentifier:@"CustomSegue" sender:self];
hightech
1
Выполняя это в iOS 6 и 7, новый контроллер представления очищается во время анимации презентации, но как только он установлен, фон становится черным. Это снова становится ясным при анимации увольнения. Кто-нибудь еще имел эту проблему?
Дрю С
3
@pkamb Я обновил решение для iOS 7. stackoverflow.com/a/11252969/1344459 Я надеюсь, что это поможет вам.
хай-тек
114

Так что для чисто визуальных мыслителей и любителей раскадровки вы можете сделать:

1. Представление View Controller

Определить контекст

2. Представлен вид контроллера

Презентация: в текущем контексте

pasevin
источник
Это должен быть принятый ответ. Это все, что вам нужно сделать, чтобы это сработало, а затем установите цвет фона представления на модальном контроллере, чтобы очистить.
Джесси
Согласитесь, варианты раскадровки перезаписывают код в этом случае.
C0D3
17
Этот ответ такой сладкий, у меня сейчас диабет.
GeneCode 10.10.16
25

Решение Swift 3 и iOS10:

//create view controller
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "RoadTripPreviewViewController")
//remove black screen in background
vc.modalPresentationStyle = .overCurrentContext
//add clear color background
vc.view.backgroundColor = UIColor.clear
//present modal
self.present(vc, animated: true, completion: nil)
Кевин ABRIOUX
источник
16

Это из xCode 7 beta 4, использующей Seg для управления перетаскиванием. Просто установите фон вашего места назначения, чтобы очистить, и установите свойства перехода в IB следующим образом (примечание. Презентация также может быть «на весь экран»):

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

smileBot
источник
2
СПАСИБО. я сделал ваше исправление segue + ответ ViewControllers от @pasevin, и это сработало !!
CSawy
1
Это ответило на мой вопрос. Большое спасибо. Голосование "за": D
Nate4436271
8

Я обнаружил, что самый простой способ заставить его работать на iOS7 и iOS8 - это добавить установить presentationStyle в UIModalPresentationOverCurrentContext на modallyPresentedVC (ViewController, который вы хотите представить модально) из-за iOS8:

[modallyPresentedVC setModalPresentationStyle:UIModalPresentationOverCurrentContext];
[modallyPresentedVC.navigationController setModalPresentationStyle:UIModalPresentationOverCurrentContext];

и UIModalPresentationCurrentContext для представления VC (контроллер, который представляет modallyPresented) из-за iOS7:

[presentingVC setModalPresentationStyle:UIModalPresentationCurrentContext];
[presentingVC.navigationController setModalPresentationStyle:UIModalPresentationCurrentContext];

Потому что вещи обрабатываются по-разному на iOS7 и iOS8. Конечно, вам не нужно устанавливать свойства navigationController, если вы его не используете. Надеюсь, это поможет.

3vangelos
источник
спас мой бекон! Спасибо
утка
5

Версия Swift2:

let vc = self.storyboard!.instantiateViewControllerWithIdentifier("YourViewController") as! YourViewController
vc.view.backgroundColor = UIColor.clearColor()
vc.modalPresentationStyle = UIModalPresentationStyle.OverFullScreen // orOverCurrentContext to place under navigation
self.presentViewController(vc, animated: true, completion: nil)
Mojtabye
источник
4

Другой способ (не нужно создавать собственные переходы и работает на iOS 7)

Использование раскадровки:

Создайте дочерний контроллер вида со свободным размером, установите ширину вида 500x500 (например) и добавьте следующий метод:

- (void)viewWillLayoutSubviews{
    [super viewWillLayoutSubviews];
    self.view.superview.bounds = CGRectMake(0, 0, 500, 500);
    self.view.superview.backgroundColor = [UIColor clearColor];
}

Затем создайте модальный переход с помощью Form Sheet и протестируйте его.

educaPix
источник
Ты великолепен!!! это на самом деле работает !!! (установка размера "свобода" в IB не влияет на то, что это - симуляция, но в любом случае это работает !!!) и это так просто !!!
Раду Симионеску
4

Решение для iOS 7 с пользовательским интерфейсом:

CustomSegue.h
#import <UIKit/UIKit.h>

    @interface CustomSegue : UIStoryboardSegue <UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning>

    @end



CustomSegue.m
#import "CustomSegue.h"

@implementation CustomSegue

-(void)perform {

    UIViewController* destViewController = (UIViewController*)[self destinationViewController];
    destViewController.view.backgroundColor = [UIColor clearColor];
    [destViewController setTransitioningDelegate:self];
    destViewController.modalPresentationStyle = UIModalPresentationCustom;
    [[self sourceViewController] presentViewController:[self destinationViewController] animated:YES completion:nil];
}


//===================================================================
// - UIViewControllerAnimatedTransitioning
//===================================================================

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

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {

    UIView *inView = [transitionContext containerView];
    UIViewController* toVC = (UIViewController*)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIViewController* fromVC = (UIViewController *)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

    [inView addSubview:toVC.view];

    CGRect screenRect = [[UIScreen mainScreen] bounds];
    [toVC.view setFrame:CGRectMake(0, screenRect.size.height, fromVC.view.frame.size.width, fromVC.view.frame.size.height)];

    [UIView animateWithDuration:0.25f
                     animations:^{

                         [toVC.view setFrame:CGRectMake(0, 0, fromVC.view.frame.size.width, fromVC.view.frame.size.height)];
                     }
                     completion:^(BOOL finished) {
                         [transitionContext completeTransition:YES];
                     }];
}


//===================================================================
// - UIViewControllerTransitioningDelegate
//===================================================================

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {

    return self;
}

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
    //I will fix it later.
    //    AnimatedTransitioning *controller = [[AnimatedTransitioning alloc]init];
    //    controller.isPresenting = NO;
    //    return controller;
    return nil;
}

- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id <UIViewControllerAnimatedTransitioning>)animator {
    return nil;
}

- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator {
    return nil;
}

@end

Решение на основе высокотехнологичного кода.

Макс Грибов
источник
Когда я отклоняю по [self dismissViewControllerAnimated: YES завершение: NULL]; Я получаю исключение ??
Асадулла Али
Да, для этого кода. Или вы должны реализовать animationControllerForDismissedController метод для анимации начать работу.
Макс Грибов
4

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

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main_iPhone" bundle:nil];
    UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"MMPushNotificationViewController"];

    vc.view.backgroundColor = [UIColor clearColor];
    self.modalPresentationStyle = UIModalPresentationCurrentContext;
#ifdef __IPHONE_8_0
    if(IS_OS_8_OR_LATER)
    {
        self.providesPresentationContextTransitionStyle = YES;
        self.definesPresentationContext = YES;
        [vc setModalPresentationStyle:UIModalPresentationOverCurrentContext];
    }
#endif


    [self presentViewController:vc animated:NO completion:nil];

MMPushNotificationViewControllerявляется контроллером прозрачного вида, а также я сделал MMPushNotificationViewControllerцвет представления прозрачным. Теперь все, что я сделал и сделал моим Transparentview-контроллером.

Манаб Кумар Мал
источник
2

Для iOS7

Теперь есть способ добиться этого с помощью пользовательских переходов iOS7, например:

MyController * controller = [MyController new];
[controller setTransitioningDelegate:self.transitionController];
controller.modalPresentationStyle = UIModalPresentationCustom;
[self controller animated:YES completion:nil];

Чтобы создать свой собственный переход, вам нужно 2 вещи:

  • Объект TransitionDelegate (реализация <UIViewControllerTransitionDelegate>)
  • Объект "AnimatedTransitioning" (реализация <UIViewControllerAnimatedTransitioning>)

Вы можете найти больше информации о пользовательских переходах в этом руководстве .

Kirualex
источник
Какие-то конкретные причины, по которым вы добавили mainviewcontroller и второй класс контроллера представления в класс аниматора? почему вы непосредственно не использовали UIViewController * toVC = (UIViewController *) [transitionContext viewControllerForKey: UITransitionContextToViewControllerKey]; UIViewController * fromVC = (UIViewController *) [transitionContext viewControllerForKey: UITransitionContextFromViewControllerKey];
Сатьям Райкар
Это не мое руководство, поэтому я не знаю все подробности об этом. Ваша точка зрения кажется верной, хотя.
Kirualex
2

Отлично работает на iOS7 и iOS8

UIViewController* vc=[[UIViewController alloc]initWithNibName:@"VC" bundle:nil];

vc.view.alpha=0.7;
[vc setModalPresentationStyle:UIModalPresentationOverCurrentContext];

self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;

[self presentViewController:vc animated:NO completion:nil];
Hoppus
источник
Дубликат второго лучшего ответа.
Томаш Бек
2

Вы также можете повторно добавить окно к представлению.

OneViewController *vc = [[OneViewController alloc] init];
if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]) {
    [self presentViewController:vc animated:YES completion:nil];
} else {
    [self presentModalViewController:vc animated:YES];
}

[[[UIApplication sharedApplication] keyWindow] insertSubview:self.view atIndex:0];

И таким образом, представление может быть анимированным.

Эльф сундэ
источник
1

Для iOS 7 и только с помощью Interface Builder это можно сделать, установив Presentation в «Over Current Context» на всех контроллерах представления, участвующих в модальной презентации. Даже для навигационных контроллеров.

Например, установите его на всех этих контроллерах представления:

NavController -> RootViewController -> ModalViewController

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

Дэвид Эрнандес
источник
0

Я не слишком много играл с Storyboard / Interface Builder, но что мне бросается в глаза, это то, что вы говорите, что изображение прозрачное (т. Е. 100% альфа / прозрачность), а также говорите, что оно непрозрачное ( 0% альфа - полностью твердое вещество). Эти две вещи, кажется, не мешают. Я бы закомментировал self.view.opaque = YES;строку и посмотрел, работает ли она тогда;)

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

WendiKidd
источник
Я пытался закомментировать self.view.opaque = YES; линия, и это не работает. :-(
hightech
Вы читали вторую часть моего ответа? Вы не сможете делать то, что хотите, в зависимости от ваших настроек. Что вы размещаете за clearColor VC? Может быть, мы можем разобраться в этом ^^
WendiKidd
-3

Просто используйте "self.modalPresentationStyle = UIModalPresentationCurrentContext;", в представлении представления

Будет работать нормально :)

Venkateswarlu.NP
источник
1
Это просто повторение того, что уже сказано в существующих ответах.
Пан