自定义Airplaybutton的外观

我使用标准的渐变叠加(在Photoshop中完成),使button看起来更好,在我的应用程序。 我添加了一个Airplaybutton,但美观不匹配。

在这里输入图像说明

我真的想把它放在一个渐变层,所以它匹配,但我能find的任何东西只显示如何用PNG,而不是现有的UIView。 如果不是渐变层,我只需要以任何方式改变Apple Airplaybutton的外观,同时保持其function的完整性。

设置代码很简单:

MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame:frame]; [volumeView setShowsVolumeSlider:NO]; [bottomPanel addSubview:volumeView]; 

我怎样才能得到这个匹配我的控件的外观?

我认为自iOS 6以来有更好的解决scheme:使用

- (void)setRouteButtonImage:(UIImage *)image forState:(UIControlState)state;

在MPVolumeView上。

请参阅https://developer.apple.com/Library/ios/documentation/MediaPlayer/Reference/MPVolumeView_Class/index.html#//apple_ref/occ/instm/MPVolumeView/setRouteButtonImage:forState

在接受@Erik B的回答并奖励了他之后,我发现需要更多的调整才能使其工作。 我在这里张贴为了未来的SOsearch者的利益。

我看到的问题是,button的内部机制将分配基于当前airplay状态的图像。 因此,如果Airplay接收器离开,或者状态发生了某种变化,那么在初始化过程中我所做的任何自定义操作都不会停止。 为了解决这个问题,我在button的alpha键上设置了KVO观察值。 我注意到,button总是淡入/淡出,这是一个alpha上的animation。

 MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame:CGRectZero]; [volumeView setShowsVolumeSlider:NO]; for (UIButton *button in volumeView.subviews) { if ([button isKindOfClass:[UIButton class]]) { self.airplayButton = button; // @property retain [self.airplayButton setImage:[UIImage imageNamed:@"airplay.png"] forState:UIControlStateNormal]; [self.airplayButton setBounds:CGRectMake(0, 0, kDefaultIconSize, kDefaultIconSize)]; [self.airplayButton addObserver:self forKeyPath:@"alpha" options:NSKeyValueObservingOptionNew context:nil]; } } [volumeView sizeToFit]; 

然后我观察buttonalpha的改变的价值。

 - (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.png"] forState:UIControlStateNormal]; [(UIButton *)object setBounds:CGRectMake(0, 0, kDefaultIconSize, kDefaultIconSize)]; } } 

如果您销毁button,请不要忘记移除观察者

 - (void)dealloc { [self.airplayButton removeObserver:self forKeyPath:@"alpha"]; … } 

基于代码观察,如果Apple更改MPVolumeView的内部视图层次结构以添加/删除/更改视图,以便出现不同的button,则该button将会中断。 这使得它变得脆弱,所以要自己承担风险,或者提出一个计划,以防万一。 我一直在使用它一年以上没有问题的生产。 如果你想看到它的实际情况,请查看Ambiance中的主播放器屏幕

我终于find了一个蓝牙耳机,以便我可以testingbutton。 改变它的外观非常简单。 代码如下:

 for (UIButton *button in volumeView.subviews) { if ([button isKindOfClass:[UIButton class]]) { [button setImage:[UIImage imageNamed:@"custom-route-button.png"] forState:UIControlStateNormal]; [button sizeToFit]; } } 

这就是它的全部。

上面的代码不适用于我(AirPlaybutton后来添加)。 作为一种解决方法,您可以在UI中使用标准UIButton,并在(隐藏) MPVolumeViewbutton中触发AirPlay

 for (UIButton *button in volumeView.subviews) { if ([button isKindOfClass:[UIButton class]]) { [button sendActionsForControlEvents:UIControlEventTouchUpInside]; } } 

副作用是当只有一个路由可用时,该button不会自动隐藏,这可能是也可能不是所期望的行为。

我创build了一个完美的自定义方法…

 -(void)airplayIcon:(CGRect)rect { UIView *aiplayView = [[UIView alloc] initWithFrame:self.bounds]; aiplayView.clipsToBounds = true; aiplayView.backgroundColor = [UIColor clearColor]; [self addSubview:aiplayView]; MPVolumeView *airplayVolume = [[MPVolumeView alloc] initWithFrame:aiplayView.bounds]; airplayVolume.showsVolumeSlider = false; [aiplayView addSubview:airplayVolume]; for (UIButton *button in airplayVolume.subviews) { [button setFrame:self.bounds]; if ([button isKindOfClass:[UIButton class]]) { [button setImage:[UIImage imageNamed:@"normal.png"] forState:UIControlStateNormal]; [button setImage:[UIImage imageNamed:@"selected.png"] forState:UIControlStateSelected]; [button sizeToFit]; } } }