Ios 与新苹果音乐应用程序中的动态状态栏相同
是否可以在新的苹果音乐应用程序中动态着色状态栏 编辑: iOS 8.4中的新苹果音乐应用程序具有此功能Ios 与新苹果音乐应用程序中的动态状态栏相同,ios,objective-c,user-interface,dynamic,statusbar,Ios,Objective C,User Interface,Dynamic,Statusbar,是否可以在新的苹果音乐应用程序中动态着色状态栏 编辑: iOS 8.4中的新苹果音乐应用程序具有此功能 打开应用程序 选择并播放歌曲(状态栏为白色) 向下滑动播放器控制器以查看“我的音乐”控制器(它有黑色的状态栏,可能您必须返回导航层次结构) 现在只需向上/向下滑动即可查看动态状态栏的更改 编辑2: 苹果的文档似乎不允许我们现在就使用它(ios8.4)。将来可能会在iOS 9上提供 编辑3: 在iOS 9中似乎还不可用。正在考虑如何在没有专用API的情况下实现此功能 我认为可能有一个解决方
- 打开应用程序
- 选择并播放歌曲(状态栏为白色)
- 向下滑动播放器控制器以查看“我的音乐”控制器(它有黑色的状态栏,可能您必须返回导航层次结构)李>
- 现在只需向上/向下滑动即可查看动态状态栏的更改
ios8.4
)。将来可能会在iOS 9上提供
编辑3:
在iOS 9中似乎还不可用。正在考虑如何在没有专用API的情况下实现此功能
我认为可能有一个解决方案,第二个UIWindow覆盖您的状态栏
也许可以将状态栏的屏幕截图(从主窗口拍摄)不断地显示在图像上,对其应用一些过滤器,并在第二个窗口(在“真实”状态栏上方)显示此“假状态栏图像”
你可以用第二个“假”状态栏做你想做的事。乍一看,它看起来像是从状态栏操纵快照,但状态栏两端都是活动的,所以情况并非如此
乍一看,它看起来像是iOS 8.4中引入的一些新api,但在查看该api后,我找不到任何与此相关的内容
我觉得很奇怪,苹果会在自己的应用程序中使用私有API。这会给开发人员带来一些非常糟糕的例子,但同样,没有任何公共工具可以让您在live statusbar上拥有两种样式
这就给我们留下了私有api或黑魔法 我99.99%确信使用公共API无法做到这一点(很容易),因为我尝试了几乎所有的方法(我个人也不认为这是他们状态栏的神奇方法,但相反,他们的应用程序能够检索状态栏视图,然后只对其应用掩码)
我敢肯定的是,你可以做你自己的状态栏,有一个库,不幸的是,非常旧的一个,所以我真的不能说这是否有效,但似乎仍然有人使用它
但使用图书馆的方式,我认为可能会有一个解决方案,当然,需要大量的工作,但是可行的,尽管不是“活的”。简而言之,您可以这样做:
- 拍摄前20个像素的屏幕截图(状态栏)
- 从这个屏幕截图中,(你可以改进它,让它搜索黑色边缘,这样你可以保留绿色电池和透明度)这将使你的叠加遮罩和假状态栏
- 覆盖状态栏:背景视图遮罩实际状态栏和刚刚创建的alpha图像
- ,所有被遮掩的东西都会变成白色
- 根据用户滚动更改遮罩的高度
现在,您应该能够正确滚动并正确更改颜色。它留下的唯一问题是状态栏不存在,但它真的存在吗?一旦你向外滚动,你立即移除覆盖,让它刷新。当您滚动到最顶端时,也会执行相同的操作,但在这种情况下,您会将状态栏的颜色更改为白色(无动画),以使其适合您的状态。它不会只活一小段时间
希望有帮助 重复Jiri的答案,这会让你非常接近。替换为。要处理视图控制器之间的模式转换,我使用。我们假设self.view中有一个imageView:“art”和frame:CGRect(0,0,self.view.bounds.size.width,self.view.bounds.size.width)。需要一点按摩,但你明白要点了。注意:虽然我们没有“带电”,但我们最多只能关机一秒钟,电池颜色也不会保留。此外,还需要将CWStatusBarNotification.m中的动画时间设置为零。(notificationAnimationDuration属性)
因为我们对计时器有很强的引用,并且设置和失效发生在同一个线程上,所以不必担心计时器无法失效。
最终结果应如下所示:
思考私有APIMAGE:顶部白色部分是第一个VC,带有白色状态栏和相册封面的部分是另一个VC(位于第一个VC上方)。问题是状态栏的上半部分为深色,下半部分为浅色?不,这不是问题。iOS 8.4中的新苹果音乐应用程序具有此功能。您只需打开应用程序,选择一首歌曲(状态栏为白色),然后向下滑动此控制器以查看“我的音乐”控制器(状态栏为黑色)。现在只需向上/向下滑动即可查看动态状态栏的更改。感谢更新的信息。我知道,这个问题没有简单的解决办法。您可以查看此项目以供参考,它使用的方法与我在回答中建议的类似(但实现可滚动的状态栏行为)。作者拍摄状态栏的快照,并将其作为图像添加到假状态栏窗口中。为什么苹果使用私有API会很奇怪呢?我相信苹果在后台使用了很多私有的东西,但是开发者显然无法使用这些东西。。我觉得有点不对劲。不管是谁否决了这个答案,你能不能提供你的意见,说明为什么这个答案不好,这样我们就可以重复一下了?非常感谢。奖励这个答案是因为它提供了私人api意见,并提供了一个示例(即使它不成功)。真正的答案是,我们可能都必须等待。他们也在使用私有API来制作in/out表视图A-Z索引的动画,它肯定不是公开的,而且Apple Music中有做私有UI事情的先例:(
#import "CWStatusBarNotification.h"
#define kStatusTextOffset 5.4 // (rough guess of) space between window's origin.y and status bar label's origin.y
@interface M_Player () <UIGestureRecognizerDelegate>
@property (retain) UIView *fakeStatusBarView;
@property (retain) CWStatusBarNotification *fakeStatusBar;
@property (retain) UIImageView *statusImgView;
@property (retain) UIImageView *statusImgViewCopy;
@property (retain) UIWindow *window;
@property (strong, nonatomic) NSTimer *statusTimer;
@end
@implementation M_Player
@synthesisze fakeStatusBarView, fakeStatusBar, statusImgView, statusImgViewCopy, window, statusTimer;
-(void)viewDidLoad{
self.window = [[UIApplication sharedApplication] delegate].window;
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleStatusBarDrag:)];
pan.delegate = self;
[self.view addGestureRecognizer:pan];
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
if (!fakeStatusBar){
[self buildFakeStatusBar];
}
if (!statusTimer) {
[self setupStatusBarImageUpdateTimer];
}
// optional
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
[self setNeedsStatusBarAppearanceUpdate];
-(void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
[self destroyStatusBarImageUpdateTimer];
-(void)destroyFakeStatusBar{
[statusImgView removeFromSuperview];
statusImgView = nil;
[fakeStatusBarView removeFromSuperview];
fakeStatusBarView = nil;
fakeStatusBar = nil;
}
-(void)buildFakeStatusBar{
UIWindow *statusBarWindow = [[UIApplication sharedApplication] valueForKey:@"_statusBarWindow"]; // This window is actually still fullscreen. So we need to capture just the top 20 points.
UIGraphicsBeginImageContext(self.view.bounds.size);
[statusBarWindow.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGRect rect = CGRectMake(0, 0, self.view.bounds.size.width, 20);
CGImageRef imageRef = CGImageCreateWithImageInRect([viewImage CGImage], rect);
UIImage *statusImg = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
statusImg = [statusImg imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; // This allows us to set the status bar content's color via the imageView's .tintColor property
statusImgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 20)];
statusImgView.image = statusImg;
statusImgView.tintColor = [UIColor colorWithWhite:0.859 alpha:1.000]; // any color you want
statusImgViewCopy = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 20)];
statusImgViewCopy.image = statusImg;
statusImgViewCopy.tintColor = statusImgView.tintColor;
fakeStatusBarView = nil;
fakeStatusBar = nil;
fakeStatusBarView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 20)];
[fakeStatusBarView addSubview:statusImgView];
fakeStatusBar = [CWStatusBarNotification new];
fakeStatusBar.notificationStyle = CWNotificationStyleStatusBarNotification;
[fakeStatusBar displayNotificationWithView:fakeStatusBarView forDuration:CGFLOAT_MAX];
}
-(void)handleStatusBarDrag:(UIPanGestureRecognizer*)gestureRecognizer{
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
}
if (gestureRecognizer.state == UIGestureRecognizerStateChanged){
CGPoint convertedPoint = [self.window convertPoint:art.frame.origin fromView:self.view];
CGFloat originY = convertedPoint.y - kStatusTextOffset;
if (originY > 0 && originY <= 10) { // the range of change we're interested in
//NSLog(@"originY:%f statusImgView.frame:%@", originY, NSStringFromCGRect(statusImgView.frame));
// render in context from new originY using our untouched copy as reference view
UIGraphicsBeginImageContext(self.view.bounds.size);
[statusImgViewCopy.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGRect rect = CGRectMake(0, kStatusTextOffset + originY, self.view.bounds.size.width, 20);
CGImageRef imageRef = CGImageCreateWithImageInRect([viewImage CGImage], rect);
UIImage *statusImg = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
statusImgView.image = statusImg;
statusImgView.transform = CGAffineTransformMakeTranslation(0, kStatusTextOffset + originY);
}
// destroy
if (originY > 90) {
[self destroyFakeStatusBar];
}
}
if (gestureRecognizer.state == UIGestureRecognizerStateEnded){
}
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
-(void)setupStatusBarImageUpdateTimer{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^(){
// main thread
if (!statusTimer) {
statusTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(handleStatusTimer:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:statusTimer forMode:NSRunLoopCommonModes];
}
});
});
}
-(void)destroyStatusBarImageUpdateTimer{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^(){
// main thread
[statusTimer invalidate];
statusTimer = nil;
});
});
}
-(void)handleStatusTimer:(NSTimer*)timer{
UIWindow *statusBarWindow = [[UIApplication sharedApplication] valueForKey:@"_statusBarWindow"];
UIGraphicsBeginImageContext(CGSizeMake(self.view.bounds.size.width, 20));
[statusBarWindow.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGRect rect = CGRectMake(0, 0, self.view.bounds.size.width, 20);
CGImageRef imageRef = CGImageCreateWithImageInRect([viewImage CGImage], rect);
UIImage *statusImg = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
statusImg = [statusImg imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
statusImgViewCopy.image = statusImg;
}