skip to Main Content

I’m unable to show the ModalBottomSheet on top of they keyboard input. Currently the keyboard opens and hides the fields in the back. I have used padding with MediaQuery as seen in other questions but that does not work for me.

Here is the snippet for the ModalBottomSheet:

void _showLoginModal(BuildContext context) {
showModalBottomSheet(
  context: context,
  isScrollControlled: true,
  isDismissible: false,
  enableDrag: false,
  backgroundColor: Colors.transparent,
  builder: (BuildContext context) {
    return WillPopScope(
      onWillPop: () async => false,
      child: FractionallySizedBox(
        heightFactor: 0.4,
        child: Container(
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.only(
              topLeft: Radius.circular(20),
              topRight: Radius.circular(20),
            ),
          ),
          padding: EdgeInsets.only(
              bottom: MediaQuery.of(context).viewInsets.bottom),
          child: LoginPage(),
        ),
      ),
    );
  },
);
}

Now here is the code for the login_page.dart fields:

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: SingleChildScrollView(
        padding: EdgeInsets.all(10),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            SizedBox(height: 20),
            Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: firstNameController,
                    decoration: _buildInputDecoration('First Name'),
                    textCapitalization: TextCapitalization.words,
                  ),
                ),
                SizedBox(width: 20),
                Expanded(
                  child: TextField(
                    controller: lastNameController,
                    decoration: _buildInputDecoration('Last Name'),
                    textCapitalization: TextCapitalization.words,
                  ),
                ),
              ],
            ),
            SizedBox(height: 10),
            TextField(
              controller: phoneNumberController,
              decoration: _buildInputDecoration('10 digit Mobile Number'),
              keyboardType: TextInputType.phone,
              maxLength: 10,
              enabled: !isOtpSent,
            ),
            SizedBox(height: 10),
            if (isOtpSent)
              TextField(
                controller: otpController,
                decoration: _buildInputDecoration('Enter OTP'),
                keyboardType: TextInputType.number,
              ),
            SizedBox(height: 10),
            ElevatedButton.icon(
              onPressed: () {
                if (isOtpSent) {
                  verifyOtp();
                } else {
                  sendOtp();
                }
              },
              style: ButtonStyle(
                backgroundColor:
                    MaterialStateProperty.all<Color>(Color(0xFF0194FE)),
                shape: MaterialStateProperty.all<RoundedRectangleBorder>(
                  RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(10),
                  ),
                ),
              ),
              icon: Icon(Icons.send, color: Colors.white),
              label: Text(
                isOtpSent ? 'Verify OTP' : 'Send OTP',
                style: TextStyle(color: Colors.white),
              ),
            ),
          ],
        ),
      ),
    );
  }

2

Answers


  1. I also did face this issue, follow below step to resolve this issue
    
    step 1: showModalBottomSheet ->
    isScrollControlled: true,
    useSafeArea: true,
    context: context,
    
    step 2: in scaffold ->
    resizeToAvoidBottomInset: true,
    
    step 3: and provide margin to container ->
    margin: EdgeInsetsDirectional.only(
    bottom: MediaQuery.of(context).viewInsets.bottom,
    ),
    
    Login or Signup to reply.
  2. Here’s a working example of a modal bottom sheet that is aware of the soft keyboard. It is set to take a percentage of the screen’s height (70%) but of course it can be adapted to have different sizes relative to viewInsets.bottom which represents the height of the soft keyboard even during animation.

    Also, this example assumes that you want to show scrollable content in the bottom modal sheet.

    enter image description here

    Recipe summary:

    • call showModalBottomSeet with isScrollControlled: true
    • builder returns a SafeArea with a Padding where bottom is at least viewInsets.bottom. You can add an extra value here if you need.
    • The child of the Padding is a SizedBox specifying the desired height of the scroll viewport. You can play with this value if for example you want the bottom sheet to appear as it is lifted when the keyboard opens. Again, in this example the height is computed so that modal’s height stays constant whether the soft keyboard is open or closed.
    import 'package:flutter/material.dart';
    
    class TestPage extends StatelessWidget {
      const TestPage({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: TextButton(
              onPressed: () => showSoftKeyboardAwareBottomModal(context),
              child: Text('Show'),
            ),
          ),
        );
      }
    
      Future<void> showSoftKeyboardAwareBottomModal(BuildContext context) async {
        const heightFactor = 0.7;
    
        await showModalBottomSheet<void>(
          context: context,
          isScrollControlled: true,
          builder: (context) {
            final viewInsets = MediaQuery.of(context).viewInsets;
            final screenSize = MediaQuery.of(context).size;
            final height = screenSize.height * heightFactor - viewInsets.bottom;
    
            return SafeArea(
              child: Padding(
                padding: EdgeInsets.fromLTRB(16, 16, 16, viewInsets.bottom),
                child: SizedBox(
                  height: height,
                  child: SingleChildScrollView(
                    child: Column(
                      children: [
                        Text("Field 1"),
                        TextField(
                          decoration: InputDecoration(
                            border: OutlineInputBorder(),
                            isDense: true,
                          ),
                        ),
                        const SizedBox(height: 16),
                        Container(
                          height: 100,
                          color: Colors.blue.shade100,
                        ),
                        Container(
                          height: 100,
                          color: Colors.white,
                        ),
                        Container(
                          height: 100,
                          color: Colors.blue.shade100,
                        ),
                        Container(
                          height: 100,
                          color: Colors.white,
                        ),
                        Text("Field 2"),
                        TextField(
                          decoration: InputDecoration(
                            border: OutlineInputBorder(),
                            isDense: true,
                          ),
                        ),
                        const SizedBox(height: 16),
                        Container(
                          height: 100,
                          color: Colors.blue.shade100,
                        ),
                        Container(
                          height: 100,
                          color: Colors.white,
                        ),
                        Container(
                          height: 100,
                          color: Colors.blue.shade100,
                        ),
                        Container(
                          height: 100,
                          color: Colors.white,
                        ),
                        Container(
                          height: 100,
                          color: Colors.blue.shade100,
                        ),
                        Text("Field 3"),
                        TextField(
                          decoration: InputDecoration(
                            border: OutlineInputBorder(),
                            isDense: true,
                          ),
                        ),
                        const SizedBox(height: 16),
                      ],
                    ),
                  ),
                ),
              ),
            );
          },
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search