React-native: [Inicialización] Flash blanco de la pantalla de inicio

Creado en 26 may. 2015  ·  138Comentarios  ·  Fuente: facebook/react-native

Me pregunto si existe una buena práctica sobre LaunchScreen. La razón por la que pregunto esto es que si uno agrega LaunchScreen, hay un destello blanco antes de que reaccione el nativo y cargue la aplicación. ¿Hay alguna forma de prevenir esto?

AsyncStorage Locked

Comentario más útil

Para agregar a esto ...

Una solución que encontré fue asignar rootView un color de fondo pero usar [UIColor colorWithPatternImage:img] .

Esto no requiere ningún retraso para garantizar que permanezca visible hasta que esté completamente cargado.

A continuación, se muestra un fragmento completo (y utilizando la sugerencia proporcionada por @ dvine-multimedia) que encontrará la LaunchImage deseada para el dispositivo:

NSArray *allPngImageNames = [[NSBundle mainBundle] pathsForResourcesOfType:@"png" inDirectory:nil];
  for (NSString *imgName in allPngImageNames){
    if ([imgName containsString:@"LaunchImage"]){
      UIImage *img = [UIImage imageNamed:imgName];

      if (img.scale == [UIScreen mainScreen].scale && CGSizeEqualToSize(img.size, [UIScreen mainScreen].bounds.size)) {
        rootView.backgroundColor = [UIColor colorWithPatternImage:img];
      }
  }
}

LaunchImage ahora permanece visible hasta que el paquete react-native se haya cargado por completo.

Todos 138 comentarios

@liubko Sí, esto es exactamente de lo que quiero deshacerme. Aún no he aplicado el parche, pero lo haré esta noche.

@brentvatne : No veo cómo ese parche solucionaría este problema (si soy ciego / estúpido, perdóname :-). El problema es que hay un momento entre el lanzamiento de la aplicación y React sigue funcionando. Idealmente, LaunchScreen se mostraría hasta que React esté terminado y completamente renderizado como lo hace en una aplicación "completamente nativa".

@oblador - ah, esto le permitiría realizar una transición más fluida al tener el mismo color de fondo que la pantalla de inicio en el momento de "parpadeo".

@vjeux : ¿cómo se @nicklockwood

También hay una solución (separada) para este problema. Use la nueva propiedad loadingView de RCTRootView y configúrela en una pantalla completa UIImageView muestre su imagen de inicio. El código podría verse así:

UIImageView *launchView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"MyLaunchImage"];
rootView.loadingView = launchView;

He estado experimentando con una forma de detectar automáticamente la imagen de inicio y hacer que esto sea completamente automático, pero aún no está listo. Si está interesado, se ve así:

// TODO: support landscape orientation

// Get launch image
NSString *launchImageName = nil;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
  CGFloat height = MAX(RCTScreenSize().width, RCTScreenSize().height);
  if (height == 480) launchImageName = @"[email protected]"; // iPhone 4/4s
  else if (height == 568) launchImageName = @"[email protected]"; // iPhone 5/5s
  else if (height == 667) launchImageName = @"[email protected]"; // iPhone 6
  else if (height == 736) launchImageName = @"[email protected]"; // iPhone 6+
} else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
  CGFloat scale = RCTScreenScale();
  if (scale == 1) launchImageName = @"LaunchImage-700-Portrait~ipad.png"; // iPad
  else if (scale == 2) launchImageName = @"LaunchImage-700-Portrait@2x~ipad.png"; // Retina iPad
}

// Create loading view
UIImage *image = [UIImage imageNamed:launchImageName];
if (image) {
  UIImageView *imageView = [[UIImageView alloc] initWithFrame:(CGRect){CGPointZero, RCTScreenSize()}];
  imageView.contentMode = UIViewContentModeBottom;
  imageView.image = image;
  rootView.loadingView = imageView;
}

Una solución fácil a lo que describió @nicklockwood es cargar la pantalla de inicio xib si está en iOS 8+.

@ide Estoy usando la pantalla de inicio xib. Veo mi vista de pantalla de inicio en el momento de inicio, pero antes de que mi aplicación se inicie, veo una vista en blanco (flash).

@alinz , creo que @ide significa usar su pantalla de inicio xib para configurar RCTRootView loadingView (que aún deberá hacer manualmente). No hay soporte automático para hacer eso (todavía).

Para aclarar, iOS oculta la pantalla de inicio en el momento en que React _comienza a cargarse. Para evitar ver una pantalla en blanco, deberá extender el tiempo que se muestra la pantalla de inicio mostrando manualmente la misma vista que la vista de carga de RCTRootView.

Gracias @nicklockwood por la aclaración. Eso fue mi mal. :)

Cortesía de http://stackoverflow.com/a/29115477/255765 Terminé con esto:

for (NSString *imgName in allPngImageNames){
    // Find launch images
    if ([imgName containsString:@"LaunchImage"]){
      UIImage *img = [UIImage imageNamed:imgName]; //-- this is a launch image
      // Has image same scale and dimensions as our current device's screen?
      if (img.scale == [UIScreen mainScreen].scale && CGSizeEqualToSize(img.size, [UIScreen mainScreen].bounds.size)) {
        NSLog(@"Found launch image for current device %@", img.description);
        UIImageView *launchView = [[UIImageView alloc] initWithImage: img];
        rootView.loadingView = launchView;
      }
    }
  }

Parece funcionar.

+1 para una forma estándar / documentada.

@ dvine-multimedia, ¿funciona mejor que el fragmento de código que proporcioné anteriormente?

@ myusuf3

@nicklockwood En realidad, hacen prácticamente lo mismo. Cuando comencé a investigar esto, probablemente no entendí qué hacer con tu recorte por pura falta de experiencia en xcode. Cuando finalmente llegué al punto en el que entendí qué hacer, no me di cuenta de que ya habías estado allí. Además de eso, personalmente encuentro "mi" solución un poco más legible. Pero esa pura estética.

@nicklockwood Probé tu código pero todavía veo un destello blanco. Creé una imagen de inicio para establecerla como vista de carga. La imagen de inicio es la misma que la de launchScreen.xib.

Esto es lo único que contiene el lanzamiento de nuestra aplicación. Realmente agradezco cualquier ayuda en esto.

¿Aparece el flash después de que se oculta la imagen de inicio o no aparece la imagen de inicio? (Esto puede ser difícil de determinar con solo mirar; cambie la imagen de inicio a algo así como un rectángulo rojo sólido temporalmente para estar seguro).

@nicklockwood Intenté cambiar el color entre el archivo xib y la imagen de la pantalla de inicio. Todavía estaba viendo ese destello.

Mi código se ve así:

 UIImageView *launchView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"launchScreen1"]];
 rootView.loadingView = launchView;

 rootView.loadingViewFadeDelay = 0.0;
 rootView.loadingViewFadeDuration = 0.15;

Eliminé las dos últimas líneas loadingViewFadeDelay y duration ahora y parece que el problema está resuelto. No veo ningún destello. Bonita transición suave.

@ chirag04 Acabo de

esto es lo que hice

  RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                      moduleName:@"whiteFlash"
                                                   launchOptions:launchOptions];

  //here's what I did
  UIImage *image = [UIImage imageNamed:@"LaunchImage"];
  if (image) {
    UIImageView *launchView = [[UIImageView alloc] initWithImage: image];
    launchView.contentMode = UIViewContentModeBottom;
    launchView.image = image;
    rootView.loadingView = launchView;
  }
  ///////////////////////////

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [[UIViewController alloc] init];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  return YES;

Está bien. profundizando, parece que el flash tal vez porque mi aplicación no muestra nada hasta que se carga un valor desde asyncstore.

render() {
  if(!this.state.loaded) return (null);
  return <View ...../>;
}

Creo que loadingView piensa que js terminó de renderizarse y oculta loadingView. Sin embargo, js acaba de terminar de renderizar con ese return null

@nicklockwood @alinz Solo estoy disparando al aire. puede que no sea la razón real. Qué piensan ustedes.

También una cosa que noté es que si configuro esos valores de loadingViewFadeDelay, etc. a 0.30 o más, la transición es muy, muy suave. los valores predeterminados son 0,25, que también es suave.

El propósito de loadingFadeDelay es precisamente cubrir el escenario en el que su aplicación no procesa nada de inmediato, por lo que la está usando correctamente.

Sin embargo, es posible que desee considerar configurar loadingViewFadeDelay explícitamente, en caso de que el valor predeterminado cambie alguna vez, y asegúrese de probar en el dispositivo más lento que admita, en caso de que tarde más en cargarse.

Me gusta la solución @nicklockwood , pero debes considerar la latencia de la red, que no se puede predecir.

Otra solución es establecer el estado del componente en algún tipo de valor predeterminado para decirle a su componente que muestre algún tipo de diálogo de carga.

Frio. Creo que tengo la solución.

¿Qué piensan ustedes acerca de tener 3 componentes iguales?

1) launchScreen.xib
2) loadingView
3) return null in render to actually render a view which is like loadingView and launchScreen.xib?

Sin embargo, no estoy seguro de cómo se escalará el punto 3 en diferentes dispositivos. ¿Podrían sugerir eso siquiera?

Si el tiempo de inicio depende de la red y luego de las pruebas, definitivamente recomendaría dibujar una vista "vacía" inmediatamente en lugar de esperar que se descargue más rápido que el retraso del desvanecimiento.

depende de asyncstorage. sin red

Ya sea que dependa de la red o no, realmente no me gusta usar la visualización de la base de tiempo. No hay forma de que pueda garantizar al 100% que la hora establecida sea precisa. Siempre debe mostrar algo al usuario para indicar que algo está sucediendo pero que no está listo para mostrarse. Es sólo una sugerencia.

Acordado. El propósito de loadingView, al igual que la imagen de carga estándar de iOS, es cubrir hasta que su aplicación esté lista para mostrar algo, incluso si toda la aplicación está lista para mostrar es una ruleta de carga.

Dicho esto, la razón por la que lo convertí en una vista en lugar de una imagen es para que pueda hacerlo no estático. Puede agregar un UIActivityIndicatorView a loadingView si lo desea.

¿Cómo se puede posicionar la imagen de lanzamiento? Intenté ajustar el origen del marco, pero siempre lo coloca en el centro sin importar el origen que usé. Tengo una pequeña imagen de la barra superior que quiero colocar en la parte superior y estirada de izquierda a derecha.

Esto es lo que tengo:

  UIImageView *launchView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"LaunchImage"]];
  CGRect frame = launchView.frame;
  frame.origin.x = 0;
  frame.origin.y = 0;
  launchView.frame = frame;
  rootView.loadingView = launchView;
  rootView.loadingViewFadeDelay = 0.0;
  rootView.loadingViewFadeDuration = 0.0;

No es una imagen de lanzamiento, es una _view_ de lanzamiento, por lo que puede colocar su imageView dentro de otra vista de contenedor y usar el contenedor como la vista de lanzamiento:

UIView *launchView = [[UIView alloc] init];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"LaunchImage"]];
imageView.frame = CGRectMake(whatever);
[launchView addSubview:imageView];
...

Es cierto, supongo que podría hacer que la envoltura llene el espacio de la pantalla y coloque la imagen en la parte superior. RootView colocará automáticamente el contenedor en el centro, parece https://github.com/facebook/react-native/blob/757d6d204ae2d743634af64e3f78a4aad9d53f70/React/Base/RCTRootView.m#L191.

@Intellicode sí.

Acabo de romper mi aplicación en producción en el iphone 4s usando el código de @ dvine-multimedia. arreglar es simplemente poner un descanso en el if.

Un fallo más porque containsString no está disponible en ios 7.

@nicklockwood se pregunta si la vista de carga elegirá automáticamente la mejor resolución posible.

loadingView no elige una imagen en absoluto, solo usa lo que usted pasa. Sin embargo, el fragmento que publiqué arriba para encontrar la página de inicio seleccionará la resolución correcta para el dispositivo.

Sin embargo, su fragmento no elige el que tiene las dimensiones correctas. alguna solución para eso?

¿Estabas usando mi solución o la de dvine? ¿Qué modelo de iPhone estás usando? ¿Retrato u paisaje?

al usar dvine's, toma la dimensión correcta. Con su solución, tiene un espacio negro alrededor de la imagen. Supongo que el espacio negro es porque recoge la imagen con la dimensión incorrecta.

Estoy en el iphone 6. retrato.

Así es como luce. Observe el fondo blanco.

Usando el siguiente código:

UIImageView *launchView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"LaunchImage"]];
  rootView.loadingView = launchView;
  rootView.loadingViewFadeDelay = 0.20;
  rootView.loadingViewFadeDuration = 0.20;

lrn_launch_screen

Esa no fue la solución que publiqué, esta fue:

// Get launch image
NSString *launchImageName = nil;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
  CGFloat height = MAX(RCTScreenSize().width, RCTScreenSize().height);
  if (height == 480) launchImageName = @"[email protected]"; // iPhone 4/4s
  else if (height == 568) launchImageName = @"[email protected]"; // iPhone 5/5s
  else if (height == 667) launchImageName = @"[email protected]"; // iPhone 6
  else if (height == 736) launchImageName = @"[email protected]"; // iPhone 6+
} else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
  CGFloat scale = RCTScreenScale();
  if (scale == 1) launchImageName = @"LaunchImage-700-Portrait~ipad.png"; // iPad
  else if (scale == 2) launchImageName = @"LaunchImage-700-Portrait@2x~ipad.png"; // Retina iPad
}

// Create loading view
UIImage *image = [UIImage imageNamed:launchImageName];
if (image) {
  UIImageView *imageView = [[UIImageView alloc] initWithFrame:(CGRect){CGPointZero, RCTScreenSize()}];
  imageView.contentMode = UIViewContentModeBottom;
  imageView.image = image;
  rootView.loadingView = imageView;
}

¡Oh demonios! Deseo leer tu comentario con atención. Su solución funciona y también es fácil de entender.

I've been experimenting with a way to automatically detect the launch image and make this completely automatic, but it's not really ready yet. If you're interested, it looks like this:

Tal vez sea la cosa experimenting . No estoy seguro de cómo me lo perdí. Disculpa, me equivoque.

Gracias por la ayuda. Definitivamente usará este código en la próxima versión. Parece cubrir todos los casos también. No necesito paisaje.

Je, supongo que lo vendí por debajo del precio. Probablemente debería haber dicho "esto es lo que estamos usando en producción en este momento, y parece funcionar bien" :-)

"esto es lo que estamos usando en producción en este momento" nos habría salvado de una estrella de 1 en la tienda de aplicaciones. ja ja. No hay problema. Siempre hay una nueva versión para salvar el mundo. :)

¿Cerrar este problema por cierto?

Iré y cerraré este boleto ya que se ha discutido completamente en detalle, tenemos algunas buenas soluciones.

Solo para dejar esto 100% claro para aquellos que están usando un xib de LaunchScreen, aquí está el código que hará que eso funcione:

UIView* launchScreenView = [[[NSBundle mainBundle] loadNibNamed:@"LaunchScreen" owner:self options:nil] objectAtIndex:0];
launchScreenView.frame = self.window.bounds;
rootView.loadingView = launchScreenView;

Añadir estas líneas a la application didFinishLaunchingWithOptions método en el AppDelegate.m archivo, justo por encima de la línea que dice return YES .

@arnemart para ser más claro, ese método solo funcionará para ios 8+, ¿verdad?

@arnemart ¡Gracias! Funciona perfectamente .

Para aquellos que usan LaunchImage , deben configurar tanto frame como contentMode para que la imagen se escale correctamente:

UIImageView *launchScreenView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"LaunchImage"]];
launchScreenView.frame = self.window.bounds;
launchScreenView.contentMode = UIViewContentModeScaleAspectFill;
rootView.loadingView = launchScreenView;

Al igual que el comentario de @arnemart, añadir estas líneas a la application didFinishLaunchingWithOptions método en el AppDelegate.m archivo, por encima de la línea que dice return YES .

Extraño. En RN v.0.11.4, la aplicación se inicia primero con una pantalla negra y luego LaunchScreen.xib antes de cargar la aplicación. iOS 9 w / @arnemart 's fix https://github.com/facebook/react-native/issues/1402#issuecomment -130,236,507. ¿Algunas ideas?

@irfaan intenta cambiar window.backgroundColor a algo como [UIColor redColor], que debería decirnos si el color negro proviene de la ventana o de otra cosa.

self.window.backgroundColor = [UIColor redColor]; dentro de didFinishLaunchingWithOptions no cambió nada. Todavía negro antes de LaunchScreen.xib. Así que no desde la ventana, parece @nicklockwood

¿Cómo me recomiendas que depure esto?

Parece que iOS no está cargando su launchScreen.xib en absoluto hasta que la aplicación se haya cargado (en ese momento, React lo muestra como loadingView).

¿Quizás es un error de configuración en Xcode? ¿O posiblemente un error en iOS 9?

¿Lo has probado en un dispositivo o solo en el simulador?

Gracias @nicklockwood . Había estado experimentando el problema en el dispositivo. Lo ejecuté en el simulador y funcionó perfectamente, y luego se eliminó + se ejecutó en el dispositivo y funciona bien. Realmente extraño. Publicaré de nuevo si el problema vuelve a surgir.

hola @genexliu , agregué mi conjunto de imágenes "LaunchImage" a Images.xcassets/LaunchImage.launchimage/ pero ni el código que pegaste ni mi LaunchScreen.storyboard pueden encontrarlas / usarlas (ambos fallan silenciosamente). Mi guión gráfico de LaunchScreen se está cargando correctamente, ya que veo su color de fondo, pero no muestra la imagen a la que se hace referencia. ¿Algunas ideas?

Además, la secuencia de inicio cuando se ejecuta desde XCode parece normal, pero parece haber una ejecución adicional de la secuencia de inicio / destello blanco adicional / etc cuando se ejecuta natal launch desde la línea cmd.

Resulta que mi problema con el Storyboard al no encontrar LaunchImage fue aparentemente un error con XCode. Cambié la configuración de inicio a 'usar catálogo de activos' y luego volví a 'usar guión gráfico' y comenzó a funcionar. No está claro si el código de @genexliu funciona para mí o no, ya que loadingViewFadeDelay no parece tener ningún efecto.

Aquí está mi código:

  UIImageView *launchScreenView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Images/LaunchImage"]];
  launchScreenView.frame = self.window.bounds;
  launchScreenView.contentMode = UIViewContentModeScaleAspectFill;
  rootView.loadingView = launchScreenView;
  rootView.loadingViewFadeDelay = 5000;

sin embargo, no hay demora entre la visualización de LaunchImage del guión gráfico y mi React render inicial.

@ "Images / LaunchImage" no me parece correcto. Probablemente sea solo @ "LaunchImage"

Oh, vaya, sí. Estás bien. Eso fue un error de pegado, una de las permutaciones que probé (pero no la primera).

Además, verifique el código de ejemplo en mi comentario anterior de hace 3 meses: hay muchos archivos de imagen de inicio para diferentes clases de dispositivos.

Doh! Usted tenía razón. Después de volver a LaunchImage ahora está funcionando. ¡Gracias!

¿Alguien puede indicarme alguna documentación sobre esto para Android?

+1 para Android

cc @dmmiller ¿tenemos una función loadingView en Android?

Hola, me encuentro con el mismo problema y, aunque veo que hay algunas soluciones publicadas aquí, no entiendo dónde poner este código. Según tengo entendido, la solución es cambiar el código de Objective-C, no algo que se pueda hacer dentro de React Native, ¿correcto? En ese caso, ¿a dónde va el código publicado? ¿En el archivo main.m en la raíz del proyecto xcode? Gracias.

@CorpusCallosum el código debe ir en el archivo AppDelegate.m, donde está configurado RCTRootView.

Gracias @nicklockwood , lo intentaré.

Oye, este código me funciona ahora, en la medida en que no veo el destello blanco y mi imagen se está cargando en esa pantalla inicial, sin embargo, ¡ahora mi aplicación real no se cargará! Simplemente permanece en esa pantalla de carga, aunque puedo ver en mi consola, la aplicación está cargada y ejecutándose, e incluso la interacción está funcionando (tocar y deslizar), pero en realidad no puedo ver mi aplicación en absoluto, simplemente está atascada en esa pantalla inicial. ¿Alguna idea de por qué?

Aquí está mi código de mi archivo AppDelegate.m:

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [[UIViewController alloc] init];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];

  //use launch image as BG image for app
  UIImageView *launchScreenView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"LaunchImage-blank-grey"]];
  launchScreenView.frame = self.window.bounds;
  launchScreenView.contentMode = UIViewContentModeScaleAspectFill;
  rootView.loadingView = launchScreenView;
  rootView.loadingViewFadeDelay = 1000;

  return YES;

@CorpusCallosum Puedes intentar eliminar la línea
rootView.loadingViewFadeDelay = 1000;
o ajustar la transición entre la pantalla de presentación y su aplicación con su valor (creo que las unidades son segundos, no milisegundos, por eso parece "atascado" en la presentación).
Si eliminar la línea por completo no funciona para usted, intente establecer valores entre 0-5 (también puede establecer valores que no sean enteros).

Trabajando para mí, gracias chicos :)

Para aquellos que quieran usar su pantalla de inicio xib como loadingView, aquí está el código para insertar en AppDelegate.m:

UIView *loading = [[[NSBundle mainBundle] loadNibNamed:@"LaunchScreen" owner:self options:nil] objectAtIndex:0];
rootView.loadingView = loading;
rootView.loadingViewFadeDelay = 1;

La última línea es opcional, como mencioné anteriormente, establece el tiempo que permanecerá loadingView antes de pasar a la aplicación en sí.

@ david-a ¡muchas gracias por eso! He estado lidiando con esto desde que comencé a probar react native. 👏

@ david-a, @geriux : También tuve que configurar launchScreenView.frame = CGRectZero; ya que mi LaunchScreen.xib tenía una imagen de fondo con el modo de contenido AspectFill y no escalaba correctamente. Llegué a la solución después de algunas pruebas y errores, no estoy seguro de qué causa esto.

@BasitAli sí, lo siento, eso debería estar mejor documentado. Si establece el tamaño de la vista en un valor distinto de cero, se centrará en la pantalla. Si lo establece en cero, se escalará para ajustarse a la pantalla.

@ david-a ¡muchas gracias! Su comentario debe incluirse en el texto estándar, o al menos ser parte de la documentación nativa principal de react. No estoy seguro de por qué se cerró este problema en marzo de 2015, claramente todavía existe en RN 0.20 en febrero de 2016.

Sería bueno si alguien pudiera hacer las relaciones públicas del documento.

Los consejos de sus muchachos me ayudan mucho (en IOS, funcionan perfectamente), ¿alguien encuentra una manera de solucionar esto en Android?

@weiyisheng , estoy usando react-native-splashscreen como lo sugiere @braco en Android junto con la solución discutida anteriormente en iOS.

@braco @BasitAli SÍ, ayudó, lo

@BasitAli, ¿

Mi aplicación se anima sin problemas desde la pantalla de inicio hasta la pantalla de inicio de sesión (el logotipo se mueve hacia arriba y los campos de inicio de sesión saltan). El complemento rn-splashscreen se desvanece, lo que no va muy bien con mi animación. Tuve que usarlo en Android ya que no tenía otra opción.

@BasitAli parece que el complemento react-native-splashscreen obedece a la configuración rootView.loadingViewFadeDuration , siempre que lo establezca después de adjuntarlo, por lo que esto debería deshabilitar el desvanecimiento:

[RCTSplashScreen show:rootView];
rootView.loadingViewFadeDuration = 0;

¿Hay alguna forma de eliminar ese pequeño mensaje en la parte superior que dice "Cargando desde un archivo empaquetado"?

@rclai establece el esquema para lanzar

¡Ah! ¡Gracias!

¿Existe alguna solución nativa de reacción para la pantalla de presentación de ambas plataformas? Escribir en los archivos internos de ambas plataformas hace que el uso de react-native sea inútil. Respuesta simple, por favor. Gracias

@rclai

¿Hay alguna forma de eliminar ese pequeño mensaje en la parte superior que dice "Cargando desde un archivo empaquetado"?

Eso no se muestra en el modo de lanzamiento, solo en el modo de depuración. Si también desea ocultarlo en modo de depuración, puede ocultarlo poniendo [RCTDevLoadingView setEnabled:NO]; en su AppDelegate.

@nicklockwood Hola, ¿es eso correcto? Si no es así, ¿qué debo cambiar / eliminar?

  RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                      moduleName:@"SomeApp"
                                               initialProperties:nil
                                                   launchOptions:launchOptions];

// Get launch image
NSString *launchImageName = nil;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
  CGFloat height = MAX(RCTScreenSize().width, RCTScreenSize().height);
  if (height == 480) launchImageName = @"[email protected]"; // iPhone 4/4s
  else if (height == 568) launchImageName = @"[email protected]"; // iPhone 5/5s
  else if (height == 667) launchImageName = @"[email protected]"; // iPhone 6
  else if (height == 736) launchImageName = @"[email protected]"; // iPhone 6+
} else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
  CGFloat scale = RCTScreenScale();
  if (scale == 1) launchImageName = @"LaunchImage-700-Portrait~ipad.png"; // iPad
  else if (scale == 2) launchImageName = @"LaunchImage-700-Portrait@2x~ipad.png"; // Retina iPad
}

// Create loading view
UIImage *image = [UIImage imageNamed:launchImageName];
if (image) {
  UIImageView *imageView = [[UIImageView alloc] initWithFrame:(CGRect){CGPointZero, RCTScreenSize()}];
  imageView.contentMode = UIViewContentModeBottom;
  imageView.image = image;
  rootView.loadingView = imageView;
}

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  return YES;
}

@TeodorKolev me parece bien. Si sigue viendo un destello al inicio, intente configurar

rootView.loadingViewFadeDelay

A un valor mayor (es en segundos; el valor predeterminado es 0.25)

EDITAR:

Esta línea

UIImageView *imageView = [[UIImageView alloc] initWithFrame:(CGRect){CGPointZero, RCTScreenSize()}];

Probablemente debería ser

UIImageView *imageView = [[UIImageView alloc] init];

Gracias, ¿en qué carpeta debo agregar esas imágenes? ¿Necesito Content.json adicional para esto o no? Recibí varios errores en ese código comenzando con
(https://cloud.githubusercontent.com/assets/10398337/13778676/e01e3d32-eabf-11e5-95bf-d7a1205a5ca1.png)
Mirando fijamente:

CGFloat height = MAX(RCTScreenSize().width, RCTScreenSize().height);

@TeodorKolev Xcode tiene una GUI para agregarlos. Haga clic en Images.xcassets, luego haga clic en el botón + y seleccione "Iconos de aplicaciones e imágenes de lanzamiento"> "Nueva imagen de lanzamiento de iOS".

screen shot 2016-03-15 at 13 47 48

@TeodorKolev para corregir los errores, debe agregar

#import "RCTUtils.h"

En su AppDelegate.

Muchas gracias, pero quiero ver la pantalla de inicio hasta que mi URL de WebView se cargue por completo, y ahora no funciona así. ¡Respeto!

@nicklockwood ¿Tienes algún remedio para este?

¿Cuál es el método actual para solucionar este problema? Dado que ha pasado un año y unos meses desde que apareció el problema, dudo que alguna vez se solucione, así que me pregunto cuál es el remedio actual. ¿Qué archivo debe modificarse y qué código debe modificarse?

Editar: solo estoy usando una pantalla negra con launchscreen.xib, pero a la mitad se vuelve blanca antes de que la aplicación se cargue por completo.

@ hasen6 el problema ya se ha solucionado, pero el desarrollador debe trabajar un poco.

Como se discutió en los comentarios anteriores, debe configurar rootView.loadingView con algo de contenido para mostrar en lugar de la pantalla blanca, y ajustar rootView.loadingViewFadeDelay para asegurarse de que la vista de carga no esté oculta antes de su la aplicación ha terminado de cargarse.

Si solo desea mostrar una pantalla negra, es posible que no necesite molestarse con loadingView y simplemente configure el rootView.backgroundColor en negro, pero tendrá que experimentar.

Cambié rootView.backgroundColor = [UIColor clearColor]; a rootView.backgroundColor = [UIColor blackColor]; but it didn't make any difference. Doing a search in XCode for rootView.loadingView` no devolvió ningún resultado.

@ hasen6 , debe averiguar de dónde proviene el color blanco; puede ser que haya una vista dentro de su aplicación JS que sea blanca y se muestre durante un tiempo antes de que se cargue el contenido.

loadingView es una propiedad de RCTRootView , de la que presumiblemente tiene una instancia dentro de su AppDelegate. El código real rootView.loadingView no aparecerá en su Xcode a menos que lo haya agregado usted mismo. Aquí tienes un ejemplo de cómo puedes usarlo:

rootView.loadingView = [UIView new];
rootView.loadingView.backgroundColor = [UIColor blackColor];
rootView.loadingViewFadeDelay = 0.5; // measured in seconds

Mi aplicación no es blanca en ninguna parte. Todas mis aplicaciones muestran la misma pantalla blanca al cargar después de que se muestra la pantalla de inicio, así que estoy seguro de que no es un problema con mis aplicaciones.

¿Entonces necesito agregar ese código en el appdelegate.m? Eso tampoco funcionó. Supongo que debe ser casi imposible de arreglar, de lo contrario no habría pasado un año sin que los desarrolladores lo hubieran resuelto. Teniendo en cuenta lo mal que hace que las aplicaciones se vean, obviamente también sería la primera de la lista para resolver.

FWIW, así es como estoy resolviendo este problema. Estoy usando LaunchScreen.xib y la solución de David-a:

UIView *loading = [[[NSBundle mainBundle] loadNibNamed:@"LaunchScreen" owner:self options:nil] objectAtIndex:0];
rootView.loadingView = loading;
rootView.loadingViewFadeDelay = 1;

Este código se inserta justo debajo

RCTRootView *rootView = [[RCTRootView alloc] etc etc etc...]

Si reemplazo ese código con el código de muestra de nicklockwood, el flash blanco regresa.

¡Woah! Ok, ese funciona. ¡Gracias grittathh!

@grittathh @ hasen6 ah, está bien. No recordé que loadingView se dimensionó automáticamente para ajustarse a la pantalla si tiene tamaño cero, pero aparentemente ese nunca fue el caso ¯_ (ツ) _ / ¯.

@ hasen6 aquí hay una versión modificada del código que debería funcionar (la solución xib también está bien, pero es redundante si solo estás usando una pantalla negra).

rootView.loadingView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
rootView.loadingView.backgroundColor = [UIColor blackColor];
rootView.loadingViewFadeDelay = 0.5; // measured in seconds

Nota: 1 es un valor bastante grande para loadingViewFadeDelay, ya que significa que los usuarios tienen que esperar un segundo más antes de que se inicie la aplicación. Sugiero configurarlo al valor más bajo con el que pueda salirse con la suya (0.25 es el valor predeterminado, que está bien para la mayoría de las aplicaciones).

Sí, encontré que 1 era un poco larga y me faltaba la animación de apertura en una de mis aplicaciones. Encontré que incluso 0.1 estaba bien. Gracias por tu ayuda.

Estoy de acuerdo con @ hasen6 . Ciertamente parece un poco extraño que los usuarios tengan que sumergirse inmediatamente en Objective-C ( AppDelegate.m ) y modificar un poco de código inmediatamente después de generar una aplicación React Native. ¿No sería posible que React Native generara código con esta corrección ya incorporada? ¿O introducir una solución más abstracta para la configuración de la pantalla de inicio desde JavaScript (o un lenguaje de configuración declarativo)?

@johanatan Irónicamente, los dos problemas más grandes y duraderos con React Native tienen que ver con algún tipo de flash blanco. Este error y el destello blanco en las imágenes.

Cuando uso mi LaunchScreen xib, tiende a ser más grande, ¿alguna solución?

¿Qué tiende a ser más grande?

UIView * loading = [[[NSBundle mainBundle] loadNibNamed: @ "LaunchScreen" propietario: self options: nil ] obje ctAtIndex: 0 ];
rootView.loadingView = cargando;

la vista de la interfaz de usuario de carga, no parece cambiar de tamaño, se supone que es la misma que mi pantalla de inicio, que es mi LaunchScreen.xib

Estoy usando clases de tamaño y restricciones por cierto

@akoshdee eso es correcto: deberá establecer el tamaño de la vista explícitamente para que coincida con el tamaño de la pantalla. Utilizando

loading.frame = [UIScreen mainScreen].bounds;

ya cambió el marco pero aún no funciona

cualquier solución para android?

@ajoshdee La loadingView.frame = [UIScreen mainScreen].bounds; no funcionó para mí, pero esto sí: loadingView.frame = self.window.bounds;

Esto es lo que estoy usando:

NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:@"LaunchScreen" owner:self options:nil];
UIImageView *loadingView = [nibObjects objectAtIndex:0];
loadingView.frame = self.window.bounds;
rootView.loadingView = loadingView;

¡Hola! Configuré el color para reaccionar vista:
rootViewController.view.backgroundColor = [UIColor blackColor];

@ py110 @ajwhite

La solución de Android es estúpidamente simple hasta el punto de molestarme conmigo mismo por el tiempo que me llevó averiguarlo.

Se trata de una pantalla de presentación de 3 etapas.

https://github.com/mehcode/rn-splash-screen/issues/1

Tuve una implementación similar @mehcode ; sin getReactNativeHost() , es bueno saberlo.

Había hecho lo siguiente (no estoy contento con eso)

  1. SplashActivity comenzó cuando se abre la aplicación
  2. Abre inmediatamente MainActivity y finish()
  3. MainActivity inicia SplashActivity con una bandera que indica que está en "modo de primer plano" tan pronto como comienza a mostrar el chapoteo sobre MainActivity . Después de un corto período de tiempo, SplashActivity cierra revelando la aplicación.

@ajwhite

Gracias. El efecto es muy suave.

En mis proyectos actuales, literalmente he copiado ReactActivity en mi base de código y he hecho que el mReactInstanceMangager esté protegido en lugar de privado.

En react-native 0.29 (debería haber dicho en el comentario) el equipo de react native nos dio un método público getReactNativeHost() para entrar en él.

Ese contenedor ReactNativeHost es un movimiento brillante. Este es exactamente el problema con el que me encontré: no poder conectarme al ciclo de vida desde MainActivity.

Ref para los interesados: https://github.com/facebook/react-native/commit/49f20f41546e3ba8e7fe43c84c4c701684d0434d#diff -1346852de0c7f8466a36d42de50ec808R20

Para agregar a esto ...

Una solución que encontré fue asignar rootView un color de fondo pero usar [UIColor colorWithPatternImage:img] .

Esto no requiere ningún retraso para garantizar que permanezca visible hasta que esté completamente cargado.

A continuación, se muestra un fragmento completo (y utilizando la sugerencia proporcionada por @ dvine-multimedia) que encontrará la LaunchImage deseada para el dispositivo:

NSArray *allPngImageNames = [[NSBundle mainBundle] pathsForResourcesOfType:@"png" inDirectory:nil];
  for (NSString *imgName in allPngImageNames){
    if ([imgName containsString:@"LaunchImage"]){
      UIImage *img = [UIImage imageNamed:imgName];

      if (img.scale == [UIScreen mainScreen].scale && CGSizeEqualToSize(img.size, [UIScreen mainScreen].bounds.size)) {
        rootView.backgroundColor = [UIColor colorWithPatternImage:img];
      }
  }
}

LaunchImage ahora permanece visible hasta que el paquete react-native se haya cargado por completo.

Probé casi todos los bloques de código en esta conversación sin ninguna posibilidad, pero este funcionó a la perfección.
¡Gracias @ dbonner1987 !

alguna solución para android?

@ pareekkhushboo77 https://github.com/mehcode/rn-splash-screen/blob/master/docs/android.md


@sercanov @ dbonner1987 Esto también usa el enfoque mencionado anteriormente para iOS para hacer la pantalla de inicio de JavaScript.

@arnemart Gracias, todavía funciona un poco en RN 0.30.0. Tuve que eliminar mi aplicación y reinstalarla. Tuvo el destello blanco la primera vez, pero ninguno después de eso.

@nicklockwood ¿Hay algún tipo de devolución de llamada que pueda usar para saber cuándo se carga el javascript real? La razón de esto es que cuando mi aplicación navega entre páginas, hay algo de transparencia donde rootView.backgroundColor es visible en el fondo de la vista. También tengo un problema similar con el complemento Drawer que estoy usando durante la transición de apertura del cajón.
Entonces me gustaría hacer algo como:

  • Establezca el color de fondo de rootView en la imagen del iniciador , utilizando el
  • Cuando el javascript ha terminado de cargarse y comienza la primera ruta de navegación (o algo por el estilo)
  • Vuelva a establecer el color de fondo de rootView en blanco.

Entonces, básicamente, necesito una devolución de llamada para saber cuándo se realiza la carga.

@ UKDeveloper99 Consulte la documentación que he vinculado anteriormente un par de veces. Hay una devolución de llamada disponible.

https://github.com/mehcode/rn-splash-screen/blob/master/docs/android.md

@mehcode eso es perfecto gracias !!

¿Alguien tiene sugerencias sobre cómo implementar un LaunchScreen.storyboard que se apaga una vez que se ha cargado el paquete? Actualmente se muestra durante un período de tiempo fijo, luego veo una pantalla en blanco y luego la aplicación carga RN 34.1 xcode 8

@ajoshdee Tuve problemas similares donde la vista terminó siendo mucho más grande que la pantalla. No estoy seguro de si está relacionado, pero estaba usando AutoLayout en mi LaunchScreen.xib .

Necesitaba también establecer

launchScreenView.autoresizingMask = UIViewAutoresizingNone;

Para que tenga el tamaño adecuado.

Entonces https://github.com/facebook/react-native/issues/1402#issuecomment -166963438 con esa línea agregada arriba

También puede actualizar el color de inicio en reemplazar esta línea en appdelegate.m:

rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];

por esta línea:
rootView.backgroundColor = [[UIColor alloc] initWithRed:0.94 green:0.90 blue:0.89 alpha:1.0];

y encuentra el color que deseas con este sitio web

¿Alguien logró resolver esto en Android?

Aquí hay una solución para ios y android: https://github.com/mehcode/rn-splash-screen .
Escondí la pantalla de bienvenida en la función de renderizado de mi app.tsx (el punto de entrada) y mostré la misma imagen hasta que se completaron todas mis solicitudes https.

Mi código:
''
render público ()
{
SplashScreen.hide ();

   //after everything has finished loading - show my app.
   if (this.state.isFinishedloading) 
    {
        return (
            <this.navigator screenProps={{ ...providers }} />
        );
    }

  // Until then show the same image as the splash screen with an ActivityIndicator.
    return (
       <View style={{ flex: 1 }}>
          <Image style={styles.image} source={require('../assets/img/splash.png')} >
            <ActivityIndicator  style={styles.indicator} color="#fff"></ActivityIndicator>
          </Image>
       </View>
    );

}

''

¿Hay alguna solución para esto si estoy usando un guión gráfico para la pantalla de inicio? Ya no tengo las imágenes de la pantalla de inicio para cada dimensión.

En react native para iOS dentro de AppDelegate.m cambie la siguiente línea escribiendo sus códigos de color RGB en consecuencia:

rootView.backgroundColor = [[UIColor alloc] initWithRed:52.0f/255.0f green:73.0f/255.0f blue:94.0f/255.0f alpha:1];

Por ROJO cambie el número 52
Por VERDE cambie el número 73
Por AZUL cambie el número 94

_Nota: Estoy usando react native v0.51.0_

¿Todavía no hay solución para Android?

@otoinsa vea la respuesta anterior https://github.com/facebook/react-native/issues/1402#issuecomment -339336380 por @neomib. Hay algunas otras bibliotecas de pantallas de presentación que funcionan igual de bien, por ejemplo, para https://github.com/crazycodeboy/react-native-splash-screen.

¿Alguna sugerencia sobre el guión gráfico utilizado como LaunchScreen?

Mi enfoque fue así (pero la aplicación se bloquea al iniciarse)

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSURL *jsCodeLocation;
    [Fabric with:@[[Crashlytics class]]];

    jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];

    RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                moduleName:@"MyApp"
                                initialProperties:nil
                                launchOptions:launchOptions];
    rootView.backgroundColor = [UIColor clearColor];

    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

//  UIViewController *rootViewController = [UIViewController new];

  UIStoryboard *storyboard = self.window.rootViewController.storyboard;
  UIViewController *rootViewController = [storyboard instantiateViewControllerWithIdentifier:@"the_storyboard_id"];

    rootViewController.view = rootView;
    self.window.rootViewController = rootViewController;
    [self.window makeKeyAndVisible];
    return YES;
}

la aplicación se bloquea con el siguiente error:

2018-03-30 11:21:04.995601+0530 MyApp[6119:101967] Running application MyApp ({
    initialProps =     {
    };
    rootTag = 1;
})
2018-03-30 11:21:05.014109+0530 MyApp[6119:101967] *** Assertion failure in -[UIApplication _runWithMainScene:transitionContext:completion:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3698.33.6/UIApplication.m:3529
2018-03-30 11:21:05.090174+0530 MyApp[6119:101967] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Application windows are expected to have a root view controller at the end of application launch'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000011170f12b __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x0000000110001f41 objc_exception_throw + 48
    2   CoreFoundation                      0x00000001117142f2 +[NSException raise:format:arguments:] + 98
    3   Foundation                          0x000000010faa2d69 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 193
    4   UIKit                               0x000000010d838051 -[UIApplication _runWithMainScene:transitionContext:completion:] + 3102
    5   UIKit                               0x000000010dc016f8 __111-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:]_block_invoke + 924
    6   UIKit                               0x000000010dfd74c8 +[_UICanvas _enqueuePostSettingUpdateTransactionBlock:] + 153
    7   UIKit                               0x000000010dc012f1 -

Gracias.

sustituido

UIStoryboard *storyboard = self.window.rootViewController.storyboard;

con

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil];

ahora la aplicación se inicia pero aparece un fondo negro.

O puede usar https://github.com/crazycodeboy/react-native-splash-screen, es mucho más fácil :)

¿Fue útil esta página
0 / 5 - 0 calificaciones