Cuando aparece el teclado, los widgets de Flutter cambian de tamaño. ¿Cómo prevenir esto?

101

Tengo una columna de widgets expandidos como este:

 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,
          ),
        ],
      ),
    );

Se parece a esto:

ingrese la descripción de la imagen aquí

convertFrom, incluye un TextField. Cuando toco este campo de texto, el teclado de Android aparece en la pantalla. Esto cambia el tamaño de la pantalla, por lo que los widgets cambian de tamaño así:

ingrese la descripción de la imagen aquí

¿Hay alguna manera de que el teclado "superponga" la pantalla para que mi columna no cambie de tamaño? Si no utilizo Expandedwidgets y codifico una altura para cada widget, los widgets no cambian de tamaño, pero aparece el error de rayas negras y amarillas cuando aparece el teclado (porque no hay suficiente espacio). Esto tampoco es flexible para todos los tamaños de pantalla.

No estoy seguro de si esto es específico de Android o de Flutter.

María
fuente
En su cuerpo de Scaffold, use SingleChildScrollView.
linhadiretalipe

Respuestas:

259

En su Scaffold, establezca la resizeToAvoidBottomInsetpropiedad en false.

La propiedad "resizeToAvoidBottomPadding" está obsoleta ahora .... En su Scaffold, establezca la resizeToAvoidBottomPaddingpropiedad en false.

aziza
fuente
11
¿Hay alguna forma de producir un efecto similar android:windowSoftInputMode="adjustPan"? Si agrego resizeToAvoidBottomPaddingal andamio, termina cubriendo el TextField.
Epicality
2
No sé sobre Android, pero generalmente es una buena práctica envolver su diseño dentro de un ListView en este caso
aziza
@aziza, sufría el mismo problema, pero después de su solución, funciona bien, pero hay otro problema, verifique el video del enlace La imagen parpadeaba cuando aparece el teclado. dropbox.com/s/lian92mnzz8kv9w/FlutterIssue1.mov?dl=0
Kishan Vyas
@KishanVyas lo mismo conmigo, la imagen se ha ido.
stuckedoverflow
@aziza Respuesta sólida
Val
27

La mayoría de las otras respuestas sugieren usar resizeToAvoidBottomPadding=false. En mi experiencia, esto permite que el teclado cubra los campos de texto si están debajo de donde aparecería el teclado.

Mi solución actual es forzar mi columna a tener la misma altura que la pantalla, luego colocarla de SingleChildScrollViewmanera que Flutter se desplace automáticamente lo suficiente por la pantalla cuando se usa el teclado.

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
            ],
          ),
        ),
      ),
    ),
  );
}

Lo uso NeverScrollableScrollPhysicspara que el usuario no pueda desplazarse por sí mismo.

Duncan Jones
fuente
2
Intenté NeverScrollableScrollPhysicshacerlo sin y todo se ve bien, excepto que el usuario puede intentar deslizar hacia arriba y hacia abajo y pueden ver el brillo de desplazamiento. Cuando uso el NeverScrollableScrollPhysics, me da el mismo comportamiento queresizeToAvoidBottomInset
Sajad Jaward
Establezca la propiedad principal en falso.
VLXU
16

Establecer en resizeToAvoidBottomInseten falselugar de resizeToAvoidBottomPaddingque está obsoleto.

    return Scaffold(
      resizeToAvoidBottomInset : false,
      body: YourWidgets(),
    );
ArtiomLK
fuente
¿En qué se diferencia esta respuesta de la aceptada?
Ojonugwa Jude Ochalifu
2
Son las mismas respuestas @Ojonugwa, tal vez el editor actualizó la respuesta aceptada después de que publiqué la mía, así que ahora la diferencia es que la mía incluye un ejemplo.
ArtiomLK
4

Método 1: Quitar android:windowSoftInputMode="adjustResize"del archivo AndroidManifest.xml (De lo contrario se anulará el código aleteo) y añadir resizeToAvoidBottomPadding: falseen Andamios, como a continuación:

Scaffold(
      resizeToAvoidBottomPadding: false,
      appBar: AppBar()
)

Método 2 (no recomendado): simplemente agregue android:windowSoftInputMode="stateVisible"AndroidManifest.xml de Android en la actividad, solo funcionará para Android y no para IOS.

<activity
       ...
        android:windowSoftInputMode="stateVisible">

Nota: No lo configure enandroid:windowSoftInputMode="adjustResize"

yatin deokar
fuente
4

Bueno, creo que si implementamos la solución de @ Aman, nuestra aplicación se comportará mal, ya que cuando aparece el teclado, no ajustará nuestra ventana de visualización de la pantalla según la altura disponible y hará que otros campos se escondan detrás del teclado. Así que sugiero usarlo SingleChildScrollViewen su lugar.

Envuelva su código SingleChildScrollViewcomo se indica a continuación,

 return new Container(
  child: SingleChildScrollView(
    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,
      ),
    ],
  ),
 ),
);
Deepak Jha
fuente
2

Dependiendo del caso de uso también se puede considerar el uso de una vista de lista . Eso aseguraría que el contenido se desplazara cuando no hay suficiente espacio. A modo de ejemplo, se puede ver en el campo de texto de demostración de la aplicación Galería

aptik
fuente
4
Pero esto aún no hace que el TextField que seleccionó sea visible, el teclado aún se superpondrá. Tienes que desplazarte tú mismo. No acostumbrado como desarrollador / usuario de Android
Chico
2

Mi enfoque es utilizarlo SingleChildScrollViewcon la ClampingScrollPhysicsfísica.

SingleChildScrollView(
  physics: ClampingScrollPhysics(),
  child: Container(),
)
Guarida
fuente
1

Para mí, cambiar la propiedad del artículo a continuación de verdadero a falso

<item name="android:windowFullscreen">false</item>

en archivo

android/app/src/main/res/values/styles.xml

ha hecho que Flutter arrastre todo el contenido de la página hacia arriba en el foco de entrada

Flutter arrastra todo el contenido de la página hacia arriba en el foco de entrada

javeedishaq
fuente
0

Mi sugerencia es usarlo de resizeToAvoidBottomInset: falsetodos modos para evitar que los widgets cambien de tamaño si el teclado aparece repentinamente en la pantalla. Por ejemplo, si un usuario usa cabezas de chat de Facebook mientras está en su aplicación.

Para evitar que el teclado se superponga a los widgets, en las pantallas donde lo necesite, sugiero el siguiente enfoque, donde se SingleChildScrollViewreduce la altura a la altura del espacio disponible. En este caso, SingleChildScrollViewtambién se desplaza hasta el widget enfocado.

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()
        ],
      ),
    ),
  ),
);
birca123
fuente