flutter 如何通过保留文本字段文本来取消对键盘的聚焦?

tag5nh1u  于 2023-05-30  发布在  Flutter
关注(0)|答案(1)|浏览(160)

我有一个登录屏幕,我做了一个有状态的自定义文本字段小部件,然后我在登录屏幕中使用这个小部件的电子邮件和密码部分。问题是,当我通过点击文本字段外取消屏幕焦点时,不同文本字段中的所有文本都被删除。我怎样才能摆脱这个问题?
自定义文本字段:

import 'package:flutter/material.dart';
import 'package:flutter_parisa/constants.dart';

class TextInputField extends StatefulWidget {
  final String labelText;
  final TextEditingController controller;
  bool isObscure;
  final IconData icon;
  final bool hasSuffixIcon;

  TextInputField(
      {super.key,
      required this.labelText,
      required this.controller,
      required this.icon,
      this.isObscure = false,
      required this.hasSuffixIcon});

  @override
  State<TextInputField> createState() => _TextInputFieldState();
}

class _TextInputFieldState extends State<TextInputField> {
  final GlobalKey _key = GlobalKey();
  void toggleObscure() {
    setState(() {
      widget.isObscure = !widget.isObscure;
    });
  }

  void unFocus() {
    FocusScope.of(context).unfocus();
  }

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _key,
      child: TextFormField(
        onTapOutside: (event) {
          FocusScope.of(context).unfocus();
        },
        controller: widget.controller,
        obscureText: widget.isObscure,
        decoration: InputDecoration(
          labelStyle: const TextStyle(color: authbuttonColor),
          prefixIconColor: authbuttonColor,
          suffixIcon: widget.hasSuffixIcon
              ? IconButton(
                  onPressed: () {
                    toggleObscure();
                  },
                  icon: widget.isObscure
                      ? const Icon(
                          Icons.visibility,
                          color: authbuttonColor,
                        )
                      : const Icon(
                          Icons.visibility_off,
                          color: authbuttonColor,
                        ))
              : null,
          prefixIcon: Icon(widget.icon),
          labelText: widget.labelText,
          enabledBorder: OutlineInputBorder(
              borderRadius: BorderRadius.circular(5),
              borderSide: const BorderSide(
                color: authbuttonColor,
              )),
          focusedBorder: OutlineInputBorder(
              borderRadius: BorderRadius.circular(5),
              borderSide: BorderSide(color: focusedBorderColor!)),
        ),
      ),
    );
  }
}

登录界面:

import 'package:flutter/material.dart';
import 'package:flutter_parisa/constants.dart';
import 'package:flutter_parisa/views/screens/auth/forgotpassword_screen.dart';
import 'package:flutter_parisa/views/screens/auth/signup_screen.dart';
import 'package:flutter_parisa/views/widgets/custom_elevated_button.dart';
import 'package:flutter_parisa/views/widgets/custom_text_button.dart';
import 'package:flutter_parisa/views/widgets/text_input_field.dart';
import 'package:get/get.dart';

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

  @override
  Widget build(BuildContext context) {
    TextEditingController emailController = TextEditingController();
    TextEditingController passwordController = TextEditingController();
    return Scaffold(
      backgroundColor: authBackgroundColor,
      body: SingleChildScrollView(
        child: Container(
          color: authBackgroundColor,
          child: InkWell(
            highlightColor: Colors.transparent,
            hoverColor: Colors.transparent,
            splashColor: Colors.transparent,
            onTap: () {
              //FocusScope.of(context).requestFocus(FocusNode());
              // FocusScopeNode currentFocus = FocusScope.of(context);
              // if (!currentFocus.hasPrimaryFocus) {
              //   currentFocus.unfocus();
              // }
              //FocusScope.of(context).unfocus();
              //FocusManager.instance.primaryFocus?.unfocus();
            },
            child: SafeArea(
              child: SizedBox(
                height: MediaQuery.of(context).size.height,
                width: MediaQuery.of(context).size.width,
                child: Column(
                  children: [
                    Container(
                      height: MediaQuery.of(context).size.height * 0.3,
                      width: double.infinity,
                      decoration: const BoxDecoration(
                          image: DecorationImage(
                              fit: BoxFit.contain,
                              image:
                                  AssetImage('assets/images/parisa_logo.png'))),
                    ),
                    const SizedBox(
                      height: 40,
                      width: double.infinity,
                      child: Padding(
                        padding: EdgeInsets.only(left: 25),
                        child: Text(
                          'Daxil ol',
                          style: TextStyle(
                              color: Colors.black,
                              fontSize: 28,
                              fontWeight: FontWeight.bold),
                        ),
                      ),
                    ),
                    //here we have to add custom textfield
                    Padding(
                      padding: const EdgeInsets.symmetric(
                          horizontal: 25, vertical: 5),
                      child: Column(
                        children: [
                          TextInputField(
                              hasSuffixIcon: false,
                              labelText: 'Email',
                              controller: emailController,
                              icon: Icons.mail),
                          const SizedBox(
                            height: 15,
                          ),
                          TextInputField(
                              hasSuffixIcon: true,
                              labelText: 'Şifrə',
                              controller: passwordController,
                              icon: Icons.lock,
                              isObscure: true),
                        ],
                      ),
                    ),

                    Container(
                      width: double.infinity,
                      alignment: Alignment.centerRight,
                      padding: const EdgeInsets.only(right: 25, bottom: 10),
                      child: CustomTextButton(
                          textColor: authbuttonColor,
                          buttonText: 'Şifrəni Unutduz?',
                          fontSize: 14,
                          isBold: true,
                          onPressed: () {
                            Get.to(() =>
                                ForgotPassword(emailContent: emailController));
                          }),
                    ),

                    Obx(() {
                      return Padding(
                        padding: const EdgeInsets.symmetric(horizontal: 25),
                        child: authController.isLoading.value
                            ? const Center(
                                child: CircularProgressIndicator(
                                  color: authbuttonColor,
                                ),
                              )
                            : CustomElevatedButton(
                                fontSize: 24,
                                buttonColor: authbuttonColor,
                                buttonName: 'Daxil ol',
                                onPressed: () {
                                  FocusScope.of(context).unfocus();
                                  authController.loginUser(
                                      emailController.text.trim(),
                                      passwordController.text.trim());
                                },
                                textColor: Colors.white,
                              ),
                      );
                    }),
                    SizedBox(
                      height: MediaQuery.of(context).size.height * 0.1,
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          const Text(
                            'Hesabınız yoxdur?',
                            style: TextStyle(
                                color: Colors.grey,
                                fontSize: 14,
                                fontWeight: FontWeight.bold),
                          ),
                          CustomTextButton(
                              textColor: authbuttonColor,
                              buttonText: 'Qeydiyyat',
                              fontSize: 14,
                              isBold: true,
                              onPressed: () =>
                                  Get.to(() => const SignUpScreen())),
                        ],
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

我试过他们所有人分开,但没有帮助。

//FocusScope.of(context).requestFocus(FocusNode());
              // FocusScopeNode currentFocus = FocusScope.of(context);
              // if (!currentFocus.hasPrimaryFocus) {
              //   currentFocus.unfocus();
              // }
              //FocusScope.of(context).unfocus();
              //FocusManager.instance.primaryFocus?.unfocus();
ki0zmccv

ki0zmccv1#

你应该把emailControllerpasswordController作为LoginScreen的属性,而不是build方法的局部属性。

import 'package:flutter/material.dart';
import 'package:flutter_parisa/constants.dart';
import 'package:flutter_parisa/views/screens/auth/forgotpassword_screen.dart';
import 'package:flutter_parisa/views/screens/auth/signup_screen.dart';
import 'package:flutter_parisa/views/widgets/custom_elevated_button.dart';
import 'package:flutter_parisa/views/widgets/custom_text_button.dart';
import 'package:flutter_parisa/views/widgets/text_input_field.dart';
import 'package:get/get.dart';

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

  @override
  State<LoginScreen> createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  TextEditingController emailController = TextEditingController();
  TextEditingController passwordController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: authBackgroundColor,
      body: SingleChildScrollView(
        child: Container(
          color: authBackgroundColor,
          child: InkWell(
            highlightColor: Colors.transparent,
            hoverColor: Colors.transparent,
            splashColor: Colors.transparent,
            onTap: () {
              //FocusScope.of(context).requestFocus(FocusNode());
              // FocusScopeNode currentFocus = FocusScope.of(context);
              // if (!currentFocus.hasPrimaryFocus) {
              //   currentFocus.unfocus();
              // }
              //FocusScope.of(context).unfocus();
              //FocusManager.instance.primaryFocus?.unfocus();
            },
            child: SafeArea(
              child: SizedBox(
                height: MediaQuery.of(context).size.height,
                width: MediaQuery.of(context).size.width,
                child: Column(
                  children: [
                    Container(
                      height: MediaQuery.of(context).size.height * 0.3,
                      width: double.infinity,
                      decoration: const BoxDecoration(
                          image: DecorationImage(
                              fit: BoxFit.contain,
                              image:
                              AssetImage('assets/images/parisa_logo.png'))),
                    ),
                    const SizedBox(
                      height: 40,
                      width: double.infinity,
                      child: Padding(
                        padding: EdgeInsets.only(left: 25),
                        child: Text(
                          'Daxil ol',
                          style: TextStyle(
                              color: Colors.black,
                              fontSize: 28,
                              fontWeight: FontWeight.bold),
                        ),
                      ),
                    ),
                    //here we have to add custom textfield
                    Padding(
                      padding: const EdgeInsets.symmetric(
                          horizontal: 25, vertical: 5),
                      child: Column(
                        children: [
                          TextInputField(
                              hasSuffixIcon: false,
                              labelText: 'Email',
                              controller: emailController,
                              icon: Icons.mail),
                          const SizedBox(
                            height: 15,
                          ),
                          TextInputField(
                              hasSuffixIcon: true,
                              labelText: 'Şifrə',
                              controller: passwordController,
                              icon: Icons.lock,
                              isObscure: true),
                        ],
                      ),
                    ),

                    Container(
                      width: double.infinity,
                      alignment: Alignment.centerRight,
                      padding: const EdgeInsets.only(right: 25, bottom: 10),
                      child: CustomTextButton(
                          textColor: authbuttonColor,
                          buttonText: 'Şifrəni Unutduz?',
                          fontSize: 14,
                          isBold: true,
                          onPressed: () {
                            Get.to(() =>
                                ForgotPassword(emailContent: emailController));
                          }),
                    ),

                    Obx(() {
                      return Padding(
                        padding: const EdgeInsets.symmetric(horizontal: 25),
                        child: authController.isLoading.value
                            ? const Center(
                          child: CircularProgressIndicator(
                            color: authbuttonColor,
                          ),
                        )
                            : CustomElevatedButton(
                          fontSize: 24,
                          buttonColor: authbuttonColor,
                          buttonName: 'Daxil ol',
                          onPressed: () {
                            FocusScope.of(context).unfocus();
                            authController.loginUser(
                                emailController.text.trim(),
                                passwordController.text.trim());
                          },
                          textColor: Colors.white,
                        ),
                      );
                    }),
                    SizedBox(
                      height: MediaQuery.of(context).size.height * 0.1,
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          const Text(
                            'Hesabınız yoxdur?',
                            style: TextStyle(
                                color: Colors.grey,
                                fontSize: 14,
                                fontWeight: FontWeight.bold),
                          ),
                          CustomTextButton(
                              textColor: authbuttonColor,
                              buttonText: 'Qeydiyyat',
                              fontSize: 14,
                              isBold: true,
                              onPressed: () =>
                                  Get.to(() => const SignUpScreen())),
                        ],
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
  
  @override
  void dispose() {
    super.dispose();
    emailController.dispose();
    passwordController.dispose();
  }
}

您还需要在处理LoginScreen之后处理TextEditingController

相关问题