web-dev-qa-db-fra.com

Ajout d'un écran de démarrage aux applications Flutter

Comment aborderiez-vous l'ajout d'un écran de démarrage aux applications Flutter? Il devrait charger et afficher avant tout autre contenu. Il y a actuellement un bref éclair de couleur avant le chargement du widget Scaffold (home: X).

39
Pieter

Je veux apporter un peu plus de lumière sur la manière de faire écran Splash dans Flutter.

J'ai suivi un peu la trace ici et j'ai vu que l'écran Splash de Flutter ne semblait pas si mauvais.

Peut-être que la plupart des développeurs (comme moi) pensent qu'il n'y a pas d'écran Splash par défaut dans Flutter et qu'ils doivent faire quelque chose à ce sujet. En réalité, il existe un écran de démarrage, mais avec un fond blanc et personne ne peut comprendre qu’il existe déjà un écran de démarrage pour iOS et Android par défaut. 

C’est vraiment cool, car la seule chose que le développeur doit faire est de placer l’image de marque au bon endroit et l’écran de démarrage commencera à fonctionner comme ça.

Maintenant, voici comment cela peut être fait, étape par étape:

First pour Android (car c'est ma plate-forme préférée :))

  1. Recherchez le dossier "Android" dans votre projet Flutter. 

  2. Accédez au dossier app -> src -> main -> res et placez toutes les variantes de votre image de marque dans les dossiers correspondants. Par exemple:

    • l'image de densité 1 doit être placée dans mipmap-mdpi, 
    • l'image de densité 1.5 doit être placée dans mipmap-hdpi, 
    • l'image de densité 2 doit être placée dans mipmap-xdpi, 
    • l'image de densité 3 doit être placée dans mipmap-xxdpi,
    • l'image de densité 4 doit être placée dans mipmap-xxxdpi, 

Par défaut, le dossier Android ne contient pas drawable-mdpi, drawable-hdpi, etc., mais tout le monde peut créer s’il le souhaite. C'est pourquoi les images doivent être placées dans des dossiers mipmap. De plus, le code XML par défaut relatif à l'écran de démarrage (sous Android) sera examiné dans @mipmap et non dans @drawable (vous pouvez le modifier si vous le souhaitez).

  1. La dernière étape sous Android consiste à décommenter du code dans drawable/launch_background.xml. Naviguez vers app -> src -> main -> res-> drawable et ouvrez launch_background.xml. Dans ce fichier, vous verrez pourquoi le fond d'écran Slash est blanc. Pour appliquer l'image de marque que nous avons placée à l'étape 2, nous devons supprimer une partie du code XML de votre fichier launch_background.xml. Ainsi, après le changement, le code devrait ressembler à ceci:

    <!--<item Android:drawable="@Android:color/white" />-->
    
    <item>
    
        <bitmap
            Android:gravity="center"
            Android:src="@mipmap/your_image_name" />
    
    </item>
    

Veuillez faire attention à commenter le code d’arrière-plan blanc et à ne pas commenter le code relatif à l’image mipmap. Si quelqu'un est intéressé, ce fichier launch_background.xml est utilisé dans le fichier styles.xml.

Maintenant pour iOS:

  1. Recherchez le dossier "ios" dans votre projet Flutter. 

  2. Accédez à Runner -> Assets.xcassets -> LaunchImage.imageset. Il devrait y avoir LaunchImage.png, [email protected], etc. Vous devez maintenant remplacer ces images par vos variantes d'image de marque. Par exemple:

Si je ne me trompe pas, [email protected] n'existe pas par défaut, mais vous pouvez facilement en créer un. Si [email protected] n'existe pas, vous devez le déclarer également dans le fichier Contents.json, qui se trouve dans le même répertoire que les images. Après la modification, mon fichier Contents.json ressemble à ceci:

{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "LaunchImage.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "filename" : "[email protected]",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "filename" : "[email protected]",
      "scale" : "3x"
    },
    {
      "idiom" : "universal",
      "filename" : "[email protected]",
      "scale" : "4x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

Et cela devrait être tout. La prochaine fois que vous exécuterez votre application, sur Android et iOS, vous devriez avoir le bon écran de démarrage avec l'image de marque que vous avez ajoutée.

Merci

101
Sniper

Il n'y a pas encore de bon exemple, mais vous pouvez le faire vous-même en utilisant les outils natifs de chaque plate-forme:

iOS: https://docs.nativescript.org/publishing/creating-launch-screens-ios

Android: https://www.bignerdranch.com/blog/splash-screens-the-right-way/

Abonnez-vous à numéro 8147 pour les mises à jour d'exemples de code d'écrans de démarrage. Si le scintillement noir entre l'écran de démarrage et l'application sur iOS vous dérange, abonnez-vous à au numéro 8127 pour obtenir les mises à jour.

Edit: à compter du 31 août 2017, la prise en charge améliorée des écrans de démarrage est désormais disponible dans le nouveau modèle de projet. Voir # 11505 .

11
Collin Jackson

Si vous flutter created votre projet, vous pouvez suivre les étapes à https://flutter.io/assets-and-images/#updating-the-launch-screen

9
xster

Vous devriez essayer ci-dessous le code, a travaillé pour moi

import 'Dart:async';
import 'package:attendance/components/appbar.Dart';
import 'package:attendance/homepage.Dart';
import 'package:flutter/material.Dart';

class _SplashScreenState extends State<SplashScreen>
with SingleTickerProviderStateMixin {


void handleTimeout() {
  Navigator.of(context).pushReplacement(new MaterialPageRoute(
    builder: (BuildContext context) => new MyHomePage()));
}

startTimeout() async {
  var duration = const Duration(seconds: 3);
  return new Timer(duration, handleTimeout);
}

@override
void initState() {
  // TODO: implement initState
  super.initState();

  _iconAnimationController = new AnimationController(
      vsync: this, duration: new Duration(milliseconds: 2000));

  _iconAnimation = new CurvedAnimation(
      parent: _iconAnimationController, curve: Curves.easeIn);
  _iconAnimation.addListener(() => this.setState(() {}));

  _iconAnimationController.forward();

  startTimeout();
}

@override
Widget build(BuildContext context) {
  return new Scaffold(
    body: new Scaffold(
      body: new Center(
        child: new Image(
        image: new AssetImage("images/logo.png"),
        width: _iconAnimation.value * 100,
        height: _iconAnimation.value * 100,
      )),
    ),
  );
}
}
6
Jaldhi Bhatt

Pour Android, accédez à Android> app> src> main> res> drawable> launcher_background.xml

Désactivez maintenant cette option et remplacez @ mipmap/launch_image par l'emplacement de votre image.

<item>
      <bitmap
          Android:gravity="center"
          Android:src="@mipmap/launch_image" />
</item>

Vous pouvez changer la couleur de votre écran ici - 

<item Android:drawable="@Android:color/white" />
4

@ Collin Jackson et @ Sniper ont raison. Vous pouvez suivre ces étapes pour configurer les images de lancement dans Android et iOS respectivement. Ensuite, dans votre MyApp (), dans votre initState (), vous pouvez utiliser Future.delayed pour configurer un minuteur ou appeler une api. Jusqu'à ce que la réponse soit renvoyée de l'avenir, vos icônes de lancement s'afficheront. Ensuite, lorsque la réponse vous parviendra, vous pourrez accéder à l'écran de votre choix après l'écran d'accueil. Vous pouvez voir ce lien: Flutter Splash Screen

4
Vikas Pandey

les personnes qui obtiennent l'erreur telle qu'une image introuvable après l'application de la réponse vérifiée s'assurent d'ajouter @ mipmap/ic_launcher au lieu de @ mipmap/ic_launcher.png

4
Md Sadab Wasim

Ajouter une page comme ci-dessous et le routage peut aider

import 'Dart:async';

import 'package:flutter/material.Dart';
import 'package:flutkart/utils/flutkart.Dart';
import 'package:flutkart/utils/my_navigator.Dart';

class SplashScreen extends StatefulWidget {
  @override
  _SplashScreenState createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    Timer(Duration(seconds: 5), () => MyNavigator.goToIntro(context));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        fit: StackFit.expand,
        children: <Widget>[
          Container(
            decoration: BoxDecoration(color: Colors.redAccent),
          ),
          Column(
            mainAxisAlignment: MainAxisAlignment.start,
            children: <Widget>[
              Expanded(
                flex: 2,
                child: Container(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      CircleAvatar(
                        backgroundColor: Colors.white,
                        radius: 50.0,
                        child: Icon(
                          Icons.shopping_cart,
                          color: Colors.greenAccent,
                          size: 50.0,
                        ),
                      ),
                      Padding(
                        padding: EdgeInsets.only(top: 10.0),
                      ),
                      Text(
                        Flutkart.name,
                        style: TextStyle(
                            color: Colors.white,
                            fontWeight: FontWeight.bold,
                            fontSize: 24.0),
                      )
                    ],
                  ),
                ),
              ),
              Expanded(
                flex: 1,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    CircularProgressIndicator(),
                    Padding(
                      padding: EdgeInsets.only(top: 20.0),
                    ),
                    Text(
                      Flutkart.store,
                      softWrap: true,
                      textAlign: TextAlign.center,
                      style: TextStyle(
                          fontWeight: FontWeight.bold,
                          fontSize: 18.0,
                          color: Colors.white),
                    )
                  ],
                ),
              )
            ],
          )
        ],
      ),
    );
  }
}

Si vous souhaitez suivre, voir: https://www.youtube.com/watch?v=FNBuo-7zg2Q

3
goops17

Le code de Jaldhi Bhatt ne fonctionne pas pour moi.

Flutter génère une opération ' Navigator demandée avec un contexte n'incluant pas Navigator .'

J'ai corrigé le code englobant le composant consommateur Navigator à l'intérieur d'un autre composant qui initialise le contexte du navigateur à l'aide de routes, comme indiqué dans this article.

import 'Dart:async';

import 'package:flutter/material.Dart';
import 'package:my-app/view/main-view.Dart';

class SplashView extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
        home: Builder(
          builder: (context) => new _SplashContent(),
        ),
        routes: <String, WidgetBuilder>{
          '/main': (BuildContext context) => new MainView()}
    );
  }
}

class _SplashContent extends StatefulWidget{

  @override
  _SplashContentState createState() => new _SplashContentState();
}

class _SplashContentState extends State<_SplashContent>
    with SingleTickerProviderStateMixin {

  var _iconAnimationController;
  var _iconAnimation;

  startTimeout() async {
    var duration = const Duration(seconds: 3);
    return new Timer(duration, handleTimeout);
  }

  void handleTimeout() {
    Navigator.pushReplacementNamed(context, "/main");
  }

  @override
  void initState() {
    super.initState();

    _iconAnimationController = new AnimationController(
        vsync: this, duration: new Duration(milliseconds: 2000));

    _iconAnimation = new CurvedAnimation(
        parent: _iconAnimationController, curve: Curves.easeIn);
    _iconAnimation.addListener(() => this.setState(() {}));

    _iconAnimationController.forward();

    startTimeout();
  }

  @override
  Widget build(BuildContext context) {
    return new Center(
        child: new Image(
          image: new AssetImage("images/logo.png"),
          width: _iconAnimation.value * 100,
          height: _iconAnimation.value * 100,
        )
    );
  }
}
2
GiBi

Flutter donne en fait un moyen plus simple d’ajouter Splash Screen à notre application. Nous devons d’abord concevoir une page de base, tout comme nous concevons d’autres écrans d’application. Vous devez en faire un StatefulWidget puisque son état changera dans quelques secondes.

import 'Dart:async';
import 'package:flutter/material.Dart';
import 'home.Dart';

class SplashScreen extends StatefulWidget {
  @override
  _SplashScreenState createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  @override
  void initState() {
    super.initState();
    Timer(
        Duration(seconds: 3),
        () => Navigator.of(context).pushReplacement(MaterialPageRoute(
            builder: (BuildContext context) => HomeScreen())));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: Center(
        child: Image.asset('assets/splash.png'),
      ),
    );
  }
}

Logic Dans le initState (), appelez un Timer () avec la durée, comme vous le souhaitez, je l'ai fait 3 secondes, une fois terminé. Appuyez ensuite sur le navigateur pour Écran d'accueil de notre application.

Remarque: L'application ne doit afficher qu'un seul écran de démarrage, l'utilisateur ne doit pas y revenir en appuyant sur le bouton précédent. Pour cela, nous utilisonsNavigator.pushReplacement (), Il passera à un nouvel écran et supprimera l’écran précédent de la pile de l’historique de navigation.

Pour une meilleure compréhension, visitez Flutter: concevez votre propre écran de démarrage

1
kowsalya_ckar

Si vous souhaitez un écran de démarrage secondaire (après l’écran natif), voici un exemple simple qui fonctionne:

class SplashPage extends StatelessWidget {
  SplashPage(BuildContext context) {
    Future.delayed(const Duration(seconds: 3), () {
      // Navigate here to next screen
    });
  }

  @override
  Widget build(BuildContext context) {
    return Text('Splash screen here');
  }
}
1
david72

Plusieurs façons de le faire, mais la plus simple que j'utilise est:

J'utilise la bibliothèque Flutter pour les icônes de lancement Icône Flutter Launcher

Pour l'écran de démarrage personnalisé Je crée différentes résolutions d'écran, puis ajoute les images de démarrage dans le dossier mipmap conformément à la résolution pour Android.

La dernière partie ajuste le fichier launch_background.xml dans le dossier pouvant être dessiné dans le dossier res sous Android.

Il suffit de changer votre code pour ressembler à ceci:

<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <!-- <item Android:drawable="@Android:color/white" />
    <item Android:drawable="@drawable/<splashfilename>" />     --> -->

    <!-- You can insert your own image assets here -->
    <item>
        <bitmap
            Android:gravity="center"
            Android:src="@mipmap/<Your splash image name here as per the mipmap folder>"/>
    </item>
</layer-list>

Quelques développeurs que j'ai vus ajoutent le splash comme dessinable, j'ai essayé cela, mais d'une manière ou d'une autre, la construction échoue dans Flutter 1.0.0 et Dart SDK 2.0+. Par conséquent, je préfère ajouter le splash dans la section bitmap.

iOS La création d'un écran de démarrage est plutôt simple.

Dans le dossier Runner d’iOS, il suffit de mettre à jour les fichiers LaunchImage.png avec vos images d’écrans Splash personnalisées portant le même nom que LaunchImage.png @ 2x, @ 3x, @ 4x.

Juste un ajout qui me fait plaisir d’avoir une image 4x dans le jeu LaunchImage.images. Il suffit de mettre à jour votre code dans Content.json avec les lignes suivantes, en dessous de l'échelle 3x pour ajouter une option d'échelle 4x:

{
      "idiom" : "universal",
      "filename" : "[email protected]",
      "scale" : "4x"
    }
1
Prashant Gupta