Problemas de encuentro
Encontré un problema al usar el control de código de verificación PinCodeField . En Android, tocar hacia atrás o tocar el teclado de cierre en la esquina superior derecha del teclado no hará que PinCodeField pierda el enfoque, por lo que después de cerrar el teclado, PinCodeField ha estado en un estado de obtención de enfoque y no puede Haga clic de nuevo para que PinCodeField obtenga el foco para que aparezca el teclado, por lo que tenemos que monitorear la ventana emergente y el cierre del teclado para establecer el estado de enfoque correspondiente.
solución
El primer uso de la biblioteca de terceros keyboard_visibility
keyboard_visibility teclado emergente monitorización cercana
Este desarrollador no lo ha actualizado durante mucho tiempo, así que extraje el código localmente para poder modificarlo yo mismo cuando no sea compatible.
Si se usa, prevalecerá la dependencia local. Colóquelo en el mismo directorio que nuestro proyecto principal y use el siguiente método para depender de:
keyboard_visibility:
path: ../flutter_keyboard_visibility
utilizar:
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();
}
Si encuentra los siguientes problemas al usar la versión anterior del autor:
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.
Cambie compileSdkVersion en build.gradle en el directorio keyboard_visibility de 27 a 28:
El segundo uso WidgetsBindingObserver y didChangeMetrics
El componente WidgetsBindingObserver puede monitorear algunos ciclos de vida de la página, y hay una devolución de llamada didChangeMetrics que puede monitorear los cambios en la altura de la interfaz. Entre ellos, las ventanas emergentes y desplegables del teclado son en realidad cambios de altura y, naturalmente, se pueden monitorear.
utilizar:
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();
}
El uso específico en combinación con PinCodeTextField es el siguiente:
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);
}
}
}
Referencia: el teclado Flutter aparece y cierra la monitorización