先说下如何在App内部触发AirPlay
- 首先我们要拿到系统的按钮
MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame:CGRectMake(260, 407, 40, 40)];
[volumeView setShowsVolumeSlider:NO];
for (UIButton *button in volumeView.subviews) {
if ([button isKindOfClass:[UIButton class]]) {
self.airplayButton = button;
self.airplayButton.showsTouchWhenHighlighted = NO;
[self.airplayButton setImage:[UIImageimageNamed:@"fav_audios_airplay.png"] forState:UIControlStateNormal];
[self.airplayButton setBounds:CGRectMake(0, 0, 40, 40)];
[self.airplayButton addObserver:self forKeyPath:@"alpha"options:NSKeyValueObservingOptionNew context:nil];
}
}
[volumeView sizeToFit];
[self.view addSubview:volumeView];
还需要添加这一段来设置多一次图片和大小
- (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:[UIImageimageNamed:@"fav_audios_airplay.png"] forState:UIControlStateNormal];
[(UIButton *) object setBounds:CGRectMake(0, 0, 40, 40)];
}
}
在dealloc里面移除
- (void)dealloc {
[self.airplayButton removeObserver:self forKeyPath:@"alpha"];
}
- 通过以上代码,就能过获取到系统的按钮,并可以自定义一些样式.当然你也可以完全自定义一个另外的按钮.这个系统的按钮通过for循环找到后,仅仅持有下便可.
当自定按钮点击时,只要将持有的系统按钮响应下事件便可.效果是一样的.代码如下:
[self.airplayButton sendActionsForControlEvents:UIControlEventTouchUpInside];
此时iOS11以下的iPhone变会弹出设备选择框了,如下
40AA06A93D8F333454AE1A123D7254BA.jpg正常情况下,流程走到这里就完了.但是,万恶的产品汪给了一个变态的需求,我需要拿到用户点出这个弹框后没有选择投屏设备而是点击取消按钮收回弹框的事件......
呵呵呵呵呵呵呵额!!!
通过一顿视图调试后发现:
F961F34A-9B17-4DD0-B665-A00337484171.png
这层弹框,其实就是个window,所以我们要拿到这个window
- (BOOL)isPresentAirPlayChooseWindow:(BOOL)isAddTarget {
NSArray *windows = [UIApplication sharedApplication].windows;
for(UIWindow *w in windows) {
if([w isKindOfClass:NSClassFromString(@"_MPAVRoutingSheetSecureWindow")]) {
return YES;
}
}
return NO;
}
A9D75548-E428-4587-AC19-A937B6F835A0.png
上图中的3个按钮点击后都会触发弹框消失的时间,他们分别对应下图中的3个区域:
F5FDEF57-1805-4B33-BB28-2D1EB305B55C.png
所以我们找出window之后再拿到这三个按钮,绑定下事件就ok了
- (BOOL)isPresentAirPlayChooseWindow:(BOOL)isAddTarget {
NSArray *windows = [UIApplication sharedApplication].windows;
for(UIWindow *w in windows) {
if([w isKindOfClass:NSClassFromString(@"_MPAVRoutingSheetSecureWindow")]) {
if(isAddTarget) {
///<找到系统的 "取消按钮" 并捕捉事件
UIView *view = w.subviews.firstObject;
if([UIDevice currentDevice].systemVersion.floatValue < 11) {
[self addTargetForView_iOS10:view];
}else {
[self addTargetForView_iOS11:view];
}
}
return YES;
}
}
return NO;
}
- (void)addTargetForView_iOS10:(UIView *)view {
for(UIView *v in view.subviews) {
if([v isKindOfClass:[UIButton class]]) {
//找到第一个button
[((UIButton *)v) addTarget:self action:@selector(airplayChooseViewDismiss:) forControlEvents:UIControlEventTouchUpInside];
}else if(v.subviews.count > 1 && ![v isKindOfClass:[UIButton class]]) {
for(UIView *sv in v.subviews) {
if([sv isKindOfClass:[UIButton class]]) {
//2,3号button
[((UIButton *)sv) addTarget:self action:@selector(airplayChooseViewDismiss:) forControlEvents:UIControlEventTouchUpInside];
}
}
}
}
}
好了,大功告成.....
至于iOS11以上,系统层级变了.一番探索后发现和iOS11以下有截然区别.不是单单添加一层window那么简单,不是单单添加在单个app层面上的,貌似是和我们上拉下拉弹出的通知栏一个级别的.所以,没有所以...妈个鸡...
- (void)addTargetForView_iOS11:(UIView *)view {
/*
哦豁...
*/
}
网友评论