Kiedy pojawi się klawiatura, zmieniają się rozmiary widżetów Flutter. Jak temu zapobiec?


114

Mam kolumnę rozszerzonych widżetów w następujący sposób:

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

To wygląda tak:

wprowadź opis obrazu tutaj

convertFrom, zawiera TextField. Po dotknięciu tego pola tekstowego na ekranie pojawia się klawiatura systemu Android. Zmienia to rozmiar ekranu, więc widżety zmieniają rozmiar w następujący sposób:

wprowadź opis obrazu tutaj

Czy istnieje sposób, aby klawiatura „nakładała” ekran, aby moja kolumna nie zmieniała rozmiaru? Jeśli nie używam Expandedwidżetów i nie zakoduję na stałe wysokości dla każdego widżetu, widżety nie zmieniają rozmiaru, ale pojawia się błąd w czarno-żółte paski, gdy pojawia się klawiatura (ponieważ nie ma wystarczającej ilości miejsca). Nie jest to również elastyczne dla wszystkich rozmiarów ekranu.

Nie jestem pewien, czy jest to specyficzne dla Androida, czy dla Fluttera.


W treści szkieletu użyj SingleChildScrollView.
linhadiretalipe

Odpowiedzi:


287

Zaktualizowana odpowiedź

resizeToAvoidBottomPaddingjest teraz przestarzała .

Zaktualizowanym rozwiązaniem jest ustawienie resizeToAvoidBottomInsetwłaściwości na false.


Oryginalna odpowiedź

W swoim Scaffoldustaw resizeToAvoidBottomPaddingwłaściwość na false.


11
Czy jest sposób, aby uzyskać podobny efekt android:windowSoftInputMode="adjustPan"? Jeśli dodam resizeToAvoidBottomPaddingdo rusztowania, zakryje to TextField.
Epicality

3
Nie wiem o Androidzie, ale ogólnie dobrą praktyką jest zawijanie układu wewnątrz ListView w tym przypadku
aziza

@aziza, cierpiałem na ten sam problem, ale po rozwiązaniu działa dobrze, ale jest inny problem, sprawdź wideo z linku. Obraz migał, gdy pojawia się klawiatura. dropbox.com/s/lian92mnzz8kv9w/FlutterIssue1.mov?dl=0
Kishan Vyas

@KishanVyas to samo ze mną obraz zniknął.
stuckedoverflow

@aziza Solid answer
Val

35

Większość innych odpowiedzi sugeruje użycie resizeToAvoidBottomPadding=false. Z mojego doświadczenia wynika, że ​​pozwala to klawiaturze zakrywać pola tekstowe, jeśli znajdują się pod miejscem, w którym pojawiłaby się klawiatura.

Moim obecnym rozwiązaniem jest wymuszenie, aby moja kolumna była tej samej wysokości co ekran, a następnie umieszczenie jej w taki SingleChildScrollViewsposób, aby Flutter automatycznie przewijał mój ekran tylko na tyle, gdy używana jest klawiatura.

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

Używam, NeverScrollableScrollPhysicsaby użytkownik nie mógł się przewijać.


4
Wypróbowałem twój sposób bez NeverScrollableScrollPhysicsi wszystko wygląda dobrze, z wyjątkiem tego, że użytkownik może próbować przesuwać palcem w górę iw dół i może zobaczyć poświatę nadmiernego przewijania. Kiedy używam, NeverScrollableScrollPhysicszachowuje się tak samo, jakresizeToAvoidBottomInset
Sajad Jaward,

Ustaw właściwość podstawową na false.
VLXU

1
ale używanie NeverScrollableScrollPhysicssprawia, że ​​nie jest on przewijany również za pomocą klawiatury.
hiwa doski

18

Ustaw resizeToAvoidBottomInsetaby falsezamiast resizeToAvoidBottomPaddingktóra jest nieaktualna.

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

3
To te same odpowiedzi @Ojonugwa, może redaktor zaktualizował zaakceptowaną odpowiedź po tym, jak opublikowałem moją, więc teraz różnica jest taka, że ​​moja zawiera przykład?
ArtiomLK

5

Moje podejście polega SingleChildScrollViewna ClampingScrollPhysicsfizyce.

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

4

Metoda 1: Usuń android:windowSoftInputMode="adjustResize"z pliku AndroidManifest.xml (w przeciwnym razie nadpisze kod flutter) i dodaj resizeToAvoidBottomPadding: falseScaffold, jak poniżej:

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

Metoda 2 (niezalecane): Po prostu dodaj android:windowSoftInputMode="stateVisible"w AndroidManifest.xml w działaniu, będzie działać tylko dla Androida i nie dla IOS.

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

Uwaga: nie ustawiaj go naandroid:windowSoftInputMode="adjustResize"


4

Cóż, myślę, że jeśli zaimplementujemy rozwiązanie @ Aman, nasza aplikacja będzie zachowywać się brzydko, ponieważ gdy pojawi się klawiatura, nie dostosuje naszego widoku ekranu do dostępnej wysokości i rozróżni inne pola ukryte za klawiaturą. Więc sugerowałbym użycie SingleChildScrollViewzamiast tego.

Owiń swój kod, SingleChildScrollViewjak podano poniżej,

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

zdajesz sobie sprawę z tego, że spowoduje to natychmiastowe pojawienie się masy błędów, ponieważ rozszerzony widżet będzie miał nieskończoną ilość miejsca do wypełnienia, podaną przez pojedynczy widok przewijania
Christian X

3

Sugeruję, aby resizeToAvoidBottomInset: falsemimo wszystko użyć, aby zapobiec zmianie rozmiaru widżetów, jeśli klawiatura nagle pojawi się na ekranie. Na przykład, jeśli użytkownik korzysta z czatów na Facebooku w Twojej aplikacji.

Aby klawiatura nie nakładała się na widżety, na ekranach, na których jest to potrzebne, proponuję następujące podejście, w którym wysokość jest SingleChildScrollViewzmniejszona do wysokości dostępnej przestrzeni. W tym przypadku SingleChildScrollViewprzewija się również do wybranego widżetu.

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

2

W zależności od przypadku użycia możesz również rozważyć użycie widoku listy . Zapewniłoby to przewijanie zawartości, gdy nie ma wystarczającej ilości miejsca. Jako przykład możesz spojrzeć na demo Textfield w aplikacji Galeria


4
Ale to nadal nie sprawia, że ​​pole tekstowe, które wybrałeś, jest widoczne, klawiatura nadal będzie na nie nakładać. Musisz sam to przewinąć. Nie przyzwyczajony do tego jako programista / użytkownik Androida
Boy

1

Dla mnie zmiana poniżej właściwości item z true na false

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

w pliku

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

sprawił, że Flutter przeciąga całą zawartość strony w górę na fokus wprowadzania danych

Flutter przeciągnij całą zawartość strony w górę na fokus wprowadzania


to będzie działać tylko dla Androida, tak jak się wydaje ...
Christian X

1

Miałem ten sam problem i zacząłem próbować losowych rozwiązań, aby go naprawić, a nagle to naprawiło. wprowadź opis obrazu tutaj

Owiń główny kontener nadrzędny w SingleChildScrollView () i podaj mu wysokość urządzenia, tj. Device_height = MediaQuery.of (context) .size.height.

Spowoduje to przewijanie całej strony, ale nie zmieni rozmiaru żadnego widżetu.


Działa idealnie! Dzięki!!
Gihan Sandaru

Cieszę się, że mogłem pomóc!
Rudr Thakur
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.