ver puedo precio musica apple aparece ios objective-c user-interface dynamic statusbar

ios - puedo - La misma barra de estado dinámico que se encuentra en la nueva aplicación Apple Music



no puedo ver mi musica en mi iphone 6 (4)

A primera vista, parecía una manipulación de una instantánea desde la barra de estado, pero la barra de estado está activa en ambos extremos, por lo que no es así.

A segunda vista, parecía una nueva API que se introdujo en iOS 8.4, pero después de revisar la API no pude encontrar nada relacionado con eso.

Me parece muy extraño que Apple utilice apis privados en su propia aplicación. Esto daría como resultado un ejemplo realmente malo para los desarrolladores, pero nuevamente, no hay nada público que te permita tener dos estilos en tu barra de estado en vivo.

Esto nos deja con api privado o magia negra.

¿Es posible tener la statusBar colores dinámicamente que está en la nueva aplicación de Apple Music ?

Editar:

La nueva aplicación Apple Music en iOS 8.4 tiene esta característica.

  • Abre la aplicación.
  • Selecciona y reproduce una canción (la barra de estado es blanca)
  • Deslice el controlador del reproductor hacia abajo para ver el controlador "Mi música" (tiene una barra de estado negra, tal vez tendrá que volver a la jerarquía de navegación).
  • Ahora solo deslice hacia arriba / abajo para ver los cambios dinámicos de la barra de estado.

Edición 2:

La documentación de Apple no parece permitirnos usarla ahora ( iOS 8.4 ). Estará disponible probablemente en el futuro con iOS 9 .

Edición 3: Parece que todavía no está disponible en iOS 9 .


Estoy seguro al 99.99% de que esto no se puede hacer usando la API pública (fácilmente), porque probé casi todo lo que hay (personalmente tampoco creo que sea un método mágico de su barra de estado, sino que su aplicación es capaz de recuperar la vista de la barra de estado y luego simplemente aplicarle la máscara).

Estoy seguro de que puedes hacer tu propia StatusBar y hay MTStatusBarOverlay biblioteca MTStatusBarOverlay para eso, desafortunadamente muy antigua, así que realmente no puedo saber si eso funciona pero parece que todavía hay personas que lo usan.

Pero usando la forma en que lo hace la biblioteca, creo que podría haber una solución segura, que requiere mucho trabajo, pero es factible, aunque no "en vivo". En pocas palabras harías esto:

  • Captura de pantalla de los 20 píxeles principales (barra de estado)
  • De esa captura de pantalla, elimine todo lo que no sea negro (puede mejorarlo para que busque bordes negros, de esta manera puede conservar la batería verde y la transparencia) Esto hará que su máscara de superposición y también falsifique la barra de estado
  • Barra de estado de superposición con: vista de fondo que enmascara la barra de estado real y la imagen alfa que acaba de crear
  • Aplicar máscara a esa imagen , todo lo que esté enmascarado cambiará de color a tonos de blanco
  • Cambiar la altura de la máscara en función del desplazamiento del usuario.

Ahora debería poder desplazarse correctamente y cambiar el color correctamente. El único problema que deja es que la barra de estado no está viva, pero ¿lo es realmente? Una vez que se desplaza hacia fuera, inmediatamente elimina la superposición, lo que permite que se actualice. Hará lo mismo cuando se desplace hacia la parte superior, pero en ese caso, cambiará el color de la barra de estado a blanco (sin animación), de modo que se ajuste a su estado. No será en vivo sólo por un breve período de tiempo.

¡Espero eso ayude!


Pensando en cómo implementar esto sin APIs privadas.

Creo que puede haber una solución con la segunda UIWindow superponiendo su statusBar.

Añadiendo vista en StatusBar en iPhone

Tal vez es posible hacer capturas de pantalla de la barra de estado constantemente (tomadas de su ventana principal) a la imagen, aplicarle un filtro y mostrar esta ''imagen falsa de la barra de estado'' en su segunda ventana (sobre la barra de estado ''real'').

Y puedes hacer lo que quieras con la segunda barra de estado "falsa".


Repitiendo la respuesta de Jiri, esto te acercará bastante. Sustituya MTStatusBarOverlay con CWStatusBarNotification . Para manejar la transición modal entre los controladores de vista, estoy usando MusicPlayerTransition . Estamos asumiendo un imageView: "art" en self.view con marco: CGRect (0, 0, self.view.bounds.size.width, self.view.bounds.size.width). Necesita un poco de masaje, pero te dan la esencia. Nota: aunque no estamos "en vivo", lo máximo que estaremos fuera es un segundo, y el color de la batería no se conserva. Además, deberá configurar el tiempo de animación en CWStatusBarNotification.m en cero. (propiedad 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; }

Para mantener sus capturas de pantalla de la barra de estado sincronizadas con la barra de estado real, configure su temporizador. Enciéndelo en viewWillAppear, y mátalo en 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; }

Debido a que tenemos una fuerte referencia al temporizador y la configuración y la invalidación ocurren en el mismo subproceso, no hay que preocuparse de que el temporizador no se pueda invalidar. El resultado final debería ser algo como esto: