【问题标题】:How to change Modal background color to transparent in Objective-C如何在 Objective-C 中将模态背景颜色更改为透明
【发布时间】:2011-05-31 01:44:50
【问题描述】:

我想要一个具有透明背景颜色的模态视图,以便用户可以看到它后面的视图。

【问题讨论】:

  • 你可以使用[UIcolor clearcolor];
  • 你使用的是什么模式对话框?
  • @Raxit:当我用清晰的颜色设置背景颜色时,我们可以看到模态后面的视图。
  • @BoltClock:是的,这是为 iOS 设计的 @Eiko:我使用的是什么模式对话框是什么意思?
  • 在您的问题中您提到“我希望用户可以看到模态背后的视图。”对吗?或者你想说一些不同的东西。请描述一下你到底想做什么?

标签: objective-c background modal-dialog


【解决方案1】:

好的,所以 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 代替 dissmissModalViewController。

有几个限制:

  1. 你必须呈现给最根视图控制器,所以如果你想 覆盖整个屏幕,你有一个VC里面 UINavigationController,将其呈现给导航控制器。
  2. 可能是旧版 iOS 上的一些旋转问题(我没有看到任何问题) 构建(4.0 左右)
  3. 目前仅处理 Cross Dissolve 和 Cover Vertical 动画。

【讨论】:

  • 漂亮整洁的解决方案,谢谢!不过有两个观察结果。首先,通知的处理程序overViewDismissed 释放 self 而不是模态视图控制器,这会导致崩溃。完全删除通知代码 addObserver/postNotification 并在 present/dismiss 方法之外管理模态视图控制器的内存。其次,[[UIScreen mainScreen] applicationFrame] 并不总是返回正确的帧大小。我改用self.view.superview.frame(见this answer)。
  • @VladimirGrigorov 嘿,谢谢你的注意,它似乎有一些不好的逻辑。我不记得我把它放在哪个代码库中,但想象一下我在本地修复它......如果你仍在某个地方编译/运行它的固定版本,你能根据你的发现编辑答案吗?我可以更改它(只是将 [self autorelease] 更改为 [self.parentViewController autorelease] 吗?盲目地进行更改对我来说是有风险的 :)
  • 我已经删除了我之前评论中所说的通知代码,并且该版本已通过测试...
  • 还有一个库可以做到这一点:github.com/martinjuhasz/MJPopupViewController
【解决方案2】:

我的答案是一行代码,在呈现模态视图控制器之前添加到父视图控制器:

self.modalPresentationStyle = UIModalPresentationCurrentContext;

一旦添加了模态视图,这将阻止父视图被删除。

【讨论】:

  • 但这有效 self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;
  • 你在父视图控制器上设置了吗?然后您是否使用了命令presentViewController:animated:completion:?我不得不承认我只在 iPad 而不是 iPhone 上尝试过,但我认为这不会有什么不同。
  • 这正是我想要的。谢谢!完美运行。
【解决方案3】:

iOS 在模态显示视图时不支持透明度。

【讨论】:

  • 是的,我想。到目前为止,iOS 不支持模态中的透明度。感谢您的回答机器。 :)
  • 好吧,虽然知道这无济于事
【解决方案4】:

您可能希望将 UIView 作为覆盖添加到当前视图,但要使用透明或半透明背景全屏。请参阅此问题的第一个答案:

disable elements on UIView behind modal UIView

【讨论】:

    【解决方案5】:

    你需要倒着做,有点。 加载您的模态视图,然后将所有元素“手动”添加为子视图,这样它们就不会被隐藏在后面。 是的,这是很多编码,但可以完成。 我通过为电影播放器​​设置较小的帧大小并将一些按钮和文本视图作为子视图在其周围放置一些按钮和文本视图来播放电影并在屏幕上添加额外元素。 乙

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-25
      • 2014-01-27
      相关资源
      最近更新 更多