遭遇の問題
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);
}
}
}