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_palestre_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: () {
//Funzione anonime per alternare lo stato di visibilità e l'icona vicino alla textfromfield che rappresentà lo stato di visibilità
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)),
//Funzione che sull'onPressed va a mostrate l'allert box di errore
onPressed: () => _showMyDialog(),
child: Text("Facebook",
style: GoogleFonts.poppins(color: Colors.white))),
)
],
),
),
),
);
}
CodePudding user response:
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_palestre_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
CodePudding user response:
A solution would be to make the SingleChildScrollView
only scrollable if the keyboard is open.
For that, check if bottom padding is larger than 0.
MediaQuery.of(context).viewInsets.bottom > 0
Now change the physics of the SingleChildScrollView
depending on it.
SingleChildScrollView(
physics: MediaQuery.of(context).viewInsets.bottom > 0 ? null : NeverScrollableScrollPhysics(),
child: ...
)
But that's a bad practice. ViewInset is not specific to keyboard. I'd suggest to use platform_channel to directly call native API that tells if the keyboard is visible or not.
Here is a package for that. flutter_keyboard_visibility