295 votes

Lorsque le clavier apparaît, les widgets de Flutter se redimensionnent. Comment éviter cela ?

J'ai une colonne de widgets étendus comme ceci :

 return new Container(
      child: new Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          new Expanded(
            flex: 1,
            child: convertFrom,
          ),
          new Expanded(
            flex: 1,
            child: convertTo,
          ),
          new Expanded(
            flex: 1,
            child: description,
          ),
        ],
      ),
    );

Ça ressemble à ça :

enter image description here

convertFrom comprend un champ de texte. Lorsque je tape sur ce champ de texte, le clavier Android apparaît à l'écran. Cela modifie la taille de l'écran, de sorte que les widgets se redimensionnent comme ceci :

enter image description here

Existe-t-il un moyen de faire en sorte que le clavier "recouvre" l'écran afin que ma colonne ne soit pas redimensionnée ? Si je n'utilise pas Expanded et coder en dur une hauteur pour chaque widget, les widgets ne se redimensionnent pas, mais j'obtiens l'erreur de la bande noire et jaune lorsque le clavier apparaît (parce qu'il n'y a pas assez d'espace). Cette méthode n'est pas non plus flexible pour toutes les tailles d'écran.

Je ne suis pas sûr que ce soit spécifique à Android ou à Flutter.

1 votes

Dans votre corps de Scaffold, utilisez un SingleChildScrollView.

662voto

aziza Points 11732

Réponse actualisée

resizeToAvoidBottomPadding est maintenant déprécié .

La solution mise à jour consiste à définir resizeToAvoidBottomInset à la propriété false .


Réponse originale

Dans votre Scaffold ensemble resizeToAvoidBottomPadding à la propriété false .

26 votes

Existe-t-il un moyen de produire un effet similaire à celui de la android:windowSoftInputMode="adjustPan" ? Si j'ajoute resizeToAvoidBottomPadding à l'échafaudage, il finit par couvrir le TextField.

4 votes

Je ne sais pas ce qu'il en est pour Android, mais c'est généralement une bonne pratique d'envelopper votre mise en page à l'intérieur d'une ListView dans ce cas.

0 votes

@aziza, j'ai souffert du même problème mais après votre solution son travail est bon, mais il y a un autre problème s'il vous plaît vérifier la vidéo du lien L'image clignotait lorsque le clavier apparaît. dropbox.com/s/lian92mnzz8kv9w/FlutterIssue1.mov?dl=0

130voto

Duncan Points 22780

La plupart des autres réponses suggèrent d'utiliser resizeToAvoidBottomPadding=false . D'après mon expérience, cela permet au clavier de couvrir les champs de texte s'ils se trouvent en dessous de l'endroit où le clavier apparaîtrait.

Ma solution actuelle consiste à forcer ma colonne à être de la même hauteur que l'écran, puis à la placer dans un fichier SingleChildScrollView pour que Flutter fasse automatiquement défiler mon écran vers le haut juste assez quand le clavier est utilisé.

Widget build(BuildContext context) {
  return Scaffold(
    body: SingleChildScrollView(
      physics: NeverScrollableScrollPhysics(),
      child: ConstrainedBox(
        constraints: BoxConstraints(
          minWidth: MediaQuery.of(context).size.width,
          minHeight: MediaQuery.of(context).size.height,
        ),
        child: IntrinsicHeight(
          child: Column(
            mainAxisSize: MainAxisSize.max,
            children: <Widget>[
              // CONTENT HERE
            ],
          ),
        ),
      ),
    ),
  );
}

J'utilise NeverScrollableScrollPhysics afin que l'utilisateur ne puisse pas se déplacer tout seul.

10 votes

J'ai essayé votre méthode sans NeverScrollableScrollPhysics et tout semble correct, sauf que l'utilisateur peut essayer de glisser vers le haut et vers le bas et il peut voir la lueur d'overscroll. Lorsque j'utilise la fonction NeverScrollableScrollPhysics cela me donne le même comportement que resizeToAvoidBottomInset

1 votes

Définissez la propriété primaire à false.

14 votes

Mais en utilisant NeverScrollableScrollPhysics fait en sorte qu'il ne soit pas défilé vers le haut avec le clavier aussi.

44voto

ArtiomLK Points 309

Définir resizeToAvoidBottomInset à false au lieu de resizeToAvoidBottomPadding qui est déprécié.

    return Scaffold(
      resizeToAvoidBottomInset : false,
      body: YourWidgets(),
    );

4 votes

Ce sont les mêmes réponses @Ojonugwa, peut-être que l'éditeur a mis à jour la réponse acceptée après que j'ai posté la mienne, donc maintenant la différence est que la mienne inclut un exemple ?

43voto

Den Points 448

Mon approche consiste à utiliser SingleChildScrollView avec le ClampingScrollPhysics physique.

SingleChildScrollView(
  physics: ClampingScrollPhysics(),
  child: Container(),
)

23voto

birca123 Points 200

Ma suggestion est d'utiliser resizeToAvoidBottomInset: false de toute façon pour empêcher les widgets de se redimensionner si le clavier apparaît soudainement à l'écran. Par exemple, si un utilisateur utilise les têtes de chat de Facebook alors qu'il se trouve dans votre application.

Pour empêcher le clavier de recouvrir les widgets, sur les écrans où vous en avez besoin, je suggère l'approche suivante, où est la hauteur de SingleChildScrollView réduit à la hauteur de l'espace disponible. Dans ce cas, SingleChildScrollView fait également défiler les pages vers le widget concerné.

final double screenHeight = MediaQuery.of(context).size.height;
final double keyboardHeight = MediaQuery.of(context).viewInsets.bottom;
return Scaffold(
  resizeToAvoidBottomInset: false,
  body: SizedBox(
    height: screenHeight - keyboardHeight,
    child: SingleChildScrollView(
      child: Column(
        children: [
          const SizedBox(height: 200),
          for (var i = 0; i < 10; i++) const TextField()
        ],
      ),
    ),
  ),
);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X