我已经试着解决这个问题两天了,我放弃了。我正在尝试实现一个自定义的airplay按钮(我必须是因为背景是白色的,按钮必须是黑色的)。我在interfacebuilder中添加了一个视图,并为它选择了mpVolumeView。然后,我建立了连接并编写了以下代码;
viewDidLoad.. {
.....
[_volumeView setShowsVolumeSlider:NO];
for (UIButton *button in _volumeView.subviews) {
if ([button isKindOfClass:[UIButton class]]) {
[button setImage:[UIImage imageNamed:@"airplay_icon.png"] forState:UIControlStateNormal];
[button addObserver:self forKeyPath:@"alpha" options:NSKeyValueObservingOptionNew context:nil];
[button addTarget:self action:@selector(switchAirplayButton) forControlEvents:UIControlEventTouchUpInside];
[button sizeToFit];
}
}
[_volumeView sizeToFit];
}
-(void)switchAirplayButton {
for (UIButton *button in _volumeView.subviews) {
if ([button isKindOfClass:[UIButton class]]) {
NSLog(@"%d", _controlBar.player.airPlayVideoActive);
if(_controlBar.player.airPlayVideoActive) {
[button setImage:[UIImage imageNamed:@"airplay_icon_pressed.png"] forState:UIControlStateNormal];
} else [button setImage:[UIImage imageNamed:@"airplay_icon.png"] forState:UIControlStateNormal];
[button sizeToFit];
}
}
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([object isKindOfClass:[UIButton class]] && [[change valueForKey:NSKeyValueChangeNewKey] intValue] == 1) {
[(UIButton *)object setImage:[UIImage imageNamed:@"airplay_icon.png"] forState:UIControlStateNormal];
[(UIButton *)object sizeToFit];
}
}"player“是一个基于AVPLayer的单音播放器。但是,当检查airPlay是否处于活动状态时,它总是返回false。也许只是因为我使用的是声音,而不是视频。
所以我的问题是,我怎么才能把按钮改成...当airplay正在播放流媒体时(就像苹果将其设置为蓝色一样),我们假设它是橙色的(只是为了与界面的其他部分相匹配)。我试过所有的方法,但就是一点也不起作用。请帮帮我。
发布于 2012-09-11 07:14:47
编辑:
虽然下面的代码可以在iOS 5和6上运行,但从iOS 6.0开始,有一种官方方法可以做到这一点,这要容易得多。只需查看MPVolumeView的文档,特别是– setRouteButtonImage:forState:。
====的老答案:====
这很难实现,但我为iOS 5.0+找到了一种方法。首先,将以下行添加到您的ViewController:
#import <AudioToolbox/AudioToolbox.h>在你的viewDidLoad中,你已经做对了大部分事情,这是我的代码:
for (id current in self.volumeView.subviews){
if([current isKindOfClass:[UIButton class]]) {
UIButton *airPlayButton = (UIButton*)current;
self.airPlayButton = airPlayButton;
[self setAirPlayButtonSelected:[self isAirPlayActive]];
[airPlayButton addObserver:self forKeyPath:@"alpha" options:NSKeyValueObservingOptionNew context:nil];
}
}下面是助手setAirPlayButtonSelected方法,它只是设置图像:
- (void)setAirPlayButtonSelected:(BOOL)selected {
UIImage* image;
if (selected) {
image = [UIImage imageNamed:@"button-airplay-selected"];
}else {
image = [UIImage imageNamed:@"button-airplay"];
}
[self.airPlayButton setImage:image forState:UIControlStateNormal];
[self.airPlayButton setImage:image forState:UIControlStateHighlighted];
[self.airPlayButton setImage:image forState:UIControlStateSelected];
}为了完整起见,observeValueForKeyPath
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (object == self.airPlayButton && [[change valueForKey:NSKeyValueChangeNewKey] intValue] == 1) {
[self setAirPlayButtonSelected:[self isAirPlayActive]];
}
}现在有趣的部分来了。下面是isAirPlayActive助手方法。它使用AudioSession框架来确定当前播放的audioSource。
- (BOOL)isAirPlayActive{
CFDictionaryRef currentRouteDescriptionDictionary = nil;
UInt32 dataSize = sizeof(currentRouteDescriptionDictionary);
AudioSessionGetProperty(kAudioSessionProperty_AudioRouteDescription, &dataSize, ¤tRouteDescriptionDictionary);
if (currentRouteDescriptionDictionary) {
CFArrayRef outputs = CFDictionaryGetValue(currentRouteDescriptionDictionary, kAudioSession_AudioRouteKey_Outputs);
if(CFArrayGetCount(outputs) > 0) {
CFDictionaryRef currentOutput = CFArrayGetValueAtIndex(outputs, 0);
CFStringRef outputType = CFDictionaryGetValue(currentOutput, kAudioSession_AudioRouteKey_Type);
return (CFStringCompare(outputType, kAudioSessionOutputRoute_AirPlay, 0) == kCFCompareEqualTo);
}
}
return NO;
}因此,所有这些代码都会在应用程序启动时正确地更改AirPlay按钮。那更新呢?我们需要监听AudioSource的变化。将以下代码行添加到viewDidLoad中
AudioSessionAddPropertyListener (kAudioSessionProperty_AudioRouteChange, audioRouteChangeCallback, (__bridge void*)self);别忘了在dealloc中注销
- (void)dealloc {
[self.airPlayButton removeObserver:self forKeyPath:@"alpha"];
AudioSessionRemovePropertyListenerWithUserData(kAudioSessionProperty_AudioRouteChange, audioRouteChangeCallback, (__bridge void*)self);
}并将此C函数添加到视图控制器的@implementation之上
void audioRouteChangeCallback (void *inUserData,
AudioSessionPropertyID inPropertyID,
UInt32 inPropertyValueSize,
const void *inPropertyValue) {
if (inPropertyID != kAudioSessionProperty_AudioRouteChange) {
return;
}
CFDictionaryRef routeChangeDictionary = inPropertyValue;
CFDictionaryRef currentRouteDescriptionDictionary = CFDictionaryGetValue(routeChangeDictionary, kAudioSession_AudioRouteChangeKey_CurrentRouteDescription);
CFArrayRef outputs = CFDictionaryGetValue(currentRouteDescriptionDictionary, kAudioSession_AudioRouteKey_Outputs);
if(CFArrayGetCount(outputs) > 0) {
CFDictionaryRef currentOutput = CFArrayGetValueAtIndex(outputs, 0);
CFStringRef outputType = CFDictionaryGetValue(currentOutput, kAudioSession_AudioRouteKey_Type);
[(__bridge SettingsViewController*)inUserData setAirPlayButtonSelected:CFStringCompare(outputType, kAudioSessionOutputRoute_AirPlay, 0) == kCFCompareEqualTo];
}
}正如您所看到的,它所做的全部工作就是确定AirPlay输出源是否处于活动状态,并相应地调用setAirPlayButtonSelected方法。
请参阅苹果的Audio Session Programming Guide,特别是this section,了解回调的确切工作方式等的详细信息。
发布于 2012-09-12 06:38:42
看看这个类似的link here.
我不确定这是否有效,但尝试制作一个带有airplay符号的黑色按钮,然后将其放在很难看到的airplay按钮的顶部。您应该将用户交互设置为禁用。试试看,这可能是一个更简单的解决方案。
*不要忘记在属性检查器和身份检查器上禁用用户交互。
https://stackoverflow.com/questions/12318377
复制相似问题