フラッターキーボードのポップアップとクローズモニタリング

遭遇の問題

PinCodeField確認コードコントロールを使用しているときに問題が発生しました。Androidでは、キーボードの右上隅にある閉じるキーボードをタップまたはタップしても、PinCodeFieldがフォーカスを失うことはありません。そのため、キーボードを閉じた後、PinCodeFieldはフォーカスを取得する状態になり、もう一度クリックすると、PinCodeFieldがフォーカスを取得してキーボードをポップアップするため、キーボードのポップアップとクローズを監視して、対応するフォーカス状態を設定する必要があります。

解決

最初に使用するkeyboard_visibilityサードパーティライブラリ

keyboard_visibilityキーボードポップアップクローズモニタリング

この開発者は長い間それを更新していないので、互換性がないときに自分で変更できるように、コードをローカルにプルしました。

使用する場合は、ローカル依存関係が優先されます。メインプロジェクトと同じディレクトリに配置し、次のメソッドを使用して依存します。

keyboard_visibility:
    path: ../flutter_keyboard_visibility

使用する:

import 'package:keyboard_visibility/keyboard_visibility.dart';


 int subscribeId;

 @protected
 void initState() {
   super.initState();
   subscribeId = KeyboardVisibilityNotification().addNewListener(
     onChange: (bool visible) {
       print(visible);
     },
   );
 }

 //及时移除防止内存泄漏问题 "A LoginInputCodeViewModel was used after being disposed."
 @override
  void dispose() {
    KeyboardVisibilityNotification().removeListener(subscribeId);
    super.dispose();
  }

著者の古いバージョンの使用中に以下の問題が発生した場合:

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':keyboard_visibility:verifyReleaseResources'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
   > 1 exception was raised by workers:
     com.android.builder.internal.aapt.v2.Aapt2Exception: Android resource linking failed
     C:\Users\Administrator\.gradle\caches\transforms-2\files-2.1\da95e0dd41fd0c634661df2a0f122634\core-1.1.0\res\values\values.xml:142:5-173:25: AAPT: error: resource android:attr/fontVariationSettings not found.

     C:\Users\Administrator\.gradle\caches\transforms-2\files-2.1\da95e0dd41fd0c634661df2a0f122634\core-1.1.0\res\values\values.xml:142:5-173:25: AAPT: error: resource android:attr/ttcIndex not found.

keyboard_visibilityディレクトリのbuild.gradleのcompileSdkVersionを27から28に変更してください:
ここに画像の説明を挿入

Keyboard_visibilityが詳細に使用され、このフォークライブラリはすでに上記の問題に対処しています

2番目の使用WidgetsBindingObserverとdidChangeMetrics

WidgetsBindingObserverコンポーネントは、ページのいくつかのライフサイクルを監視でき、インターフェイスの高さの変化を監視できるコールドdidChangeMetricsがあります。その中でも、キーボードのポップアップと折りたたみは実際には高さの変化であり、自然に監視できます。

使用する:

class _PinCodeTextFieldState extends State<PinCodeTextField> with WidgetsBindingObserver {

  bool isKeyboardActived = false;

 @protected
void initState() {
 //根据autoFocus赋予isKeyboardActived初值,自动获取焦点的话键盘是自动弹出的需要赋值为true正好和autoFocus对应
 isKeyboardActived = widget.autoFocus;
 WidgetsBinding.instance.addObserver(this);
   super.initState();
}

@override
  void didChangeMetrics() {
    super.didChangeMetrics();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      // 当前是安卓系统并且在焦点聚焦的情况下
      if (Platform.isAndroid && _focusNode.hasFocus) {
        if (isKeyboardActived) {
          isKeyboardActived = false;
          // 使输入框失去焦点
          _focusNode.unfocus();
          return;
        } else {
//          showToast("键盘弹出 false");
        }
        isKeyboardActived = true;
      } else {
        isKeyboardActived = false;
//        showToast("键盘消失");
      }
    });
  }

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

PinCodeTextFieldと組み合わせた特定の使用法は次のとおりです。

class PinCodeTextField extends StatefulWidget {
 
  /// If the pin code field should be autofocused or not. Default is [false]
  final bool autoFocus;

  /// Should pass a [FocusNode] to manage it from the parent
  final FocusNode focusNode;

  PinCodeTextField({
    Key key,
    //省略代吗...
    this.autoFocus = false,
    this.focusNode,
	//省略代吗...
  }) : super(key: key);
}

class _PinCodeTextFieldState extends State<PinCodeTextField>
    with WidgetsBindingObserver {//重点
  FocusNode _focusNode;
  bool isKeyboardActived = false;

  @override
  void initState() {
	 //重点
    isKeyboardActived = widget.autoFocus;
    //重点
    WidgetsBinding.instance.addObserver(this);
    _focusNode = widget.focusNode ?? FocusNode();
    _focusNode.addListener(() {
      setState(() {});
    }); 
    super.initState();
  }

  // validating all the values
  void _checkForInvalidValues() {
   //省略代吗...
  }


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


  @override
  Widget build(BuildContext context) {
    return Stack(
    	//省略代吗...
        GestureDetector(
          onTap: _onFocus,
        	//省略代吗...
          child: Container(
            //省略代吗...
          ),
        ),
      ],
    );
  }
   //重点
  @override
  void didChangeMetrics() {
    super.didChangeMetrics();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      // 当前是安卓系统并且在焦点聚焦的情况下
      if (Platform.isAndroid && _focusNode.hasFocus) {
        if (isKeyboardActived) {
          isKeyboardActived = false;
          // 使输入框失去焦点
          _focusNode.unfocus();
          return;
        } else {
//          showToast("键盘弹出 false");
        }
        isKeyboardActived = true;
      } else {
        isKeyboardActived = false;
//        showToast("键盘消失");
      }
    });
  }
 //重点
  void _onFocus() {
    if (_focusNode.hasFocus) {
//      showToast("点击 hasFocus");
      _focusNode.unfocus();
    } else {
//      showToast("点击 noFocus");
      FocusScope.of(context).requestFocus(_focusNode);
    }
  }
}

参照:Flutterキーボードがポップアップして監視を閉じます

おすすめ

転載: blog.csdn.net/u011148116/article/details/106902318