当使用MPVolumeView时,如何隐藏灰色的音量叠加层?

13

我在播放视频时,将MPVolumeView添加到了上面。问题在于,每当我使用MPVolumeView调整音量时,标准的灰色音量叠加层就会出现(当您在iPhone上使用摇杆开关时会出现此图层)。有没有办法禁用标准的灰色叠加层?


你找到解决方案了吗?不幸的是,myyellOw的回答对我没有用。 - user1349663
@user1349663 我认为我已经获得了一些关于更可重复的解决方案的见解。请看下面我的答案。 - ravron
4个回答

18

可能我有点晚了,但我认为我有一些有用的东西要补充。如果你只是在寻找一个答案,请跳到我是如何解决它的?

MPVolumeView 是什么?
MPVolumeView 类用于将一个滑块放置在屏幕上以控制系统音量。它应该可以防止系统音量叠加层在其上出现,但有时不起作用。我遇到了这个问题,当我将自己的 MPVolumeView 添加到视图层次结构中时,但当我拖动滑块时仍然看到叠加层出现。

MPVolumeView 如何检测其是否可见?
这就是我问自己的问题。某种程度上,该类会检测它是否可见,并告诉系统相应地隐藏或显示系统音量叠加层。这是因为苹果公司实际上并不希望您只是使用该类来防止叠加层出现,而不向用户显示滑块 UI(例如 myell0w 的回答中所述)。

这就是我认为 MPVolumeView 尝试检查自己是否真正可见的方式:

  1. 当视图添加到超级视图中时,由 viewWillMoveToSuperview: viewDidMoveToSuperview 检测到,它会启动一个短定时器。
  2. 当计时器触发时,视图通过递归地检查 superview 属性来遍历其祖先视图树。
  3. MPVolumewView 检查每个祖先视图都具有 hidden = NOalpha 大于某些小值(可能为 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];
}

并且每次需要强制视图重新评估它是否可见时,我都会调用它。这种方法只是假装重新将视图添加到层次结构中。一旦我满足了视图评估的条件(每个祖先都不隐藏或者alpha非常低),我就调用它,然后遮罩停止显示。在我上面的示例代码中,我将添加一行:

- (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
}

太棒了!非常有效。谢谢。 - tonymontana
您还可以将视图添加到键窗口中,并将其放置在视图外部。 - Saren Inden
@SarenInden 是的,但我希望我的用户也能够实际使用该控件。 - ravron
@ravron,您能否确认此解决方案在iOS 10+上仍然有效? - Works On Mine
@WorksOnMine 我不知道这个解决方案是否仍然有效,但测试应该很容易——我鼓励你去尝试并回报! - ravron

7

通常情况下,当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。


@myello0w:但是你什么时候可以从应用程序中更改音量? - Nirmalsinh Rathod

1
这可能会有所帮助。
-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    self.volumeView.hidden = NO;
    [self.volumeView willMoveToSuperview:self.volumeView.superview];
    [self.volumeView didMoveToSuperview];

}

0

最简单的方法是......

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

参考了这个线程 应用音乐播放器音量通知


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接