Скрыть серый объем наложения при использовании MPVolumeView? - PullRequest
13 голосов
/ 15 сентября 2011

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

Ответы [ 4 ]

16 голосов
/ 26 октября 2014

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

Что такое 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 stack trace

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

- (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
}
7 голосов
/ 08 июня 2012

Обычно, когда 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, даже если вы ставите объемный вид над фильмом?

1 голос
/ 01 сентября 2016

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

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

}
0 голосов
/ 17 декабря 2014

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

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

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

...