React-native: [Инициализация] Экран запуска белая вспышка

Созданный на 26 мая 2015  ·  138Комментарии  ·  Источник: facebook/react-native

Мне просто интересно, есть ли хорошая практика в отношении LaunchScreen. Причина, по которой я спрашиваю об этом, заключается в том, что если добавить LaunchScreen, будет белая вспышка перед тем, как сработает react-native и загрузит приложение. Есть ли способ предотвратить это?

AsyncStorage Locked

Самый полезный комментарий

Чтобы добавить к этому ...

Решение, которое я нашел, заключалось в том, чтобы назначить rootView цвет фона, но использовать [UIColor colorWithPatternImage:img] .

Это не требует каких-либо задержек, чтобы убедиться, что он остается видимым до полной загрузки.

Полный фрагмент (и с использованием подсказки, предоставленной @ dvine-multimedia), который найдет желаемый LaunchImage для устройства, приведен ниже:

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 теперь остается видимым, пока не будет полностью загружен пакет, поддерживающий реакцию.

Все 138 Комментарий

@alinz - это исправлено в следующем выпуске: https://github.com/tadeuzagallo/react-native/commit/8d992262ed2dcf0d46e8d22e605764902c33012f

@liubko Да, именно от этого я и хочу избавиться. Патч еще не наложил, но сделаю сегодня вечером.

@brentvatne : Я не понимаю, как этот патч решит эту проблему (если я слепой / глупый, пожалуйста, простите :-). Проблема в том, что есть момент между запуском приложения и тем, что React все еще работает. В идеале LaunchScreen будет отображаться до тех пор, пока React не будет завершен и полностью отрисован, как в «полностью родном» приложении.

@oblador - ах, это позволит вам более плавно переходить, имея тот же цвет фона, что и экран запуска в момент "мерцания".

@vjeux - как решить эту проблему в приложениях FB? Я заметил, что F8, который, если я правильно понимаю, является 100% React Native, переходит прямо с экрана запуска в приложение. cc @nicklockwood

Для этой проблемы тоже есть (отдельное) исправление. Используйте новое свойство loadingView для RCTRootView и установите его на полноэкранный режим UIImageView изображением вашего запуска. Код может выглядеть примерно так:

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

Я экспериментировал со способом автоматического определения образа запуска и полностью автоматизировать его, но он еще не готов. Если интересно, это выглядит так:

// 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;
}

Простое решение того, что описал @nicklockwood, - загрузить xib экрана запуска, если вы используете iOS 8+.

@ide Я использую экран запуска xib. Я вижу свой экран запуска во время запуска, но перед загрузкой приложения я вижу белый экран (мигание).

@alinz , я считаю, что @ide означает использование xib вашего экрана запуска для установки RCTRootView loadingView (что вам все равно придется делать вручную). Для этого нет автоматической поддержки (пока).

Чтобы уточнить, iOS скрывает ваш экран запуска в момент, когда React _begins_ загружается. Чтобы не видеть пустой экран, вам нужно продлить время, в течение которого отображается экран запуска, вручную показывая то же представление, что и loadView RCTRootView.

Спасибо @nicklockwood за разъяснения. Это было моим плохим. :)

Curtesy http://stackoverflow.com/a/29115477/255765 Я закончил с этим:

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;
      }
    }
  }

Кажется, работает.

+1 для стандартного / документированного способа.

@ dvine-multimedia работает ли это лучше, чем приведенный выше фрагмент кода?

@ myusuf3

@nicklockwood На самом деле они делают то же самое. Когда я начал разбираться в этом, я, вероятно, не понимал, что делать с вашими фрагментами из-за полного отсутствия опыта работы с xcode. Когда я наконец дошел до того, что понял, что делать, я не осознавал, что вы уже были там. Кроме того, я лично считаю "мое" решение более читаемым. Но это чистая эстетика.

@nicklockwood Я пробовал ваш код, но все еще вижу белую вспышку. Я создал изображение запуска, чтобы установить его в качестве представления загрузки. Изображение запуска такое же, как и в файле launchScreen.xib.

Это единственное, что сдерживает выпуск нашего приложения. Очень признателен за любую помощь в этом.

Вспышка появляется после того, как изображение запуска скрыто, или изображение запуска не появляется? (Это может быть трудно определить, просто взглянув - временно измените изображение запуска на что-то вроде сплошного красного прямоугольника, чтобы быть уверенным).

@nicklockwood Я попытался изменить цвет между xib файлом и изображением на экране запуска. Я все еще видел эту вспышку.

Мой код выглядит так:

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

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

Я удалил последние две строки loadingViewFadeDelay и duration сейчас, и, похоже, проблема решена. Я не вижу вспышки. Красивый плавный переход.

@ chirag04 Я только что попробовал с образцом проекта и не увидел вспышку :(

вот что я сделал

  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;

В порядке. копая глубже, кажется, что вспышка может быть потому, что мое приложение ничего не отображает, пока значение не будет загружено из asyncstore.

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

Я думаю, что loadingView думает, что js завершил рендеринг и скрывает loadingView. Однако js только что закончил рендеринг с этим return null

@nicklockwood @alinz Я просто стреляю в воздух. не может быть реальной причиной. Что вы думаете, ребята.

Также я заметил одну вещь: если я установил для этих значений loadingViewFadeDelay и т.д. значение 0,30 или выше, переход будет очень плавным. значения по умолчанию - 0,25, что также является плавным.

Цель loadingFadeDelay состоит в том, чтобы охватить сценарий, в котором ваше приложение ничего не отображает сразу, поэтому вы используете его правильно.

Возможно, вы захотите явно установить loadViewFadeDelay, если значение по умолчанию когда-либо изменится - и убедитесь, что вы тестируете самое медленное устройство, которое вы поддерживаете, на случай, если загрузка займет больше времени.

Мне нравится решение @nicklockwood, но вы должны учитывать задержку в сети, которую невозможно предсказать.

Еще одно решение - установить для состояния компонента какое-то значение по умолчанию, чтобы ваш компонент отображал какой-то диалог загрузки.

Прохладный. Думаю, у меня есть решение.

Что вы, ребята, думаете о трех одинаковых компонентах?

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

Не знаю, как будет масштабироваться точка 3 на разных устройствах. Вы бы даже это предложили?

Если время запуска зависит от сети, а затем от tes, я определенно рекомендую сразу рисовать «пустое» представление вместо того, чтобы надеяться, что оно будет загружаться быстрее, чем задержка затухания.

зависит от asyncstorage. нет сети

Независимо от того, зависите вы от сети или нет, мне не очень нравится использовать отображение временной развертки. Невозможно на 100% гарантировать, что установленное вами время будет точным. Вы всегда должны отображать что-то пользователю, чтобы указать, что что-то происходит, но не готово к отображению. Это просто предложение.

Согласованный. Цель loadingView, как и стандартного загрузочного изображения iOS, - просто прикрыть, пока ваше приложение не будет готово что-то отобразить, даже если все приложение готово к отображению, это счетчик загрузки.

Тем не менее, причина, по которой я сделал это представление вместо изображения, заключается в том, что вы можете сделать его нестатичным. Вы можете добавить UIActivityIndicatorView в loadingView, если хотите.

Как можно позиционировать стартовую картинку? Я пробовал отрегулировать начало координат кадра, но он всегда помещает его в центр, независимо от того, какое начало я использовал. У меня есть небольшое изображение верхней панели, которое я хочу расположить сверху и растянуть слева направо.

Вот что у меня есть:

  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;

Это не изображение запуска, это _view_ запуска, поэтому вы можете разместить свой imageView внутри другого представления контейнера и использовать контейнер в качестве представления запуска:

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

Правда, полагаю, я мог бы заставить обертку заполнить пространство экрана и расположить изображение вверху. Обертка будет автоматически размещена в центре RootView, кажется, https://github.com/facebook/react-native/blob/757d6d204ae2d743634af64e3f78a4aad9d53f70/React/Base/RCTRootView.m#L191.

@Intellicode да.

Только что сломал мое приложение в производстве на iphone 4s, используя код @ dvine-multimedia. fix - просто поставить паузу в if.

Еще один сбой, потому что containsString недоступен на ios 7.

@nicklockwood интересно, будет ли при загрузке автоматически

loadingView вообще не выбирает изображение, он просто использует то, что вы передаете. Фрагмент, который я опубликовал выше для поиска времени запуска, выберет правильное разрешение для устройства.

Однако ваш фрагмент не выбирает тот, который имеет правильные размеры. какое-нибудь исправление для этого?

Вы использовали мое решение или dvine? Какую модель iPhone вы используете? Портрет или пейзаж?

при использовании dvine's он подбирает правильное измерение. С решением ur вокруг изображения появляется черное пространство. Я предполагаю, что черное пространство связано с тем, что оно принимает изображение с неправильным размером.

Я на iphone 6. портрет.

Вот как это выглядит. Обратите внимание на белый фон.

Используя следующий код:

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

lrn_launch_screen

Это было не то решение, которое я опубликовал, это было:

// 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;
}

Ох черт! Я хочу внимательно прочитать ваш комментарий. Ваше решение работает, и его также легко понять.

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:

Может, дело в experimenting . Не знаю, как я это пропустил. Извини, я виноват.

Спасибо за помощь. Обязательно воспользуюсь этим кодом в следующей версии. Кажется, также охватывает все случаи. Не нужен пейзаж.

Хех, наверное, я недооценил это. Наверное, мне следовало просто сказать «это то, что мы сейчас используем в продакшене, и, похоже, все работает нормально» :-)

«Это то, что мы используем в производстве прямо сейчас» спасло бы нас от одной звезды в магазине приложений. ха-ха. Не беспокойся. Всегда есть новая версия для спасения мира. :)

Кстати, закрыть эту проблему?

Я пойду и закрою этот тикет, поскольку он подробно обсужден, у нас есть несколько хороших решений.

Чтобы на 100% прояснить это для тех, кто использует LaunchScreen xib, вот код, который заставит это работать:

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

Добавьте эти строки в метод application didFinishLaunchingWithOptions в файле AppDelegate.m сразу над строкой return YES .

@arnemart, чтобы быть более понятным, метод будет работать только для ios 8+, верно?

@arnemart Спасибо! Прекрасно работает .

Для тех, кто использует LaunchImage , вам необходимо установить как frame и contentMode для правильного масштабирования изображения:

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

Так же , как комментарий от @arnemart, добавьте эти строки в application didFinishLaunchingWithOptions метода в AppDelegate.m файла, выше линии , которая говорит return YES .

Странный. В RN v.0.11.4 приложение сначала запускается с черным экраном, а затем LaunchScreen.xib перед загрузкой приложения. IOS 9 ж / @arnemart «ы затруднительного https://github.com/facebook/react-native/issues/1402#issuecomment -130236507. Любые идеи?

@irfaan попробуйте изменить window.backgroundColor на что-то вроде [UIColor redColor], это должно сказать нам, исходит ли черный цвет из окна или что-то еще.

self.window.backgroundColor = [UIColor redColor]; внутри didFinishLaunchingWithOptions ничего не изменил. Все еще черный перед LaunchScreen.xib. Так что не из окна вроде @nicklockwood

Как вы порекомендуете мне отладить это?

Похоже, iOS вообще не загружает ваш launchScreen.xib до тех пор, пока приложение не загрузится (в этот момент React отображает его как loadingView).

Может это ошибка конфигурации в Xcode? Или, возможно, ошибка в iOS 9?

Вы пробовали на девайсе, или только на симуляторе?

Спасибо @nicklockwood - у меня возникла проблема на устройстве. Запустил его в симуляторе, и он отлично работал, а затем удалил + запустил на устройстве, и он отлично работает. Действительно странно. Опубликуем еще раз, если проблема возникнет снова.

привет @genexliu , я добавил свой набор изображений "LaunchImage" в Images.xcassets/LaunchImage.launchimage/ но ни вставленный вами код, ни моя LaunchScreen.storyboard не могут их найти / использовать (оба не работают без предупреждения). Моя раскадровка LaunchScreen загружается правильно, так как я вижу ее цвет фона, но не отображает указанное изображение. Любые идеи?

Также последовательность запуска при запуске из XCode выглядит нормально, но, похоже, есть дополнительный запуск последовательности запуска / дополнительная белая вспышка / и т. Д. При запуске natal launch из строки cmd.

Оказывается, моя проблема с раскадровкой, не находящей LaunchImage, по-видимому, была ошибкой с XCode. Я изменил настройку запуска на «использовать каталог ресурсов», а затем снова на «использовать раскадровку», и все заработало. Неясно, работает ли код @genexliu для меня или нет, поскольку loadingViewFadeDelay , похоже, не имеет никакого эффекта.

Вот мой код:

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

пока нет никакой задержки между отображением LaunchImage раскадровки и моим первоначальным React render .

@ "Images / LaunchImage" мне не подходит. Вероятно, это просто @ "LaunchImage"

Ой, ой, да. Ты прав. Это была неправильная вставка - одна из перестановок, которые я пробовал (но не первая).

Кроме того, проверьте пример кода в моем комментарии выше от 3 месяцев назад - существует много файлов изображений запуска для разных классов устройств.

Дох! Ты был прав. После переключения обратно на LaunchImage теперь он работает. Спасибо!

Может ли кто-нибудь указать мне на какую-либо документацию по этому поводу для Android?

+1 для Android

cc @dmmiller есть ли у нас функция loadingView на Android?

Привет, я столкнулся с той же проблемой, и хотя я вижу, что здесь есть несколько опубликованных решений, я не понимаю, где разместить этот код. Насколько я понимаю, решение состоит в изменении кода Objective-C, а не в том, что можно сделать в самом React Native, верно? В таком случае, куда идет опубликованный код? В файле main.m в корне проекта xcode? Спасибо.

@CorpusCallosum код должен находиться в файле AppDelegate.m, где настроен RCTRootView.

Спасибо @nicklockwood , я попробую.

Привет, этот код сейчас работает для меня, поскольку я не вижу белой вспышки, и мое изображение загружается на этот начальный экран, однако теперь мое фактическое приложение не загружается! Он просто остается на этом экране загрузки, хотя я вижу в своей консоли, что приложение загружено и работает, и даже взаимодействие работает (касание и смахивание), но я вообще не вижу свое приложение, оно просто зависло на этом начальном экране. Есть идеи, почему?

Вот мой код из моего файла 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 Вы можете попробовать удалить строку
rootView.loadingViewFadeDelay = 1000;
или точно настроить переход между экраном-заставкой и вашим приложением с его значением (я думаю, что единицы измерения - секунды, а не миллисекунды, поэтому он кажется "застрявшим" на заставке).
Если удаление строки полностью не работает для вас, попробуйте установить значения от 0 до 5 (вы также можете установить нецелочисленные значения).

Работаю на меня, спасибо, ребята :)

Для тех, кто хочет использовать свой экран запуска xib в качестве loadView, вот код, который нужно вставить в AppDelegate.m:

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

Последняя строка является необязательной, как я уже упоминал выше, она устанавливает время, в течение которого loadView будет оставаться перед переходом к самому приложению.

@ david-a большое тебе за это спасибо! Я занимаюсь этим с тех пор, как начал тестировать React Native. 👏

@ david-a, @geriux : Мне также пришлось установить launchScreenView.frame = CGRectZero; поскольку в моем LaunchScreen.xib было фоновое изображение с режимом содержимого AspectFill, и оно неправильно масштабировалось. Я пришел к решению после нескольких проб и ошибок, не понимая, что это вызывает.

@BasitAli Да, извините, это должно быть лучше задокументировано. Если вы установите размер представления, отличный от нуля, он будет центрирован на экране. Если вы установите его на ноль, он будет масштабирован по размеру экрана.

@ david-a огромное спасибо! Ваш комментарий должен быть включен в шаблон или, по крайней мере, быть частью основной документации React Native. Не уверен, почему эта проблема была закрыта в марте 2015 года, она явно все еще существует в RN 0.20 в феврале 2016 года.

Было бы неплохо, если бы кто-то мог сделать пиар для документа.

Советы ваших ребят мне очень помогают (на IOS работает отлично), есть ли способ исправить это на Android?

Это какая-нибудь помощь?

https://github.com/remobile/react-native-splashscreen

@weiyisheng , я использую @braco на Android, вместе с исправлением, описанным выше для iOS.

@braco @BasitAli ДА, помогло, буду использовать в своем приложении, это хорошая идея. Спасибо, ребята.

@BasitAli, почему бы не использовать его на iOS из любопытства?

Мое приложение плавно переходит от заставки к экрану входа в систему (логотип перемещается вверх, а поля входа выпрыгивают). Плагин rn-splashscreen исчезает, что не очень хорошо сочетается с моей анимацией. Мне пришлось использовать его на Android, так как у меня не было другого выбора.

@BasitAli похоже, что плагин rootView.loadingViewFadeDuration при условии, что вы установили его после присоединения, поэтому это должно отключить затухание:

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

Есть ли способ удалить это маленькое сообщение вверху с надписью «Загрузка из предварительно объединенного файла»?

@rclai установил схему для выпуска

Ах! Спасибо!

Есть ли какое-либо решение с поддержкой реакции для экрана-заставки для обеих платформ? Ввод во внутренние файлы обеих платформ делает бесполезным использование response-native. Простой ответ, пожалуйста. Спасибо

@rclai

Есть ли способ удалить это маленькое сообщение вверху с надписью «Загрузка из предварительно объединенного файла»?

Это не отображается в режиме выпуска, только в режиме отладки. Если вы хотите скрыть его и в режиме отладки, вы можете скрыть его, поместив [RCTDevLoadingView setEnabled:NO]; в свой AppDelegate.

@nicklockwood Привет, это правильно? Если нет, то что мне изменить / удалить?

  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 смотрит прямо на меня. Если вы все еще видите вспышку при запуске, попробуйте установить

rootView.loadingViewFadeDelay

На большее значение (в секундах - по умолчанию 0,25)

РЕДАКТИРОВАТЬ:

Эта линия

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

Вероятно, просто должно быть

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

Спасибо, в какую папку мне добавить эти изображения? Нужен ли мне для этого дополнительный Contents.json или нет? У меня несколько ошибок в этом коде, начиная с
(https://cloud.githubusercontent.com/assets/10398337/13778676/e01e3d32-eabf-11e5-95bf-d7a1205a5ca1.png)
Смотря на:

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

@TeodorKolev Xcode имеет графический интерфейс для их добавления. Щелкните Images.xcassets, затем нажмите кнопку + и выберите «Значки приложений и изображения запуска»> «Новое изображение запуска iOS».

screen shot 2016-03-15 at 13 47 48

@TeodorKolev для исправления ошибок нужно добавить

#import "RCTUtils.h"

В вашем AppDelegate.

Большое спасибо, но я хочу видеть заставку, пока мой URL-адрес WebView не загрузится полностью, а теперь он так не работает. Уважать!

@nicklockwood У тебя есть какое-нибудь лекарство от этого?

Какой в ​​настоящее время способ исправить это? Поскольку с момента появления проблемы прошел год и несколько месяцев, я сомневаюсь, что она когда-либо будет исправлена, поэтому мне интересно, какое средство сейчас используется. Какой файл нужно изменить, а какой код - изменить?

Изменить: я просто использую черный экран с launchscreen.xib, но на полпути он становится белым, прежде чем приложение загружается полностью.

@ hasen6 проблема уже решена, но со стороны разработчика необходимо поработать.

Как обсуждалось в комментариях выше, вам нужно установить rootView.loadingView с некоторым содержимым, которое будет отображаться вместо белого экрана, и настроить rootView.loadingViewFadeDelay чтобы убедиться, что представление загрузки не скрывается перед вашим приложение завершило загрузку.

Если вы просто хотите показать черный экран, возможно, вам не придется возиться с loadView и просто установите для rootView.backgroundColor черный цвет, но вам придется поэкспериментировать.

Я изменил rootView.backgroundColor = [UIColor clearColor]; на rootView.backgroundColor = [UIColor blackColor]; but it didn't make any difference. Doing a search in XCode for rootView.loadingView` не вернул никаких результатов.

@ hasen6 вам нужно выяснить, откуда

loadingView - это свойство RCTRootView , экземпляр которого предположительно у вас есть внутри вашего AppDelegate. Фактический код rootView.loadingView не появится в вашем Xcode, если вы не добавили его сами. Вот пример того, как вы можете его использовать:

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

Мое приложение нигде не белое. Все мои приложения показывают один и тот же белый экран при загрузке после показа экрана запуска, поэтому я уверен, что это не проблема с моими приложениями.

Итак, мне нужно добавить этот код в appdelegate.m? Это тоже не сработало. Думаю, это почти невозможно исправить, иначе не прошел бы год, если бы разработчики все еще не решили эту проблему. Учитывая, насколько плохо из-за этого выглядят приложения, эта проблема, очевидно, также будет первой в списке.

FWIW, вот как я решаю эту проблему. Я использую LaunchScreen.xib и решение Дэвида-а:

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

Этот код вставлен чуть ниже

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

Если я заменю этот код образцом кода Nicklockwood, вернется белая вспышка.

Вау! Хорошо, это работает. Спасибо, grittathh!

@grittathh @ hasen6 ах, хорошо. Я неправильно вспомнил, что размер loadView автоматически подбирался по размеру экрана, если он имеет нулевой размер, но, видимо, этого никогда не было ¯_ (ツ) _ / ¯.

@ hasen6 вот модифицированная версия кода, которая должна работать (решение xib тоже подойдет, но избыточно, если вы просто используете черный экран).

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

Примечание. 1 - довольно большое значение для loadViewFadeDelay, так как это означает, что пользователям придется подождать дополнительную секунду перед запуском приложения. Я предлагаю установить самое низкое значение, которое вам может сойти с рук (0,25 - значение по умолчанию, что подходит для большинства приложений).

Да, я обнаружил, что 1 был немного длинным, и мне не хватало анимации открытия в одном из моих приложений. Я обнаружил, что даже 0,1 будет в порядке. Спасибо за вашу помощь.

Я согласен с @ hasen6 . Это, конечно, кажется немного странным, что пользователи должны немедленно погрузиться в Objective-C ( AppDelegate.m ) и настроить код сразу после создания приложения React Native. Разве React Native не сможет сгенерировать код с уже встроенным исправлением? Или представить более абстрактное решение для настройки начального экрана из JavaScript (или декларативного языка конфигурации)?

@johanatan По иронии судьбы две самые большие и самые продолжительные проблемы с React Native связаны с какой-то белой вспышкой. Эта ошибка и белая вспышка на изображениях.

Когда я использую свой LaunchScreen xib, он имеет тенденцию быть больше, какие-либо решения?

Что обычно больше?

UIView * loading = [[[NSBundle mainBundle] loadNibNamed: @ "LaunchScreen" владелец: собственные параметры: nil ] obje ctAtIndex: 0 ];
rootView.loadingView = загрузка;

вид загружаемого пользовательского интерфейса, он, похоже, не меняет размер, он должен быть таким же, как мой экран-заставка, который является моим LaunchScreen.xib

Я использую классы размеров и ограничения, кстати

@akoshdee , это правильно - вам нужно явно установить размер представления в соответствии с размером экрана. С использованием

loading.frame = [UIScreen mainScreen].bounds;

уже поменял раму но все еще не работает

любое решение для android?

@ajoshdee Назначение loadingView.frame = [UIScreen mainScreen].bounds; у меня не сработало, но это сработало: loadingView.frame = self.window.bounds;

Вот что я использую:

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

Привет! Я установил цвет, чтобы реагировать на вид:
rootViewController.view.backgroundColor = [UIColor blackColor];

@ py110 @ajwhite

Решение Android до глупости простое до такой степени, что меня раздражает то, сколько времени потребовалось, чтобы понять это.

Он включает в себя 3-х ступенчатый экран-заставку.

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

У меня была аналогичная реализация @mehcode - getReactNativeHost() , очень полезно знать.

Я сделал следующее (не в восторге от этого)

  1. SplashActivity запускается при открытии приложения
  2. Сразу открывает MainActivity и finish()
  3. MainActivity запускает SplashActivity с флагом, указывающим, что он находится в «режиме переднего плана», как только начинает показывать всплеск над MainActivity . Через короткий промежуток времени SplashActivity закрывается, открывая приложение.

@ajwhite

Спасибо. Эффект очень плавный.

В моих текущих проектах я буквально скопировал ReactActivity в свою кодовую базу и сделал mReactInstanceMangager защищенным вместо закрытого.

В response-native 0.29 (должно было быть сказано в комментарии) команда разработчиков react-native предоставила нам общедоступный метод getReactNativeHost() чтобы войти в него.

Этот контейнер ReactNativeHost - блестящий ход. Это именно та проблема, с которой я столкнулся - невозможность подключиться к жизненному циклу из MainActivity.

Ссылка для заинтересованных: https://github.com/facebook/react-native/commit/49f20f41546e3ba8e7fe43c84c4c701684d0434d#diff -1346852de0c7f8466a36d42de50ec808R20

Чтобы добавить к этому ...

Решение, которое я нашел, заключалось в том, чтобы назначить rootView цвет фона, но использовать [UIColor colorWithPatternImage:img] .

Это не требует каких-либо задержек, чтобы убедиться, что он остается видимым до полной загрузки.

Полный фрагмент (и с использованием подсказки, предоставленной @ dvine-multimedia), который найдет желаемый LaunchImage для устройства, приведен ниже:

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 теперь остается видимым, пока не будет полностью загружен пакет, поддерживающий реакцию.

Я безуспешно перепробовал почти каждый блок кода в этом разговоре, но этот сработал отлично.
Спасибо @ dbonner1987 !

какое-нибудь решение для андроида?

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


@sercanov @ dbonner1987 Здесь также используется подход, упомянутый выше для iOS, для отображения экрана запуска javascript.

@arnemart Спасибо, все еще вроде работает в RN 0.30.0. Мне пришлось удалить свое приложение и переустановить его. В первый раз у него была белая вспышка, но после этого уже не было.

@nicklockwood Есть ли какой-то обратный вызов, который я могу использовать, чтобы узнать, когда фактический javascript загружен. Причина этого в том, что когда мое приложение перемещается между страницами, существует некоторая прозрачность, когда rootView.backgroundColor виден на заднем плане представления. У меня также возникает аналогичная проблема с плагином Drawer, который я использую во время перехода к открытию ящика.
Итак, я хотел бы сделать что-то вроде:

  • Установите цвет фона rootView для изображения средства запуска, используя описанный выше подход
  • Когда javascript завершит загрузку и начнется первый маршрут навигации (или что-то в этом роде)
  • Установите цвет фона rootView обратно на белый.

Поэтому мне в основном нужен обратный вызов, чтобы узнать, когда загрузка будет завершена.

@ UKDeveloper99 Пожалуйста, обратитесь к документации, на которую я ссылался несколько раз. Есть такой обратный звонок.

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

@mehcode это прекрасно, спасибо !!

У кого-нибудь есть предложения о том, как реализовать LaunchScreen.storyboard который отключается после загрузки пакета? В настоящее время он отображается в течение фиксированного времени, затем я вижу белый экран, а затем приложение загружает RN 34.1 xcode 8

@ajoshdee У меня были похожие проблемы, когда вид в конечном итоге был намного больше, чем экран. Не уверен, связано ли это, но я использовал AutoLayout в моем LaunchScreen.xib .

Мне также нужно было установить

launchScreenView.autoresizingMask = UIViewAutoresizingNone;

Чтобы добиться нужного размера.

Итак, https://github.com/facebook/react-native/issues/1402#issuecomment -166963438 с этой добавленной строкой выше

Вы также можете обновить цвет запуска, заменив эту строку в appdelegate.m:

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

по этой строке:
rootView.backgroundColor = [[UIColor alloc] initWithRed:0.94 green:0.90 blue:0.89 alpha:1.0];

и найдите нужный цвет на этом веб-сайте

Кому-то удалось решить эту проблему на Android?

Вот решение для iOS и Android: https://github.com/mehcode/rn-splash-screen .
Я спрятал заставку в функции рендеринга моего app.tsx (точка входа) и показывал то же изображение, пока все мои https-запросы не были выполнены.

Мой код:
`` ''
публичный рендер ()
{
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>
    );

}

`` ''

Есть ли какое-либо решение для этого, если я использую раскадровку для экрана-заставки? У меня больше нет изображений экрана запуска для каждого измерения.

В React Native для iOS внутри AppDelegate.m измените следующую строку, написав соответствующие цветовые коды RGB:

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

Для КРАСНОГО измените число 52
Для ЗЕЛЕНОГО измените число 73.
Для СИНИЙ измените число 94.

_Примечание: я использую react native v0.51.0_

А для Андроида по-прежнему нет решения?

@otoinsa см. ответ выше https://github.com/facebook/react-native/issues/1402#issuecomment -339336380 от @neomib. Есть и другие библиотеки заставок, которые работают так же хорошо, например, https://github.com/crazycodeboy/react-native-splash-screen.

Любые предложения по раскадровке, используемой в качестве LaunchScreen?

Мой подход был таким (но приложение вылетает при запуске)

- (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;
}

приложение вылетает со следующей ошибкой:

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 -

Спасибо.

заменены

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

с участием

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

теперь приложение запускается, но у меня черный фон.

Или вы можете использовать https://github.com/crazycodeboy/react-native-splash-screen, это намного проще :)

Была ли эта страница полезной?
0 / 5 - 0 рейтинги