Держите мягкую клавиатуру открытой при переключении приложений на Android (Flutter)

Вопрос или проблема

Описание

Исходная ситуация:

  • Текстовое поле в моем приложении имеет фокус. Софт-клавиатура открыта.

  • Пользователь временно переключается на другое приложение.

Ожидание:

  • Когда пользователь переключается обратно в моё приложение, софт-клавиатура должна быть готова немедленно.

На самом деле, софт-клавиатура скрыта. Мне сначала нужно снова на неё нажать.

С Flutter (к сожалению):

Я могу отслеживать с помощью WidgetsBindingObserver, когда моё приложение снова активно, и показать клавиатуру снова с помощью SystemChannels.textInput.invokeMethod('TextInput.show'), но клавиатура скрыта и снова показывается, что очень раздражает:

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

С Compose (так, как бы мне хотелось)

Ситуация другая, если у меня есть родное текстовое поле в Android. Софт-клавиатура вообще не скрывается (что я пытаюсь добиться с помощью Flutter):

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

Усилия

  • Я пробовал разные значения для android:windowSoftInputMode в AndroidManifest.xml без каких-либо улучшений или даже изменений.

Мой код

Программа будет выглядеть так в Compose:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            parent
            Box(
                modifier = Modifier
                    .fillMaxHeight(),
                contentAlignment = Alignment.Center
            ) {
                TextField(
                    modifier = Modifier.fillMaxWidth(),
                    value = "", onValueChange = {}
                )
            }
        }
    }
}

И лучшее, что я смог добиться с помощью Flutter:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(
    const App(),
  );
}

class App extends StatelessWidget {
  const App({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Home(),
    );
  }
}

class Home extends StatefulWidget {
  const Home({super.key});

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> with WidgetsBindingObserver {
  final _focusNode = FocusNode();
  late final TextEditingController _controller;

  @override
  void initState() {
    super.initState();
    _controller = TextEditingController();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    _focusNode.dispose();
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    if (state == AppLifecycleState.resumed) {
      SystemChannels.textInput.invokeMethod('TextInput.show');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Center(
        child: TextField(
          focusNode: _focusNode,
          controller: _controller,
          autofocus: true,
        ),
      ),
    );
  }
}

Вопрос

Как мне сделать так, чтобы текстовое поле в Flutter снова появлялось сразу под Android, если пользователь переключался между приложениями и возвращается в мое приложение?

Ответ или решение

Для решения проблемы по автоматическому отображению виртуальной клавиатуры в приложении Flutter на платформе Android после переключения между приложениями, необходимо учесть несколько аспектов настройки вашего приложения и обработки состояния жизненного цикла.

Введение

При разработке мобильных приложений часто возникает необходимость обеспечить удобный и интуитивно понятный интерфейс для пользователей, особенно в контексте работы с текстовыми полями. Одна из таких распространенных проблем заключается в том, что виртуальная клавиатура скрывается при переключении между приложениями, даже если текстовое поле остается активным. Это может ухудшить пользовательский опыт, так как требует дополнительных действий для её повторного отображения.

Проблема

Согласно вашему описанию, когда пользователь возвращается в ваше Flutter-приложение после переключения на другое, виртуальная клавиатура не отображается автоматически, несмотря на то, что текстовое поле имеет фокус. Вы уже пробовали изменить различные значения параметра android:windowSoftInputMode в файле AndroidManifest.xml без успеха и используете SystemChannels.textInput.invokeMethod('TextInput.show'), что приводит к мерцанию клавиатуры.

Решение

Для достижения желаемого поведения и обеспечения того, чтобы виртуальная клавиатура открывалась автоматически при возвращении в приложение, можно использовать комбинацию правильной настройки AndroidManifest и программного управления фокусом в Flutter.

  1. Настройка AndroidManifest.xml

    В вашем AndroidManifest.xml попробуйте установить значение adjustResize для android:windowSoftInputMode для вашей активности:

    <activity
       android:name=".MainActivity"
       android:windowSoftInputMode="stateVisible|adjustResize">
    </activity>

    Это может помочь приложениям сохранять состояние клавиатуры между переключениями.

  2. Программное управление фокусом и видимостью клавиатуры

    На уровне Flutter, обеспечьте наличие фокуса в вашем текстовом поле после возвращения в приложение. Вместо того чтобы просто вызывать метод для отображения клавиатуры, лучше использовать фокусное состояние, чтобы гарантировать, что текстовое поле остается активным.

    Вот исправленный вариант вашего кода, где клавиатура будет открываться автоматически при возвращении в приложение:

    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    
    void main() {
     runApp(const App());
    }
    
    class App extends StatelessWidget {
     const App({super.key});
    
     @override
     Widget build(BuildContext context) {
       return const MaterialApp(
         home: Home(),
       );
     }
    }
    
    class Home extends StatefulWidget {
     const Home({super.key});
    
     @override
     State<Home> createState() => _HomeState();
    }
    
    class _HomeState extends State<Home> with WidgetsBindingObserver {
     final _focusNode = FocusNode();
     late final TextEditingController _controller;
    
     @override
     void initState() {
       super.initState();
       _controller = TextEditingController();
       WidgetsBinding.instance.addObserver(this);
       _focusNode.requestFocus(); // Убедитесь, что поле ввода получает фокус сразу
     }
    
     @override
     void dispose() {
       _focusNode.dispose();
       WidgetsBinding.instance.removeObserver(this);
       super.dispose();
     }
    
     @override
     void didChangeAppLifecycleState(AppLifecycleState state) {
       super.didChangeAppLifecycleState(state);
       if (state == AppLifecycleState.resumed) {
         // Вернем фокус на текстовое поле
         _focusNode.requestFocus();
       }
     }
    
     @override
     Widget build(BuildContext context) {
       return Material(
         child: Center(
           child: TextField(
             focusNode: _focusNode,
             controller: _controller,
             autofocus: true,
           ),
         ),
       );
     }
    }

Заключение

Применив предложенные выше изменения в коде и настройках манифеста, вы сможете улучшить удобство использования вашего приложения и удовлетворить ожидания пользователей в отношении работы с виртуальной клавиатурой. Эти шаги должны гарантировать, что клавиатура будет возвраждена автоматически при возврате пользователя в ваше приложение, что сделает взаимодействие более плавным.

Если у вас возникнут дальнейшие вопросы или потребуется дополнительная помощь, не стесняйтесь обращаться за поддержкой!

Оцените материал
Добавить комментарий

Капча загружается...