Скрыть наложение серого тома при использовании MPVolumeView?

Я поставил MPVolumeView поверх фильма, который я играю. Проблема в том, что всякий раз, когда я настраиваю громкость с помощью MPVolumeView, появляется стандартное серое наложение громкости (тот, который появляется при использовании переключателя на iPhone). Есть ли способ отключить стандартное серое наложение?


person cannyboy    schedule 15.09.2011    source источник
comment
Вы нашли решение для этого? К сожалению, ответ myyellOw мне не помог.   -  person user1349663    schedule 22.01.2014
comment
@user1349663 user1349663 Я думаю, что получил некоторое представление о более воспроизводимом решении. Взгляните на мой ответ ниже.   -  person ravron    schedule 26.10.2014


Ответы (4)


Я могу немного опоздать, но я думаю, что могу добавить что-то полезное. Если вы просто ищете ответ, перейдите к разделу Как я это исправил?

Что такое MPVolumeView?
MPVolumeView используется для размещения на экране ползунка, который управляет громкостью системы. Предполагается, что это предотвращает появление наложения системного тома, когда оно отображается на экране, но иногда этого не происходит. Я столкнулся с этой проблемой, когда добавил свой собственный MPVolumeView в иерархию представлений, но все еще видел, что наложение появляется при перетаскивании ползунка.

Как MPVolumeView определяет, что он виден?
Это вопрос, который я задал себе. Каким-то образом класс определяет, виден он или нет, и указывает системе скрывать или отображать наложение системного тома соответствующим образом. Это связано с тем, что Apple на самом деле не хочет, чтобы вы использовали класс только для предотвращения появления наложения, фактически не отображая пользовательский интерфейс слайдера для пользователя (как в ответе myell0w).

Вот как, я думаю, MPVolumeView пытается проверить, действительно ли он виден:

  1. Когда представление добавляется в суперпредставление, что определяется viewWillMoveToSuperview: и viewDidMoveToSuperview, оно запускает короткий таймер.
  2. Когда таймер срабатывает, представление пересекает дерево предков представления, рекурсивно исследуя свойство superview.
  3. MPVolumewView проверяет, что у каждого из его предков hidden = NO и alpha больше некоторого небольшого значения (вероятно, 0,05).

Могут быть и другие проверки, о которых я не знаю, так как этот код, конечно, с закрытым исходным кодом. Таймер на шаге 1 существует, чтобы код, подобный следующему, не «обманул» представление:

MPVolumeView *volView = [[MPVolumeView alloc] init];
[self.view addSubview:volView];
volView.hidden = YES;

потому что он будет проверять свойство hidden не сразу, а через некоторое время, после того как оно уже будет установлено в YES.

Как я во всем этом разобрался? Ключевой находкой было то, что экземпляр MPVolumeView вызывал isHidden в своем суперпредставлении, как показано в следующей трассировке стека:

Трассировка стека MPVolumeView

В чем была моя проблема?
Короче говоря, я сделал что-то вроде этого:

- (void)viewDidLoad {
    // Add an MPVolumeView to my view
    self.volView = [[MPVolumeView alloc] init];
    [self.view addSubview:self.volView];
    self.volView.hidden = YES;
}

- (void)someButtonTouched {
    // Show the MPVolumeView (and hopefully hide the system overlay)
    self.volView.hidden = NO;
}

Но когда я перетаскивал ползунок только что появившегося MPVolumeView, оверлей все равно появлялся. Я понял, что это произошло потому, что во время создания экземпляра MPVolumeView его супервизор был скрыт.

Как я это исправил?
Как только я понял, как класс MPVolumeView оценивает видимость объекта, у меня появился простой способ «обмануть» его. Я добавил следующий метод в класс, отвечающий за MPVolumeView:

- (void)refreshVolumeView {
    [self.volView willMoveToSuperview:self];
    [self.volView didMoveToSuperview];
}

и вызывал его каждый раз, когда мне нужно заставить представление переоценивать, было ли оно видимым. Этот метод просто делает вид, что повторно добавляет представление в иерархию. Как только я удовлетворяю условиям, которые оценивает представление (каждый предок не скрыт или имеет очень низкую альфу), я вызываю его, и наложение перестает отображаться. В приведенном выше примере кода я бы добавил одну строку:

- (void)viewDidLoad {
    // Add an MPVolumeView to my view
    self.volView = [[MPVolumeView alloc] init];
    [self.view addSubview:self.volView];
    self.volView.hidden = YES;
}

- (void)someButtonTouched {
    // Show the MPVolumeView (and hopefully hide the system overlay)
    self.volView.hidden = NO;
    [self refreshVolumeView];  // <<< This line was added
}
person ravron    schedule 25.10.2014
comment
Отличный ответ! Работал как шарм. Спасибо. - person tonymontana; 11.11.2015
comment
Вы также можете просто добавить представление в свое ключевое окно и поместить его за пределы представления. - person Saren Inden; 06.09.2016
comment
@SarenInden да, но я бы хотел, чтобы мои пользователи также могли использовать элемент управления. - person ravron; 06.09.2016
comment
@ravron Не могли бы вы подтвердить, работает ли это решение на iOS 10+? - person Works On Mine; 04.08.2017
comment
@WorksOnMine Я не знаю, действительно ли это решение все еще действует, но его должно быть легко проверить — я призываю вас сделать это и сообщить! - person ravron; 04.08.2017

Обычно, когда виден MPVolumeView, HUD не появляется. Я использую следующий метод в своем приложении, и он работает нормально:

+ (void)preventSystemVolumePopup {
    // Prevent Audio-Change Popus
    MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame:CGRectMake(-2000., -2000., 0.f, 0.f)];
    NSArray *windows = [UIApplication sharedApplication].windows;

    volumeView.alpha = 0.1f;
    volumeView.userInteractionEnabled = NO;

    if (windows.count > 0) {
       [[windows objectAtIndex:0] addSubview:volumeView];
    }
}

По сути, он просто добавляет вид объема в первое окно в месте, где его никто не может видеть, и, таким образом, предотвращает отображение HUD системного объема. Интересно, почему вы видите этот HUD, хотя вы ставите объемный вид над своим фильмом.

person myell0w    schedule 08.06.2012
comment
@myello0w: а когда можно изменить громкость из приложения? - person Nirmalsinh; 13.05.2015

Это может помочь.

-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    self.volumeView.hidden = NO;
    [self.volumeView willMoveToSuperview:self.volumeView.superview];
    [self.volumeView didMoveToSuperview];

}
person Umair    schedule 01.09.2016

Самый простой способ сделать это.....

- (void) viewDidLoad 
{
    [super viewDidLoad];
    MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame: CGRectZero];
    [self.view addSubview: volumeView];
    ...
}

взято из этой темы уведомление о громкости applicationMusicPlayer

person Sourabh Sharma    schedule 17.12.2014