UIView проблема порядка отображения? - PullRequest
2 голосов
/ 01 июня 2011

Проблема

При отображении пользовательского контроллера плеера на экране (iOS 4) я использую AVPlayerLayer для отображения. Я хочу создать несколько оверлеев поверх плеера (рекламные баннеры, элементы управления плеером и т. Д.). На данный момент это работает абсолютно нормально со следующей иерархией:

UIView(self.view)\
                 | UIView(controlsView)\
                 *                     | UIView [some movie player controls]
                                       | UIView [some more movie player controls]
                                       *

AVPlayerLayer - это подслой self.view. При загрузке плеера я сначала добавляю слой к self.view и вызываю bringSubviewToFront: на controlsView, а затем обнаруживаю касания по нему и программно показываю / исчезаю по таймеру / как угодно. Здесь нет проблем.

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

UIView(self.view)\
                 | UIImageView (ad banner)
                 | UIImageView (another ad banner)
                 | ...
                 | UIView(controlsView)\
                 *                     | UIView [some movie player controls]
                                       | UIView [some more movie player controls]
                                       *

При загрузке плеера я затем присоединяю к своему экземпляру AVPlayer некоторые addBoundaryTimeObserverForTimes:queue:usingBlock: звонки для постепенного исчезновения рекламных баннеров в соответствующее время. При этом я добавляю UIImageView s к self.view как подпредставления без явного упорядочения (следовательно, они должны быть нарисованы поверх всего остального) и setHidden:YES на них.

Я NSLog 'd, и эти блоки затухания выполняются правильно, установив view.alpha = 1.0f и view.alpha = 0.0f для показа и скрытия соответственно на рекламных баннерах, но вообще ничего не появляется, даже если явно установить UIImage отображается при просмотре известного рабочего локального изображения и в кадре на (0, 0, 320, 480), плюс установка autoresizingMask из

UIViewAutoresizingFlexibleTopMargin  |
UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin;

По умолчанию UIViewContentMode (должно быть UIViewContentModeScaleToFill).


Решение, которое я нашел для решения проблемы

На самом деле это вообще не решает проблему, но теперь я использую непрозрачность 0,1% в качестве замены непрозрачности 0%. Эффективно скрывает элемент, не вызывая проблем, и затухания / затухания работают хорошо.


Поиск и устранение неисправностей

Чтобы убедиться, что я не рисовал фильм поверх всех неуправляемых видов, я переместил AVPlayerLayer в дополнительный вид, videoView:

UIView(self.view)\
                 | UIView(videoView)
                 | UIImageView (ad banner)
                 | UIImageView (another ad banner)
                 | ...
                 | UIView(controlsView)\
                 *                     | UIView [some movie player controls]
                                       | UIView [some more movie player controls]
                                       *

Я явно звоню sendSubviewToBack:videoView и bringSubviewToFront:controlsView, но все равно не люблю. Я могу видеть оверлейные объявления на экране, если не позвоню setHidden:YES, когда впервые добавлю их в иерархию просмотра. Кикер таков: объявление также исчезает в правильное время (в ответ на overlayImage.alpha = 0.0f в моих блоках анимации), поэтому я знаю, что мои блоки анимации в порядке.

Вот фрагмент кода для добавления рекламных баннеров в вид моего проигрывателя фильмов:

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 при первом добавлении видов. Наложение FADES IN теперь правильно. Таким образом, происходит нечто странное с тем, чтобы сделать представление на 100% невидимым, что не позволяет его снова показывать позже. Никаких сбоев, так что это не просто ссылка на освобожденную память.


Попытка обхода

Я попытался отправить все наложения рекламы за videoView, а затем, когда нужно было показать каждый из них, я позвонил

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

Все еще не показывает их, но все равно исчезает, когда я опускаю setHidden:YES.

1 Ответ

0 голосов
/ 02 июня 2011

Обратите внимание, что теперь я использую 0.001f вместо 0.0f и проблем с отображением нет.Я все еще хочу выяснить, почему он это делает.

...