当键盘遮挡表单时应该做什么?

huangapple go评论69阅读模式
英文:

What to do when the keyboard is hiding the form?

问题

I see that you're working on a Flutter project and have shared some Dart code for translation. If you have specific parts of the code you'd like to be translated, please let me know which sections you'd like to translate, and I'll provide translations for those parts.

英文:

I have this design that I'm creating on Flutter:

当键盘遮挡表单时应该做什么?

Here is what I managed to do so far:

当键盘遮挡表单时应该做什么?

I'll provided you my code and I ll explain it and finally I'll try to explain the error that I'm having. First here is my code:

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

  @override
  State<CheckoutPage> createState() => _CheckoutPageState();
}

class _CheckoutPageState extends State<CheckoutPage>
    with TickerProviderStateMixin {
  Map<String, bool> isActive = {
    'Quantity': true,
    'Payment': false,
    'Review': false,
  };
  Map<String, bool> isDone = {
    'Quantity': false,
    'Payment': false,
    'Review': false,
  };
  @override
  Widget build(BuildContext context) {
    order = ModalRoute.of(context)!.settings.arguments as Order;
    final PageController pageViewController = PageController();
    final double height = MediaQuery.of(context).size.height;
    final GlobalKey<FormState> formKey = GlobalKey<FormState>();
    final TextEditingController nameController = TextEditingController();
    final TextEditingController phoneNumberController = TextEditingController();
    final TextEditingController addressController = TextEditingController();

    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: Stack(
        children: [
          Column(
            children: [
              SizedBox(
                height: height * 0.16,
                child: PageViewIndicator(isActive: isActive, isDone: isDone),
              ),
              SizedBox(
                height: height * 0.84,
                child: Padding(
                  padding: const EdgeInsets.symmetric(
                    horizontal: 8,
                    vertical: 18,
                  ),
                  child: PageView(
                    controller: pageViewController,
                    children: [
                      QuantityStepWidget(
                        formKey: formKey,
                        addressController: addressController,
                        nameController: nameController,
                        phoneNumberController: phoneNumberController,
                      ),
                      const PaymentStepWidget(),
                      const ReviewStepWidget(),
                    ],
                  ),
                ),
              ),
            ],
          ),
          const BackButtonWidget(),
        ],
      ),
    );
  }
}

This code is mainly composed of a Scaffold, it's child is a Stack that stacks a back button (BackButton) on tap of a Column. This column has two containers SizedBox; the first one takes 16% of the height of the screen, and the second one takes 84% which makes a total of 100%. Inside the first SizedBox I defined a PageViewIndicator widget which is a Container that holds a Row that holds 3 HeadingPageViewItemWidget like this:


class PageViewIndicator extends StatelessWidget {
  final Map<String, bool> isActive;
  final Map<String, bool> isDone;
  const PageViewIndicator({
    super.key,
    required this.isActive,
    required this.isDone,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        border: Border(
          bottom: BorderSide(color: AppColors.borderColor),
        ),
      ),
      child: Padding(
        padding: const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 20),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
            HeadingPageViewItemWidget(
              number: '1',
              title: 'Quantity',
              isActive: isActive['Quantity']!,
              isDone: isDone['Quantity']!,
            ),
            HeadingPageViewItemWidget(
              number: '2',
              title: 'Payment',
              isActive: isActive['Payment']!,
              isDone: isDone['Payment']!,
            ),
            HeadingPageViewItemWidget(
              number: '3',
              title: 'Review',
              isActive: isActive['Review']!,
              isDone: isDone['Review']!,
            ),
          ],
        ),
      ),
    );
  }
}

The HeadingPageViewItemWidget is another Row that holds a CircleAvatar and a Text widget, like this:


class HeadingPageViewItemWidget extends StatelessWidget {
  final String number;
  final String title;
  final bool isDone;
  final bool isActive;
  const HeadingPageViewItemWidget({
    Key? key,
    required this.number,
    required this.title,
    this.isDone = false,
    this.isActive = false,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: 100,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          CircleAvatar(
            backgroundColor: _getColor(isDone: isDone, isActive: isActive),
            radius: 15,
            child: _getIconOrNumber(isDone),
          ),
          SizedBox(
            width: 60,
            child: Text(title, style: kCaption0),
          ),
        ],
      ),
    );
  }
}

Inside the second SizedBox I have defined a PageView that has 3 children, QuantityStepWidget, PaymentStepWidget and ReviewStepWidget, these last two are just PlaceHolders for the moment. The QuantityStepWidget is defined like this:


class QuantityStepWidget extends StatelessWidget {
  final GlobalKey<FormState> formKey;
  final TextEditingController nameController;
  final TextEditingController phoneNumberController;
  final TextEditingController addressController;
  const QuantityStepWidget(
      {super.key,
      required this.formKey,
      required this.nameController,
      required this.phoneNumberController,
      required this.addressController});

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: SizedBox(
        height: MediaQuery.of(context).size.height * 0.8,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Flexible(
              fit: FlexFit.loose,
              child: SizedBox(
                  height: MediaQuery.of(context).size.height * 0.05,
                  child: const TitleWidget(title: 'Quantity')),
            ),
            Flexible(
              flex: 3,
              fit: FlexFit.loose,
              child: SizedBox(
                height: MediaQuery.of(context).size.height * 0.35,
                width: double.infinity,
                child: MedicationCheckoutQuantityWidget(order: order),
              ),
            ),
            Flexible(
              flex: 3,
              fit: FlexFit.loose,
              child: SizedBox(
                height: MediaQuery.of(context).size.height * 0.4,
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const Text(
                      'Confirm your information',
                      style: kH3TitleStyle,
                    ),
                    const SizedBox(height: 10),
                    Flexible(
                      fit: FlexFit.loose,
                      child: SizedBox(
                        height: 200,
                        child: Form(
                          key: formKey,
                          child: Column(
                            children: [
                              Flexible(
                                flex: 1,
                                fit: FlexFit.loose,
                                child:
                                    TextFormFieldUserInformationsConfirmationWidget(
                                  type: FormType.name,
                                  controller: nameController,
                                ),
                              ),
                              Flexible(
                                flex: 1,
                                fit: FlexFit.loose,
                                child:
                                    TextFormFieldUserInformationsConfirmationWidget(
                                  type: FormType.phoneNumber,
                                  controller: phoneNumberController,
                                ),
                              ),
                              Flexible(
                                flex: 1,
                                fit: FlexFit.loose,
                                child:
                                    TextFormFieldUserInformationsConfirmationWidget(
                                  type: FormType.address,
                                  controller: addressController,
                                ),
                              ),
                            ],
                          ),
                        ),
                      ),
                    ),
                    const SizedBox(height: 20),
                    ButtonWidget(
                        onPressed: () {
                          print('lol');
                          if (formKey.currentState!.validate()) {
                            print(nameController.text);
                            print(phoneNumberController.text);
                            print(addressController.text);
                          }
                        },
                        text: 'Confirm'),
                  ],
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

It consists of a SingleChildScrollView and inside it there is a Column which holds thre Flexible widgets; the first one is the 'Quantity' title, the second one is the two cards of the medication name and quantity, and the third one is the form.

What I want is to make the form go up when the keyboard gets triggered, but it doesn't want to do that, all it does is to show the keyboard and then close it instanly, and it doesn't give me the time to add text, as soon as the keyboard opens it closes

答案1

得分: 1

在你的构建方法之外放置这两个:

final double height = MediaQuery.of(context).size.height;
final GlobalKey<FormState> formKey = GlobalKey<FormState>();

获取更多信息,请访问此线程:StackOverflow答案

英文:

Put These Two outside of your build method:

final double height = MediaQuery.of(context).size.height;
final GlobalKey&lt;FormState&gt; formKey = GlobalKey&lt;FormState&gt;();

For more information, visit this thread: StackOverflow answer

huangapple
  • 本文由 发表于 2023年7月6日 21:14:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76629241.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定