是否可以在新的 Apple Music应用中动态着色Module Module1
Sub Main()
Dim State As Action
State = AddressOf DoSomething1
State()
State = AddressOf DoSomething2
State()
Console.ReadLine() 'all the above works fine.
StateProp = AddressOf DoSomething1
'StateProp() ' **************** uncommenting this call causes compilation error: Property access must assign To the Property Or use its value.
Console.ReadLine()
End Sub
'trying to use this bit fails.
Dim m_checkstate As Action
Public Property StateProp() As Action
Get
Return m_checkstate
End Get
Set
Console.WriteLine("Changing state. Do some work")
m_checkstate = Value
End Set
End Property
Sub DoSomething1()
Console.WriteLine("Something1")
End Sub
Sub DoSomething2()
Console.WriteLine("Something2")
End Sub
End Module
?
编辑:
iOS 8.4中的新Apple Music应用程序具有此功能。
编辑2:
Apple文档似乎不允许我们立即使用它(statusBar
)。将来可能会iOS 8.4
使用。
编辑3:
似乎尚未在iOS 9
中提供。
答案 0 :(得分:3)
我99.99%肯定这不能使用公共API(轻松)完成,因为我几乎尝试了所有的东西(我个人也不认为这是他们状态栏的一些神奇方法,而是他们的应用程序能够检索状态栏视图,然后只需应用蒙版)。
我确信你可以做你自己的StatusBar并且有MTStatusBarOverlay库,不幸的是很老的,所以我无法确定它是否有效,但似乎还有人谁使用它。
但是使用库的方式,我认为可能存在确定的解决方案,需要大量的工作,但是可行,但不是“实时”。简而言之,你会这样做:
现在您应该能够正确滚动并正确更改颜色。它留下的唯一问题是状态栏不存在,但它真的存在吗?滚动后,立即删除叠加层,让它刷新。当您滚动到最顶部时,您将执行相同的操作,但在这种情况下,您将状态栏的颜色更改为白色(无动画),因此它适合您的状态。它只会在短时间内不活动。
希望它有所帮助!
答案 1 :(得分:2)
迭代Jiri的回答,这会让你非常接近。用MTStatusBarOverlay替换CWStatusBarNotification。为了处理视图控制器之间的模态转换,我使用MusicPlayerTransition。我们假设一个imageView:" art" in self.view with frame:CGRect(0,0,self.view.bounds.size.width,self.view.bounds.size.width)。需要一点按摩,但你得到了要点。注意:虽然我们没有"生活,"我们关闭的最多只有一秒钟,电池颜色不会被保留。此外,您需要将CWStatusBarNotification.m中的动画时间设置为零。 (notificationAnimationDuration属性)。
#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;
}
要使状态栏屏幕截图与实际状态栏保持同步,请设置计时器。在viewWillAppear中触发它,并在viewDidDisappear中将其杀死。
-(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;
}
因为我们对计时器和设置有强烈的引用并且在同一个线程上发生了失效,所以不必担心计时器无法失效。 最终结果应如下所示:
答案 2 :(得分:0)
乍一看,它看起来像是从状态栏操纵快照,但状态栏在两端都是实时的,所以情况并非如此。
乍一看,它看起来像iOS 8.4中引入的一些新api,但在查看api之后,我找不到任何与之相关的内容。
对我来说,苹果在她自己的应用程序中使用私有api似乎很奇怪。这会给开发人员带来一些非常糟糕的例子,但是再一次,没有公开可以让你在你的实时状态栏上有两种风格。
这给我们留下了私人api或黑魔法。
答案 3 :(得分:-1)
考虑如何在没有私有API的情况下实现此目的。
我认为第二个UIWindow可能会覆盖你的statusBar。
Adding view on StatusBar in iPhone
也许可以不断制作状态栏的截图(从主窗口拍摄)到图像,在其上应用一些过滤器并显示这个“假状态栏图像”&#39;在你的第二个窗口(上面&#39;真正的&#39; statusBar)。
你可以用第二个&#34;假的&#34;做你想做的事。状态栏。