D/InputConnectionAdaptor(3218):输入法开启光标监控

问题描述 投票:0回答:4

这是我在

auth_screen.dart
文件中的卡片小部件中使用的表格的一部分:

child: Obx(() => Form(
      key: _formKey,
      child: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            TextFormField(
              decoration: const InputDecoration(labelText: 'E-Mail'),
              keyboardType: TextInputType.emailAddress,
              validator: (value) {
                if (value!.isEmpty || !value.contains('@')) {
                  return 'Invalid email!';
                }
              },
              onSaved: (value) {
                _authData['email'] = value as String;
              },
            ),
            TextFormField(
              decoration: const InputDecoration(labelText: 'Password'),
              obscureText: true,
              controller: _passwordController,
              validator: (value) {
                if (value!.isEmpty || value.length < 5) {
                  return 'Password is too short!';
                }
              },
              onSaved: (value) {
                _authData['password'] = value as String;
              },
            ),

有两个

TextFormField
用于电子邮件和密码。

还有相关的

auth_controller.dart
文件如下:

enum AuthMode { Signup, Login }

class AuthController extends GetxController
    with GetSingleTickerProviderStateMixin {
  static AuthController instance = Get.find();
  Rx<dynamic>? authMode = AuthMode.Login.obs;
  RxBool? isLoading = false.obs;
  String? _token;
  DateTime? _expiryDate;
  String? _userId;
  Timer? _authTimer;
  final _isAuth = false.obs;

  AnimationController? controller;
  Animation<Offset>? slideAnimation;
  Animation<double>? opacityAnimation;
  late TextEditingController passwordController;
  final key = GlobalKey<FormState>();

  @override
  void onInit() {
    super.onInit();
    tryAutoLogin();
    controller = AnimationController(
      vsync: this,
      duration: const Duration(
        milliseconds: 300,
      ),
    );
    slideAnimation = Tween<Offset>(
      begin: const Offset(0, -1.5),
      end: const Offset(0, 0),
    ).animate(
      CurvedAnimation(
        parent: controller as Animation<double>,
        curve: Curves.fastOutSlowIn,
      ),
    );
    opacityAnimation = Tween(begin: 0.0, end: 1.0).animate(
      CurvedAnimation(
        parent: controller as Animation<double>,
        curve: Curves.easeIn,
      ),
    );
    // _heightAnimation.addListener(() => setState(() {}));

    passwordController = TextEditingController();
  }

  @override
  void onClose() {
    super.onClose();
    passwordController.dispose();
  }

  bool get isAuth {
    _isAuth.value = token != null;
    return _isAuth.value;
  }

  String? get token {
    if (_expiryDate != null &&
        _expiryDate!.isAfter(DateTime.now()) &&
        _token != null) {
      return _token;
    }
    return null;
  }

  String? get userId {
    return _userId;
  }

  Future<void> _authenticate(
      String email, String password, String urlSegment) async {
    // print('app is here!!!5555');
    // const host = "localhost";
    final host = UniversalPlatform.isAndroid ? '10.0.2.2' : '127.0.0.1';
    final url = Uri.parse('http://$host:8000/api/$urlSegment');

    try {
      final http.Response response = await http.post(
        url,
        headers: {"Content-Type": "application/json"},
        body: json.encode(
          {
            'email': email,
            'password': password,

            //'returnSecureToken': true,
          },
        ),
      );
      // print('this is responsde ' );
      // print(response);

      final responseData = json.decode(response.body);
        print(responseData);

      if (responseData['error'] != null) {
        throw HttpException(responseData['error']['message']);
      } else {
        _token = responseData['idToken'];
        _userId = responseData['id'];
        _expiryDate = DateTime.now().add(
          Duration(
            milliseconds: responseData['expiresIn'],
          ),
        );
      }
      _autoLogout();
      // update();
      final prefs = await SharedPreferences.getInstance();
      final userData = json.encode(
        {
          'token': _token,
          'userId': _userId,
          'expiryDate': _expiryDate!.toIso8601String(),
        },
      );
      prefs.setString('userData', userData);
      isLoading?.value = false;

      // print(prefs.getString('userData'));
      Get.toNamed(rootRoute);
    } catch (error) {
      throw error;
    }
  }

  Future<void> signup(String email, String password) async {
    return _authenticate(email, password, 'signup');
  }

  Future<void> login(String email, String password) async {
    return _authenticate(email, password, 'sessions');
  }

  Future<bool> tryAutoLogin() async {
final prefs = await SharedPreferences.getInstance();
    if (!prefs.containsKey('userData')) {
      return false;
    }
    final Map<String, Object> extractedUserData = Map<String, Object>.from(
        json.decode(prefs.getString('userData') as String));
    final expiryDate =
        DateTime.parse(extractedUserData['expiryDate'] as String);

    if (expiryDate.isBefore(DateTime.now())) {
      return false;
    }
    _token = extractedUserData['token'] as String;
    _userId = extractedUserData['userId'] as String;
    _expiryDate = expiryDate;
     _isAuth.value = true;
    _autoLogout();
    return true;
  }

  Future<void> logout() async {
    _token = null;
    _userId = null;
    _expiryDate = null;
    if (_authTimer != null) {
      _authTimer!.cancel();
      _authTimer = null;
    }
    // update();
    final prefs = await SharedPreferences.getInstance();
    // prefs.remove('userData');
    prefs.clear();
    _isAuth.value = false;
  }

  void _autoLogout() {
    if (_authTimer != null) {
      _authTimer!.cancel();
    }
    final timeToExpiry = _expiryDate!.difference(DateTime.now()).inSeconds;
    _authTimer = Timer(Duration(seconds: timeToExpiry), logout);
  }
}

当我启动应用程序时它似乎运行没有错误但是当我点击

TextFormField
s输入电子邮件或密码时,Android模拟器上的虚拟键盘立即打开和关闭并且不允许我输入任何内容.它还在 DEBUG CONSOLE 中显示以下消息:

D/InputConnectionAdaptor(3218):输入法切换光标 监控

flutter android-emulator android-softkeyboard inputconnection
4个回答
2
投票

就我而言,解决方案是将 GlobalKey() 从 build () 方法中移除

关闭键盘:

Form(key: GlobalKey<FormState>());

解决方案:

final _formKey = GlobalKey<FormState>();
Form(key: _formKey)

1
投票

经过这么多的努力,我发现代替

StateLessWidget
请使用
StatefullWidget
。 希望对你有帮助!


0
投票

key
上设置“
TextFormField
”属性为我解决了这个问题。我在
initState
方法中创建了密钥(尽管它可能在其他地方创建),使用
GlobalKey<FormFieldState>()
构造函数。


0
投票

我遇到了同样的问题。解决方案是使用 Stateful Widget 并将 _formkey 直接放在类范围下,而不是在 Widget 构建下。

    class _SignupFormState extends State<SignupForm> {
  final _formkey = GlobalKey<FormState>();
  @override
  Widget build(BuildContext context) {
//rest of the code
}
© www.soinside.com 2019 - 2024. All rights reserved.