Коли з’являється клавіатура, віджети Flutter змінюють розмір. Як цього запобігти?


101

У мене є Стовпець розширених віджетів, подібний до цього:

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

Це виглядає так:

введіть тут опис зображення

convertFrom, включає TextField. Коли я натискаю на це текстове поле, на екрані з’являється клавіатура Android. Це змінює розмір екрана, тому віджети змінюються таким чином:

введіть тут опис зображення

Чи є спосіб клавіатури "накласти" екран так, щоб мій стовпець не змінив розмір? Якщо я не використовую Expandedвіджети та жорстко кодую висоту для кожного віджета, віджети не змінюють розмір, але при появі клавіатури з’являється чорно-жовта смугаста помилка (оскільки місця недостатньо). Це також не гнучко для всіх розмірів екрану.

Я не впевнений, що це для Android чи для Flutter.


У вашому тілі риштування використовуйте SingleChildScrollView.
linhadiretalipe

Відповіді:


263

У вашому Scaffold, встановіть для resizeToAvoidBottomInsetвластивості false.

Властивість "resizeToAvoidBottomPadding" зараз застаріло .... У вашому Scaffold, встановіть для resizeToAvoidBottomPaddingвластивості false.


11
Чи є спосіб зробити подібний ефект android:windowSoftInputMode="adjustPan"? Якщо я додаю resizeToAvoidBottomPaddingдо ешафоту, це закінчується покриттям TextField.
Епічність

2
Я не знаю про android, але загалом є гарною практикою загортати свій макет всередину ListView - у цьому випадку
aziza

@aziza, я страждав від тієї ж проблеми, але після вашого рішення все працює нормально, але є ще одна проблема, перевірте відео за посиланням Зображення блимало, коли з'являється клавіатура. dropbox.com/s/lian92mnzz8kv9w/FlutterIssue1.mov?dl=0
Кішан Вяс

@KishanVyas те саме зі мною зображення вже немає.
застряг у переливі

@aziza Тверда відповідь
Вал

28

Більшість інших відповідей пропонують використовувати resizeToAvoidBottomPadding=false. На моєму досвіді це дозволяє клавіатурі прикривати текстові поля, якщо вони знаходяться внизу, де клавіатура відображається.

Моє поточне рішення полягає в тому, щоб примусити мою колонку дорівнювати висоті екрана, а потім помістити її SingleChildScrollViewтак, щоб Flutter автоматично прокручував мій екран настільки, наскільки достатньо, коли використовується клавіатура.

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

Я використовую, NeverScrollableScrollPhysicsщоб користувач не міг прокручувати навколо себе.


3
Я спробував ваш шлях без, NeverScrollableScrollPhysicsі все виглядає нормально, за винятком того, що користувач може спробувати провести пальцем вгору і вниз, і вони можуть побачити світіння прокрутки. Коли я використовую це, NeverScrollableScrollPhysicsце дає мені таку ж поведінку, якresizeToAvoidBottomInset
Сажад Джавард,

Встановіть для первинної властивості значення false.
VLXU

16

Набір resizeToAvoidBottomInsetдля falseзамість resizeToAvoidBottomPaddingяких є застарілим.

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

Чим ця відповідь відрізняється від прийнятої?
Ojonugwa Jude Ochalifu

2
Вони однакові відповіді @Ojonugwa, можливо, редактор оновив прийняту відповідь після того, як я опублікував свою, тому тепер різниця полягає в тому, що моя містить приклад?
ArtiomLK

4

Спосіб 1: Видаліть android:windowSoftInputMode="adjustResize"з файлу AndroidManifest.xml (інакше він замінить код розвівання) і додайте resizeToAvoidBottomPadding: falseв Scaffold, як показано нижче:

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

Спосіб 2 (не рекомендується): Просто додайте android:windowSoftInputMode="stateVisible"в android AndroidManifest.xml в активність, це буде працювати лише для Android, а не для IOS, як.

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

Примітка. Не встановлюйте для нього значенняandroid:windowSoftInputMode="adjustResize"


4

Ну, я думаю, якщо ми застосуємо рішення @ Aman, це призведе до того, що наш додаток буде поводитись потворно, оскільки, коли з’являється клавіатура, він не буде коригувати область огляду екрана відповідно до доступної висоти, а інші поля будуть сховані за клавіатурою. Тому я б запропонував використовувати SingleChildScrollViewзамість цього.

Оберніть свій код, SingleChildScrollViewяк зазначено нижче,

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

2

В залежності від випадку використання ви могли б також розглянути можливість використання ListView . Це забезпечить прокручування вмісту, коли місця недостатньо. Як приклад, ви можете переглянути демонстрацію текстового поля в додатку галерея


4
Але це все одно не робить поле TextField, яке ви вибрали, видимим, клавіатура все одно перекриватиме його. Ви повинні прокрутити його самостійно. Не звик як розробник / користувач Android
Хлопчик

2

Мій підхід полягає у використанні SingleChildScrollViewз ClampingScrollPhysicsфізикою.

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

1

Для мене зміна властивості нижче елемента з true на false

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

у файлі

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

змусив Flutter перетягувати весь вміст сторінки вгору на фокус введення

Флаттер перетягує весь вміст сторінки вгору на фокусі введення


0

Моя пропозиція - використовувати в resizeToAvoidBottomInset: falseбудь-якому випадку, щоб запобігти зменшенню розміру віджетів, якщо на екрані раптом з’явиться клавіатура. Наприклад, якщо користувач використовує голови чату Facebook, перебуваючи у вашому додатку.

Щоб клавіатура не накладала віджети, на екранах, де це потрібно, я пропоную такий підхід, де висота SingleChildScrollViewзменшена до висоти доступного місця. У цьому випадку SingleChildScrollViewтакож прокручується до сфокусованого віджета.

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()
        ],
      ),
    ),
  ),
);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.