Flutter:singleChildScrollView进入页面查看垂直滚动方向



我想在垂直滚动的pageView中使用SingleChildScrollView,问题是滚动冲突,pageView停止滚动,只有SingleChildScrollView开始滚动。我需要把登记表移到键盘上方。

蓝色方块显示我想用SingleChildScrollView移动什么

这是主页:

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()
],
),
);

这是表单页面

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))),
)
],
),
),
),
);
}

解决方案是使SingleChildScrollView仅在键盘打开时可滚动。

为此,请检查底部填充是否大于0。

MediaQuery.of(context).viewInsets.bottom > 0

现在根据它改变SingleChildScrollView的物理特性。

SingleChildScrollView(
physics:  MediaQuery.of(context).viewInsets.bottom > 0 ? null : NeverScrollableScrollPhysics(),
child: ...
)

但这是一种糟糕的做法。ViewInset并非特定于键盘。我建议使用platform_channel直接调用本地API,它会告诉键盘是否可见。

这是一个包裹。flaft_keyboard_visibility

为了了解手机键盘是否打开,我使用了这个在构建中更新的变量

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))),
)
],
),
),
),
)
],
),
),
);

安全区域对于不计算系统ui类缺口的空间很重要

最新更新