Как изменить модальный цвет фона на прозрачный в Objective-C - PullRequest
9 голосов
/ 27 декабря 2010

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

Ответы [ 5 ]

10 голосов
/ 31 мая 2012

Хорошо, поэтому presentModalViewController не предлагает такое поведение ... Однако это все еще возможно. Я создал категорию, которая работает для меня (и, надеюсь, вы). В качестве дополнительного бонуса он также предотвращает сбои, связанные с одновременным увольнением и представлением модальных представлений!

Заголовочный файл:

//
//  UIViewController+overView.h
//  Created by Kevin Lohman on 5/30/12.
//

#import <UIKit/UIKit.h>

@interface UIViewController (OverView)
- (void)presentOverViewController:(UIViewController *)modalViewController animated:(BOOL)animated;
- (void)dismissOverViewControllerAnimated:(BOOL)animated;
@end

Файл реализации:

//
//  UIViewController+overView.m
//  Created by Kevin Lohman on 5/30/12.
//

#import "UIViewController+overView.h"

@implementation UIViewController (OverView)

#define kUIViewControllerOverViewDismissNotification @"OverViewDismissNotification"

const float kUIViewControllerOverViewAnimationDuration = 0.75;
const NSInteger kUIViewControllerOverViewTag = 8008135; // Arbitrary number, so as not to conflict
- (void)overViewDismissed
{
    [self autorelease];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kUIViewControllerOverViewDismissNotification object:self.view];
}

- (void)presentOverViewController:(UIViewController *)modalViewController animated:(BOOL)animated
{
    UIView *toView = self.view;

    CGRect finalRect = CGRectIntersection([[UIScreen mainScreen] applicationFrame], self.view.frame); // Make sure it doesn't go under menu bar
    modalViewController.view.frame = finalRect;
    modalViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
    modalViewController.view.tag = kUIViewControllerOverViewTag+modalViewController.modalTransitionStyle; // Hiding some info here :)

    if(animated)
    {
        switch(modalViewController.modalTransitionStyle)
        {
            // Currently only cross dissolve and cover vertical supported... if you add support let me know.
            case UIModalTransitionStyleCrossDissolve:
            {
                float beforeAlpha = modalViewController.view.alpha;
                modalViewController.view.alpha = 0;
                [toView addSubview:modalViewController.view];
                [UIView animateWithDuration:kUIViewControllerOverViewAnimationDuration animations:^{
                    modalViewController.view.alpha = beforeAlpha;
                }];
                break;
            }
            case UIModalTransitionStyleCoverVertical:
            default:
            {
                modalViewController.view.frame = CGRectMake(modalViewController.view.frame.origin.x, modalViewController.view.frame.size.height, 
                                                            modalViewController.view.frame.size.width, modalViewController.view.frame.size.height);
                [toView addSubview:modalViewController.view];
                [UIView animateWithDuration:kUIViewControllerOverViewAnimationDuration animations:^{
                    modalViewController.view.frame = finalRect;
                }];
                break;
            }
        }
    }
    else {
        [toView addSubview:modalViewController.view];
    }

    [modalViewController retain]; // Keep it around until we dismiss it.
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(overViewDismissed) name:kUIViewControllerOverViewDismissNotification object:modalViewController.view]; // Release will happen when this notification is posted
}

NSInteger transitionStyleForTag(tag)
{
    if (tag >= kUIViewControllerOverViewTag && tag <= kUIViewControllerOverViewTag+UIModalTransitionStylePartialCurl)
    {
        return tag-kUIViewControllerOverViewTag;
    }
    else {
        return -1; // Not a Over View
    }
}

- (void)dismissOverViewControllerAnimated:(BOOL)animated
{
    UIView *overView = transitionStyleForTag(self.view.tag) >= 0 ? self.view : nil; // Can dismiss ourselves
    for(UIView *subview in self.view.subviews)
    {
        if(transitionStyleForTag(subview.tag) >= 0)
            overView = subview; // Keep going, lets dismiss last presented first
    }
    if(!overView) return; // None to dismiss

    if(animated)
    {
        switch(transitionStyleForTag(overView.tag))
        {
            // Currently only cross dissolve and cover vertical supported... if you add support let me know.
            case UIModalTransitionStyleCrossDissolve:
            {
                float beforeAlpha = overView.alpha;
                [UIView animateWithDuration:kUIViewControllerOverViewAnimationDuration animations:^{
                    overView.alpha = 0;
                } completion:^(BOOL finished) {
                    [overView removeFromSuperview];
                    overView.alpha = beforeAlpha;
                    [[NSNotificationCenter defaultCenter] postNotificationName:kUIViewControllerOverViewDismissNotification object:overView];
                }];
                break;
            }
            case UIModalTransitionStyleCoverVertical:
            default:
            {
                [UIView animateWithDuration:kUIViewControllerOverViewAnimationDuration animations:^{
                    overView.frame = CGRectMake(0, overView.frame.size.height, overView.frame.size.width, overView.frame.size.height);
                } completion:^(BOOL finished) {
                    [overView removeFromSuperview];
                    [[NSNotificationCenter defaultCenter] postNotificationName:kUIViewControllerOverViewDismissNotification object:overView];
                }];
                break;
            }
        }
    }
    else {
        [overView removeFromSuperview];
        [[NSNotificationCenter defaultCenter] postNotificationName:kUIViewControllerOverViewDismissNotification object:overView];
    }
}
@end

А затем для его использования просто используйте presentOverViewController вместо presentModalViewController и dismissOverViewController вместо dismissModalViewController.

Есть несколько ограничений:

  1. Вы должны представить самый корневой контроллер представления, так что если вы хотите чтобы покрыть весь экран, и у вас есть VC внутри UINavigationController, представьте его навигационному контроллеру.
  2. Может быть некоторые проблемы с ротацией (я не видел) на старых iOS builds (4.0 или около того)
  3. В настоящее время обрабатываются только анимации Cross Dissolve и Cover Vertical.
9 голосов
/ 28 июня 2012

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

self.modalPresentationStyle = UIModalPresentationCurrentContext;

Это предотвратит удаление родительского представления после добавления модального представления.

3 голосов
/ 16 февраля 2011

iOS не поддерживает прозрачность при модальном представлении.

0 голосов
/ 09 февраля 2012

Вы должны работать в обратном направлении, вроде. Загрузите ваш модальный вид, затем добавьте все свои элементы на нем «вручную» как Subview, таким образом, они не будут скрыты позади. Да, это много кодирования, но может быть сделано. Я сделал это для воспроизведения фильмов и добавления дополнительных элементов на экран, установив меньший размер кадра для проигрывателя фильмов и добавив несколько кнопок и текстовых обзоров в качестве подпредставлений. B

0 голосов
/ 14 апреля 2011

Возможно, вы хотите добавить UIView в качестве наложения к вашему текущему виду, но сделать это на весь экран с прозрачным или полупрозрачным фоном. Смотрите первый ответ на этот вопрос:

отключение элементов в UIView за модальным UIView

...