UIView 显示顺序问题?

Posted

技术标签:

【中文标题】UIView 显示顺序问题?【英文标题】:UIView display order issue? 【发布时间】:2011-06-01 07:34:34 【问题描述】:

问题

在屏幕上(ios 4)绘制自定义电影播放器​​控制器时,我使用AVPlayerLayer 来显示。我希望在播放器顶部合成一些叠加层(广告横幅、播放器控件等)。目前,这完全适用于以下层次结构:

UIView(self.view)\ | UIView(控件视图)\ * | UIView [一些电影播放器​​控件] | UIView [更多电影播放器​​控件] *

AVPlayerLayerself.view 的子层。在播放器加载时,我首先将图层添加到self.view 并在controlsView 上调用bringSubviewToFront:,然后检测对其的点击并以编程方式在计时器上显示/淡出/其他。这里没有问题。

现在我已经支持动态获取和显示广告内容,我想设置以下层次结构:

UIView(self.view)\ | UIImageView(广告横幅) | UIImageView(另一个广告横幅) | ... | UIView(控件视图)\ * | UIView [一些电影播放器​​控件] | UIView [更多电影播放器​​控件] *

在播放器加载时,我接下来要做的是附加到我的 AVPlayer 实例一些 addBoundaryTimeObserverForTimes:queue:usingBlock: 调用以在适当的时间淡入和淡出广告横幅。当我这样做时,我将UIImageViews 添加到self.view 作为没有明确排序的子视图(因此它们应该绘制在其他所有内容之上),并在它们上添加setHidden:YES

我已经 NSLog'd 并且这些淡入淡出块正在正确执行,分别在广告横幅上设置 view.alpha = 1.0fview.alpha = 0.0f 显示和隐藏,但根本没有出现任何内容,即使明确设置UIImage 由视图显示为已知的工作本地图像,框架为(0, 0, 320, 480),并设置autoresizingMask

UIViewAutoresizingFlexibleTopMargin  |
UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin;

UIViewContentMode 是默认值(应该是UIViewContentModeScaleToFill)。


我为这个问题所采用的“解决方案”

这实际上根本没有解决问题,但我现在使用 0.1% 的不透明度来代替 0% 的不透明度。有效隐藏元素而不会引起问题,并且淡入/淡出运行良好。


疑难解答

为了确保我没有在所有非控件视图的顶部绘制电影,我将 AVPlayerLayer 移到了另一个视图 videoView

UIView(self.view)\ | UIView(视频视图) | UIImageView(广告横幅) | UIImageView(另一个广告横幅) | ... | UIView(控件视图)\ * | UIView [一些电影播放器​​控件] | UIView [更多电影播放器​​控件] *

我明确地打电话给sendSubviewToBack:videoViewbringSubviewToFront:controlsView,但仍然没有爱。如果我第一次将重叠广告添加到视图层次结构中时不调用setHidden:YES,我可以在屏幕上看到它们。关键是:广告也会在正确的时间消失(响应我的动画块中的overlayImage.alpha = 0.0f),所以我知道我的动画块没问题。

这是一个代码 sn-p,用于将广告横幅添加到我的电影播放器​​的视图中:

for(MyCustomAdBannerClass *overlay in overlays)

    UIImageView *overlayImage =
    [[UIImageView alloc] initWithImage:
     [UIImage initWithData:
      [NSData dataWithContentsOfURL:[overlay contentURL]]]];
    UIViewAutoresizing autoresizingFlags =
        UIViewAutoresizingNone;
    CGFloat x, y, width, height;
    width = [overlay width];
    height = [overlay height];
    // <snip> set x, y, autoresizing values of the above vars
    [overlayImage setFrame:CGRectMake(x, y, width, height)];
    [overlayImage setAutoresizingMask:autoresizingFlags];
    [self.view addSubview:overlayImage];


for(UIView *subview in self.view.subviews)

    if(subview == controlsView)
        [self.view bringSubviewToFront:subview];
    else if(subview == videoView)
        [self.view sendSubviewToBack:subview];
    else
        [subview setHidden:YES];

这是我用于添加叠加层出现/消失回调的代码(overlay 是一个对象,其中包含有关何时显示叠加层以及显示多长时间的信息,overlayImage 是包含实际广告横幅的 UIImageView ):

[self.player
 addBoundaryTimeObserverForTimes:[NSArray arrayWithObject:
                                  [overlay startTime]]
 queue:dispatch_get_main_queue()
 usingBlock:^
     [UIView
      animateWithDuration:0.7
      animations:^
          overlayImage.alpha = 1.0f;
          dispatch_time_t popTime =
          dispatch_time(DISPATCH_TIME_NOW,
                        [overlay duration] * NSEC_PER_SEC);
          dispatch_after(popTime, dispatch_get_main_queue(),
                         ^(void)
                             [UIView
                              animateWithDuration:0.7
                              animations:^
                                  overlayImage.alpha = 0.0f;
                                  [overlayImage removeFromSuperview];
                              ];
                          ];
                ];
];

正如我所说,overlayImage.alpha = 0.0f; 调用正在执行正确

注意:刚尝试在首次添加视图时设置overlay.alpha = 0.5f; 而不是0.0f。叠加层现在正确淡入。因此,让视图 100% 不可见会发生一些奇怪的事情,这会阻止它在以后再次显示。没有崩溃,所以它不仅仅是引用释放的内存。


尝试的解决方法

我尝试将所有广告叠加层发送到 videoView 后面,然后当每一个要显示时,我都调用了

[overlayImage removeFromSuperview];
[self.view insertSubview:overlayImage aboveView:videoView];
// dispatch hide animation

仍然没有显示它们,但是当我省略 setHidden:YES 时仍然会正确淡出。

【问题讨论】:

hidden 和 alpha 属性是完全分开的。如果您隐藏视图,更改 alpha 将不会显示它,直到您取消隐藏它。 @ughoavgfhw:实际上,这是不正确的。即使我将方法更改为 setAlpha:0.0f 而不是 setHidden:YES 行为是相同的(没有显示),然后当我省略 setAlpha:0.0f 调用时,它从一开始就显示,然后在正确的时间消失。跨度> 【参考方案1】:

请注意,我现在使用的是0.001f 而不是0.0f,并且没有显示问题。不过,我仍然很想弄清楚它为什么会这样。

【讨论】:

以上是关于UIView 显示顺序问题?的主要内容,如果未能解决你的问题,请参考以下文章

UIView 子视图的顺序?

顺序 UIView 转换

如何更改 UIView 的 z 索引或堆栈顺序?

UIView的层介绍

UIView的层介绍

iOS 分类:按顺序添加视图