Search code examples
flutterflutter-layoutflutter-animation

Flutter: singleChildScrollView into pageView with vertical scrollDirection


I would like to use the SingleChildScrollView in a pageView with vertical scrolling, the problem is that scrolls conflict and the pageview stops scrolling and only SingleChildScrollView starts scrolling. I needed to move the registration form above the keyboard.

the blue square is to show what I would like to move with the SingleChildScrollView

this is the main page:

    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: PageView(
        controller: loginScreenPageController,
        scrollDirection: Axis.vertical,
        children: [
          const RegisterPage(),
          Column(children: <Widget>[
            ClipRRect(
              child: Container(
                decoration: const BoxDecoration(
                  color: Colors.black,
                ),
                height: MediaQuery.of(context).size.height / 100 * screenHeight,
                width: MediaQuery.of(context).size.width,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text("NON HO UN ACCOUNT",
                        style: GoogleFonts.poppins(
                          color: Colors.white,
                          fontSize: 25,
                        )),
                    const Icon(
                      Icons.arrow_downward,
                      size: 100,
                      color: Colors.white,
                    ),
                    SizedBox(
                      height: downArrowAnimationSize,
                    ),
                  ],
                ),
              ),
            ),
            Expanded(
              child: Container(
                decoration: const BoxDecoration(
                  color: Color.fromARGB(255, 255, 133, 12),
                ),
                height: MediaQuery.of(context).size.height / 2,
                width: MediaQuery.of(context).size.width,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text("HO GIA' UN ACCOUNT",
                        style: GoogleFonts.poppins(
                          color: Colors.white,
                          fontSize: 25,
                        )),
                    const Icon(
                      Icons.arrow_upward,
                      size: 100,
                      color: Colors.white,
                    ),
                    SizedBox(
                      height: downArrowAnimationSize,
                    ),
                  ],
                ),
              ),
            ),
          ]),
          const LoginPage()
        ],
      ),
    );

and this is the form page

  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async => false,
      child: SingleChildScrollView(
        child: Container(
          color: const Color.fromARGB(255, 255, 133, 12),
          child: Column(
            children: [
              SizedBox(height: MediaQuery.of(context).size.height / 100 * 10),
              Image(
                  image:
                      const AssetImage("lib/assets/logo_app_bianco.png"),
                  height: MediaQuery.of(context).size.height / 100 * 20),
              SizedBox(height: MediaQuery.of(context).size.height / 100 * 8),
              Padding(
                padding: EdgeInsets.only(
                    left: MediaQuery.of(context).size.width / 100 * 10,
                    right: MediaQuery.of(context).size.width / 100 * 10),
                child: TextFormField(
                  focusNode: emailFocusNode,
                  onFieldSubmitted: (_) => {passwordFocusNode.requestFocus()},
                  cursorColor: Colors.white,
                  style: GoogleFonts.poppins(color: Colors.white),
                  decoration: const InputDecoration(
                    labelText: "E-Mail",
                    labelStyle: TextStyle(color: Colors.white),
                    focusColor: Colors.white,
                    enabledBorder: UnderlineInputBorder(
                        borderSide: BorderSide(color: Colors.white)),
                    focusedBorder: UnderlineInputBorder(
                      borderSide: BorderSide(color: Colors.white),
                    ),
                  ),
                ),
              ),
              SizedBox(height: MediaQuery.of(context).size.height / 100 * 3),
              Padding(
                padding: EdgeInsets.only(
                    left: MediaQuery.of(context).size.width / 100 * 10,
                    right: MediaQuery.of(context).size.width / 100 * 10),
                child: TextFormField(
                  style: GoogleFonts.poppins(color: Colors.white),
                  obscureText: _isObscure,
                  focusNode: passwordFocusNode,
                  cursorColor: Colors.white,
                  decoration: InputDecoration(
                    labelText: "Password",
                    suffixIcon: IconButton(
                        onPressed: () {
                          
                          setState(() {
                            _isObscure = !_isObscure;
                          });
                        },
                        icon: Icon(
                          _isObscure ? Icons.visibility : Icons.visibility_off,
                          color: Colors.white,
                        )),
                    labelStyle: const TextStyle(color: Colors.white),
                    focusColor: Colors.white,
                    enabledBorder: const UnderlineInputBorder(
                        borderSide: BorderSide(color: Colors.white)),
                    focusedBorder: const UnderlineInputBorder(
                      borderSide: BorderSide(color: Colors.white),
                    ),
                  ),
                ),
              ),
              Padding(
                padding: EdgeInsets.only(
                    top: MediaQuery.of(context).size.height / 100 * 2,
                    right: MediaQuery.of(context).size.width / 100 * 10),
                child: Align(
                  alignment: AlignmentDirectional.centerEnd,
                  child: GestureDetector(
                    onTap: () {},
                    child: Text(
                      "Password Dimenticata?",
                      style:
                          GoogleFonts.poppins(color: Colors.white, fontSize: 10),
                    ),
                  ),
                ),
              ),
              SizedBox(
                height: MediaQuery.of(context).size.height / 100 * 3,
              ),
              SizedBox(
                width: MediaQuery.of(context).size.width / 100 * 80,
                child: ElevatedButton(
                    style: ElevatedButton.styleFrom(primary: Colors.white),
                    onPressed: () {
                      _showMyDialog();
                    },
                    child: Text(
                      "Accedi",
                      style: GoogleFonts.poppins(color: Colors.black),
                    )),
              ),
              SizedBox(
                height: MediaQuery.of(context).size.height / 100 * 5,
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Flexible(
                    child: Padding(
                      padding: EdgeInsets.only(
                          left: MediaQuery.of(context).size.width / 100 * 10),
                      child: Container(
                        color: Colors.white,
                        width: MediaQuery.of(context).size.width / 100 * 15,
                        height: MediaQuery.of(context).size.height / 100 * 0.2,
                      ),
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Text("Oppure Collegati con",
                        style: GoogleFonts.poppins(color: Colors.white)),
                  ),
                  Flexible(
                    child: Padding(
                      padding: EdgeInsets.only(
                          right: MediaQuery.of(context).size.width / 100 * 10),
                      child: Container(
                        color: Colors.white,
                        width: MediaQuery.of(context).size.width / 100 * 15,
                        height: MediaQuery.of(context).size.height / 100 * 0.2,
                      ),
                    ),
                  ),
                ],
              ),
              SizedBox(
                width: MediaQuery.of(context).size.width / 100 * 80,
                child: ElevatedButton(
                    style: ElevatedButton.styleFrom(
                        primary: const Color.fromARGB(255, 66, 103, 178)),
                    onPressed: () => _showMyDialog(),
                    child: Text("Facebook",
                        style: GoogleFonts.poppins(color: Colors.white))),
              )
            ],
          ),
        ),
      ),
    );
  }

Solution

  • to understand if the phone keyboard is open I used this variable that is updated in the build

      Widget build(BuildContext context) {
        bool isKeyboardShowing = MediaQuery.of(context).viewInsets.vertical > 0;
    
        return SafeArea(
          child: Scaffold(
            body: PageView(
              scrollDirection: Axis.vertical,
              children: [
                Text(isKeyboardShowing ? "si" : "no"),
                WillPopScope(
                  onWillPop: () async => false,
                  child: SingleChildScrollView(
                    physics:
                        isKeyboardShowing ? null : NeverScrollableScrollPhysics(),
                    child: Container(
                      color: const Color.fromARGB(255, 255, 133, 12),
                      child: Column(
                        children: [
                          SizedBox(
                              height:
                                  MediaQuery.of(context).size.height / 100 * 10),
                          Image(
                              image: const AssetImage(
                                  "lib/assets/logo_app_bianco.png"),
                              height:
                                  MediaQuery.of(context).size.height / 100 * 20),
                          SizedBox(
                              height: MediaQuery.of(context).size.height / 100 * 8),
                          Padding(
                            padding: EdgeInsets.only(
                                left: MediaQuery.of(context).size.width / 100 * 10,
                                right:
                                    MediaQuery.of(context).size.width / 100 * 10),
                            child: TextFormField(
                              cursorColor: Colors.white,
                              style: GoogleFonts.poppins(color: Colors.white),
                              decoration: const InputDecoration(
                                labelText: "E-Mail",
                                labelStyle: TextStyle(color: Colors.white),
                                focusColor: Colors.white,
                                enabledBorder: UnderlineInputBorder(
                                    borderSide: BorderSide(color: Colors.white)),
                                focusedBorder: UnderlineInputBorder(
                                  borderSide: BorderSide(color: Colors.white),
                                ),
                              ),
                            ),
                          ),
                          SizedBox(
                              height: MediaQuery.of(context).size.height / 100 * 3),
                          Padding(
                            padding: EdgeInsets.only(
                                left: MediaQuery.of(context).size.width / 100 * 10,
                                right:
                                    MediaQuery.of(context).size.width / 100 * 10),
                            child: TextFormField(
                              style: GoogleFonts.poppins(color: Colors.white),
                              cursorColor: Colors.white,
                              decoration: InputDecoration(
                                labelText: "Password",
                                suffixIcon: IconButton(
                                    onPressed: () {
                                      //Funzione anonime per alternare lo stato di visibilità e l'icona vicino alla textfromfield che rappresentà lo stato di visibilità
                                    },
                                    icon: Icon(
                                      Icons.visibility,
                                      color: Colors.white,
                                    )),
                                labelStyle: const TextStyle(color: Colors.white),
                                focusColor: Colors.white,
                                enabledBorder: const UnderlineInputBorder(
                                    borderSide: BorderSide(color: Colors.white)),
                                focusedBorder: const UnderlineInputBorder(
                                  borderSide: BorderSide(color: Colors.white),
                                ),
                              ),
                            ),
                          ),
                          Padding(
                            padding: EdgeInsets.only(
                                top: MediaQuery.of(context).size.height / 100 * 2,
                                right:
                                    MediaQuery.of(context).size.width / 100 * 10),
                            child: Align(
                              alignment: AlignmentDirectional.centerEnd,
                              child: GestureDetector(
                                onTap: () {},
                                child: Text(
                                  "Password Dimenticata?",
                                  style: GoogleFonts.poppins(
                                      color: Colors.white, fontSize: 10),
                                ),
                              ),
                            ),
                          ),
                          SizedBox(
                            height: MediaQuery.of(context).size.height / 100 * 3,
                          ),
                          SizedBox(
                            width: MediaQuery.of(context).size.width / 100 * 80,
                            child: ElevatedButton(
                                style:
                                    ElevatedButton.styleFrom(primary: Colors.white),
                                onPressed: () {},
                                child: Text(
                                  "Accedi",
                                  style: GoogleFonts.poppins(color: Colors.black),
                                )),
                          ),
                          SizedBox(
                            height: MediaQuery.of(context).size.height / 100 * 5,
                          ),
                          Row(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              Flexible(
                                child: Padding(
                                  padding: EdgeInsets.only(
                                      left: MediaQuery.of(context).size.width /
                                          100 *
                                          10),
                                  child: Container(
                                    color: Colors.white,
                                    width: MediaQuery.of(context).size.width /
                                        100 *
                                        15,
                                    height: MediaQuery.of(context).size.height /
                                        100 *
                                        0.2,
                                  ),
                                ),
                              ),
                              Padding(
                                padding: const EdgeInsets.all(8.0),
                                child: Text("Oppure Collegati con",
                                    style:
                                        GoogleFonts.poppins(color: Colors.white)),
                              ),
                              Flexible(
                                child: Padding(
                                  padding: EdgeInsets.only(
                                      right: MediaQuery.of(context).size.width /
                                          100 *
                                          10),
                                  child: Container(
                                    color: Colors.white,
                                    width: MediaQuery.of(context).size.width /
                                        100 *
                                        15,
                                    height: MediaQuery.of(context).size.height /
                                        100 *
                                        0.2,
                                  ),
                                ),
                              ),
                            ],
                          ),
                          SizedBox(
                            width: MediaQuery.of(context).size.width / 100 * 80,
                            child: ElevatedButton(
                                onPressed: () {},
                                style: ElevatedButton.styleFrom(
                                    primary:
                                        const Color.fromARGB(255, 66, 103, 178)),
                                //Funzione che sull'onPressed va a mostrate l'allert box di errore
    
                                child: Text("Facebook",
                                    style:
                                        GoogleFonts.poppins(color: Colors.white))),
                          )
                        ],
                      ),
                    ),
                  ),
                )
              ],
            ),
          ),
        );
    

    The safe area is important for not calculate the space for the sistem ui like notch