Відображати clearColor UIViewController над UIViewController


150

Я маю UIViewControllerпредставлення як підпогляд / модальний поверх іншого UIViewControllerвигляду, наприклад, що підпогляд / модальний режим повинен бути прозорим, і будь-які компоненти, що додаються до його, повинні бути видимі. Проблема в тому, що у мене є те, що в підрозділі показано чорний фон замість того, щоб мати clearColor. Я намагаюся зробити UIViewяк чіткий колір не чорний фон. Хтось знає, що з цим не так? Будь-яка пропозиція високо оцінена.

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. Контролер модального перегляду без чорного тла просто чіткийКольоровий / прозорий. Єдине , що мені потрібно змінити, я замінив 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
Повинна бути прийнята відповідь. Раніше прийнята відповідь все ще справедлива з застарілих причин, але це рекомендований спосіб.
Tomasz Bąk

3
Якщо ви розробляєте лише для ios 8, продовжте цю відповідь! Це працює
Mário Carvalho

2
Це добре, але чи не повинен бути останній рядок [self presentViewController:modalViewController animated:YES completion:nil];? (замість targetController)?
SuperDuperTango

3
Для того, щоб це зробити для мене, я додав modalViewController.view.backgroundColor = UIColor.clearColor () спасибі за рішення
Pramod

може хтось надати мені код для pushviewcontroller теж (я маю на увазі для навігаційного контролера).
Алок

140

ВИРІШЕНО : Я вирішив проблеми. Це так добре працює як для iPhone, так і для iPad. Контролер модального перегляду без чорного тла просто чіткийКольоровий / прозорий. Єдине, що мені потрібно змінити - це я замінив 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
btw .. Я помітив, що через 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 Я сподіваюся, що вам допоможе.
hightech

114

Тож для чисто візуальних мислителів та шанувальників розкадрувань ви можете:

1. Представлення контролера перегляду

Визначте контекст

2. Представлений контролер перегляду

Презентація: над поточним контекстом


Це має бути прийнятою відповіддю. Це все, що вам потрібно зробити для цього, а потім встановити колір тла подання на модальному контролері для очищення.
Джессі

Погоджено, параметри розкадровки замінюють код у цьому випадку.
C0D3

17
Ця відповідь така мила, у мене зараз діабет.
GeneCode

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)

16

Це з xCode 7 beta 4, використовуючи керування перетягуванням управління. Просто встановіть тло призначення, щоб очистити, і встановіть властивості segue в IB таким чином (nb. Презентація також може бути "Повноекранний"):

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


2
СПАСИБІ. я зробив ваш виправлення неясностей + відповідь ViewControllers від @pasevin, і це спрацювало !!
CSawy

1
Це відповіло на моє запитання. Велике спасибі. Проголосуйте вгору: D
Nate4436271

8

Я знайшов найпростіший спосіб змусити його працювати на iOS7 та iOS8 - це додати встановити презентаціюStyle на UIModalPresentationOverCurrentContext на modallyPresentedVC (ViewController, який ви хочете представити модально) через iOS8:

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

і UIModalPresentationCurrentContext про представлення VC (контролер, який представляє модально представлений) через iOS7:

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

Тому що в iOS7 та iOS8 обробляються різні речі. Звичайно, вам не потрібно встановлювати властивості navigationController, якщо ви їх не використовуєте. Сподіваюся, що це допомагає.


врятував мій бекон! Спасибі
Качка

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)

4

Інший спосіб (не потрібно створювати власні переходи та працює на iOS 7)

Використання розгортки:

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

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

Потім створіть модальний мозок за допомогою аркуша форми і протестуйте його.


Ти дивовижний!!! це насправді працює !!! (встановлення розміру "свободи" в ІБ не впливає на анітінг cose, це імітація метрики, але все одно, це працює !!!), і це так просто !!!
Раду Сіміонеску

4

Рішення iOS 7 із користувацьким Segue:

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

Рішення засноване на високотехнологічному коді.


Коли я відхиляю функцію [selfmissmissViewControllerAnimated: 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];

Щоб створити свій власний перехід, вам потрібно дві речі:

  • Об'єкт TransitionDelegate (реалізація <UIViewControllerTransitionDelegate>)
  • Об'єкт "Анімоване перекладення" (реалізація <UIViewControllerAnimatedTransitioning>)

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


Будь-які конкретні причини, чому ви додали головний контролер і клас контролера другого перегляду в клас аніматора? чому ви безпосередньо не використовували UIViewController * toVC = (UIViewController *) [переходContext viewControllerForKey: UITransitionContextToViewControllerKey]; UIViewController * fromVC = (UIViewController *) [переглядContext 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];

Дублікат другої найкращої відповіді.
Tomasz Bąk

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 це можна досягти, встановивши презентацію на "Над поточним контекстом" на всіх контролерах перегляду, що беруть участь у модальній презентації. Навіть для навігаційних контролерів.

Наприклад, встановіть його на всі ці контролери перегляду:

NavController -> RootViewController -> ModalViewController

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


0

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

Ах, ще щось, про що я тільки подумав - цілком можливо, що ваш контролер перегляду ВИНАЄ альфа-фон, але, звичайно, альфа буде відображатися до кольору базового вікна або контролера кореневого перегляду програми, який чорний за замовчуванням. Сам базовий шар у всій вашій програмі не може мати прозорий фон - прозорий для чого? Що за цим? Слід через щось побачити через прозорість. Чи має це сенс?


Я спробував прокоментувати self.view.opaque = ТАК; лінія, і вона не працює. :-(
хай-тек

Ви читали другу частину моєї відповіді? Ви, можливо, не зможете робити те, що хочете, залежно від налаштувань. Що ви розміщуєте позаду clearColor VC? Можливо, ми зможемо розібратися з цим ^^
WendiKidd

-3

Просто використовуйте "self.modalPresentationStyle = UIModalPresentationCurrentContext;",

Буде добре :)


1
Це лише повторення того, що вже було сказано в існуючих відповідях.
Панг
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.