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))),
)
],
),
),
),
);
}
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
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
Related
Hello i have a issue whereby textfield doesn't scroll up when the keyboard appears.
I also added the resizeToAvoidBottomInset: false, and also wrapped the tree with SingleChildScrollView but still same issue.
My code :
return Scaffold(
resizeToAvoidBottomInset: false,
body: SingleChildScrollView(
physics: ScrollPhysics(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: MediaQuery.of(context).size.height / 2.5,
child: Stack(
alignment: Alignment.center,
// fit: StackFit.expand,
overflow: Overflow.visible,
children: [
Positioned(
top: MediaQuery.of(context).size.height * 0.001 * -5,
right: MediaQuery.of(context).size.width / 1000 * -0,
child: Container(
width: MediaQuery.of(context).size.width * 1.1,
height: MediaQuery.of(context).size.height * 0.45,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.fill,
image: AssetImage('assets/slide3.png'),
),
),
),
),
],
),
),
SizedBox(height: MediaQuery.of(context).size.height * 1 / 20),
Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0, horizontal: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Create an Account',
style: GoogleFonts.workSans(
color: Colors.black,
fontSize: 23,
fontWeight: FontWeight.w500),
),
SizedBox(height: 15),
Text(
'Create an account to continue an awesome experience',
style: GoogleFonts.workSans(color: Colors.black),
),
// SizedBox(
// height: 30,
// ),
SizedBox(
height: 16,
),
InputWidget(
height: MediaQuery.of(context).size.height / 13,
controller: _usernameController,
label: 'Username',
hint: 'johndoe',
),
SizedBox(
height: 16,
),
InputWidget(
height: MediaQuery.of(context).size.height / 13,
controller: _emailController,
label: 'Email Address',
hint: 'johndoe#email.com',
),
SizedBox(
height: 16,
),
InputWidget(
height: MediaQuery.of(context).size.height / 13,
controller: _passwordController,
label: 'Password',
isObscure: true,
),
SizedBox(
height: MediaQuery.of(context).size.height / 20,
),
Center(
child: InkWell(
onTap: () {
Get.to(() => BottomBar());
},
child: InkWell(
onTap: signUpUser,
child: Container(
width: double.infinity,
height: MediaQuery.of(context).size.height / 13,
decoration: BoxDecoration(
color: primaryColor,
borderRadius: BorderRadius.circular(5),
),
child: Center(
child: _isLoading
? Center(
child: CircularProgressIndicator(
color: Colors.white,
),
)
: Text(
'Create Account',
style: TextStyle(color: Colors.white),
),
),
),
),
),
),
SizedBox(
height: 20,
),
InkWell(
onTap: () {
Get.to(() => LoginPage());
},
child: RichText(
text: TextSpan(
text: 'Already have an account? ',
style: GoogleFonts.workSans(color: Colors.black),
children: [
TextSpan(
text: 'Login',
style: GoogleFonts.workSans(
color: primaryColor,
fontWeight: FontWeight.bold,
),
),
],
)),
),
],
),
),
],
),
),
);
Result of the code above
Custom widget included
InputWidget
return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text(
widget.label,
style: GoogleFonts.workSans(
color: Colors.black,
fontWeight: FontWeight.w500,
fontSize: widget.fsize ?? 16),
),
SizedBox(height: 3),
Container(
height: widget.height ?? 60,
padding: EdgeInsets.symmetric(horizontal: 15.0),
decoration: BoxDecoration(
border: Border.all(color: primaryColor, width: 1),
borderRadius: BorderRadius.circular(5),
),
child: TextField(
maxLines: widget.maxLine ?? 1,
controller: widget.controller,
decoration: InputDecoration(
border: InputBorder.none,
hintText: widget.hint,
hintStyle: GoogleFonts.workSans(
fontSize: widget.fsize ?? 15,
),
),
obscureText: widget.isObscure,
)),
]);
I would like to make some information of a Profile Page scrollable. For the layout I used a stack as a parent widget and filled it with Positioned Widgets. I filled the Positioned Widget with all positional arguments, which allowed me to scroll it when I placed it in the middle of the screen. It seems like the further down I push the widget, the smaller the area to scroll gets. Until the area kind of disappears.
The last Positioned Widget is the one I want to make scrollable. I also used it with fix numbers, which didn't help.
I am new to programming, so I hopefully could make my problem clear. Thanks in advance for helping me out.
Here is my code:
return Scaffold(
appBar: AppBar(
elevation: 2,
leading: BackButton(onPressed: () {
Navigator.pop(context,
MaterialPageRoute(builder: (context) => eventHomeScreen()));
}),
backgroundColor: Colors.teal,
title: Text('Leute', style: TextStyle(fontSize: 28)),
actions: [
IconButton(
iconSize: 26,
icon: Icon(Icons.chat),
tooltip: 'Chat-Anfrage schicken',
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => chatRequestSentScreen.withUser(user)));
},
)
],
),
body: Stack(
alignment: Alignment.bottomCenter,
clipBehavior: Clip.none,
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width * 1,
height: MediaQuery.of(context).size.height * .35,
decoration: BoxDecoration(
image: DecorationImage(
image: user.getProfilePicture(),
fit: BoxFit.cover,
),
),
),
Positioned(
bottom: -MediaQuery.of(context).size.height * 0.19,
child: Card(
color: Colors.teal.shade50,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(40),
topRight: Radius.circular(40),
)),
elevation: 0,
child: Container(
width: MediaQuery.of(context).size.width * 1,
height: MediaQuery.of(context).size.height * 0.26,
child: Column(
children: [
Text(
user.getFullName(),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 24,
),
),
Text(user.getCurrentAge().toString() + " Jahre",
style: TextStyle(
fontSize: 22,
)),
Text('Zuletzt aktiv: Heute',
style: TextStyle(
color: Colors.grey,
fontSize: 16,
)),
SizedBox(
height: 10,
),
Container(
margin: EdgeInsets.symmetric(horizontal: 20),
padding:
EdgeInsets.symmetric(horizontal: 30, vertical: 5),
child: Text(user.getBio(),
maxLines: 3,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
)),
),
SizedBox(
height: 50,
),
],
),
),
),
),
Positioned(
top: MediaQuery.of(context).size.height * 0.45,
left: 0.0,
right: 0.0,
bottom: -MediaQuery.of(context).size.height * 0.55,
child: Container(
decoration: BoxDecoration(
color: Colors.black87,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(40),
topRight: Radius.circular(40),
)),
width: MediaQuery.of(context).size.width * 1,
height: MediaQuery.of(context).size.height * 0.4,
child:
Container(
margin: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
padding:
EdgeInsets.symmetric(horizontal: 30, vertical: 5),
child: SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
child: Column(
children: SharedScreenFeatures.getSports(
user.getSports()),
),
),
),
),
),
],
),
);
}
}```
You will be fine if you just wrap your container inside a SingleChildScrollView
The child widget inherits constraints from the parent. I added a parent container with height: double.infinity. Also the segment_two container I set a minimum height of 150 otherwise you will give pixel overflow. Be careful with your ratios on sizing.
class TestPositioned extends StatefulWidget {
TestPositioned({Key? key}) : super(key: key);
#override
State<TestPositioned> createState() => _TestPositionedState();
}
class _TestPositionedState extends State<TestPositioned> {
segment_one(BuildContext context)
{
return Container(
width: MediaQuery.of(context).size.width * 1,
height: MediaQuery.of(context).size.height * .35,
decoration: BoxDecoration(
border:Border.all(color:Colors.grey)),
child:FittedBox(
fit:BoxFit.fitHeight,
child:SizedBox(
width:200,
height:200,
child: Image.asset("assets/images/apple.jpg"),
),
),
);
}
segment_two(BuildContext context)
{
return
Positioned(
bottom: -MediaQuery.of(context).size.height * 0.01,
child:
Container(
width: MediaQuery.of(context).size.width * 1,
height: MediaQuery.of(context).size.height * 0.26>150?MediaQuery.of(context).size.height * 0.26:150,
child:Card(
color: Colors.teal.shade50,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(40),
topRight: Radius.circular(40),
)),
elevation: 0,
child: Column(
children: [
Expanded(child:Text("full Name", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 24, ),)),
Expanded(child:Text("current age" + " name",style: TextStyle(fontSize: 22,))),
Expanded(child:Text('abcdefg: hijklmn',style: TextStyle(color: Colors.grey,fontSize: 16,))),
SizedBox(height: 10,),
Container(margin: EdgeInsets.symmetric(horizontal: 10),
padding:EdgeInsets.symmetric(horizontal: 10, vertical: 5),
child:
Expanded(child:Text("bio",maxLines: 3,overflow: TextOverflow.ellipsis,textAlign: TextAlign.center,
style: TextStyle( fontSize: 20,)))
)
,
SizedBox(height: 10,),
],
),
)));
}
#override
Widget build(BuildContext context) {
return Scaffold(appBar: AppBar(title: Text("Stacked Position")),body:
Container(
height: double.infinity,child:Stack(
children: [
segment_one(context),
segment_two(context),
],)));
}
}
I solved it, which took me quite a while but now it is working perfectly for my purposes. I am still using the stack but to push the content down to where it is needed, I used a transparent container. Now the MediaQuery isn't negative anymore. Might not be the perfect answer, but it works.
return Scaffold(
backgroundColor: Colors.teal.shade50,
appBar: AppBar(
elevation: 2,
leading: BackButton(onPressed: () {
Navigator.pop(context,
MaterialPageRoute(builder: (context) => eventHomeScreen()));
}),
backgroundColor: Colors.teal,
title: Text('Leute', style: TextStyle(fontSize: 28)),
actions: [
IconButton(
iconSize: 26,
icon: Icon(Icons.chat),
tooltip: 'Chat-Anfrage schicken',
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => chatRequestSentScreen.withUser(user)));
},
)
],
),
body: Stack(
children: [
Column(children: <Widget>[
Container(
height: MediaQuery.of(context).size.height * .33,
decoration: BoxDecoration(
image: DecorationImage(
image: user.getProfilePicture(),
fit: BoxFit.cover,
),
),
),
]),
Positioned(
top: MediaQuery.of(context).size.height * .27,
child: Container(
decoration: BoxDecoration(
color: Colors.teal.shade50,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(40),
topRight: Radius.circular(40),
)),
width: MediaQuery.of(context).size.width * 1,
child: Column(
children: [
Text(
user.getFullName(),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 24,
),
),
Text(user.getCurrentAge().toString() + " Jahre",
style: TextStyle(
fontSize: 22,
)),
Text('Zuletzt aktiv: Heute',
style: TextStyle(
color: Colors.grey,
fontSize: 16,
)),
],
),
),
),
SingleChildScrollView(
physics: NeverScrollableScrollPhysics(),
child: Column(
children: [
Container(
height: MediaQuery.of(context).size.height * .39,
color: Colors.transparent,
),
Container(
height: MediaQuery.of(context).size.height * .15,
width: MediaQuery.of(context).size.width * 1,
color: Colors.teal.shade50,
padding: EdgeInsets.symmetric(horizontal: 15, vertical: 0),
child: SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
child: Text(
user.getBio(),
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
),
),
),
),
Container(
height: MediaQuery.of(context).size.height * .4,
width: MediaQuery.of(context).size.width *1 ,
decoration: BoxDecoration(
color: Colors.black87,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(40),
topRight: Radius.circular(40),
)),
child: Container(
margin: EdgeInsets.symmetric(horizontal: 20, vertical: 0),
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 20),
child: SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
child: Column(
children:
SharedScreenFeatures.getSports(user.getSports()),
),
),
),
),
],
),
),
],
),
);
This particular screen is composed of a large container (Height of screen) : This container is composed of three parts : A header (fixed container : 10% of screen size), a footer (fixed container : 10% of screen size) and a middle part : container : height of 80% of screen size.
I would like the middle container to be scrollable : so I inserted a LISTVIEW as the child of this container... but it keeps telling me I get a RenderFlex overflowed.... Why doesn't the content of the middle container scroll in between the header and the footer ??
Here is the code :
Scaffold(
backgroundColor: Colors.indigo[900],
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
automaticallyImplyLeading: false,
leading: IconButton(
icon: Icon(Icons.arrow_back_ios_rounded,
color: Colors.red[400], size: 25.0),
onPressed: () {
uD.clearSearchList();
Navigator.pushReplacementNamed(context, StudentHomeScreen.id);
}),
title: Text(
'ETAPE 1 - Découverte',
style: TextStyle(color: Colors.indigo[900], fontSize: 22),
),
actions: [
Container(
margin: const EdgeInsets.only(right: 10),
child: Icon(Icons.memory, size: 45, color: Colors.red[900]),
),
],
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Container(
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
color: Colors.orange[50],
borderRadius: BorderRadius.circular(10.0),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: (MediaQuery.of(context).size.height) * 0.12,
padding: const EdgeInsets.fromLTRB(12, 12, 12, 0),
decoration: BoxDecoration(
color: Colors.orange[100],
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Activité 1',
style: TextStyle(
color: Colors.red[900],
fontSize: 30,
fontWeight: FontWeight.bold),
),
Text(
'Mot n°1/24',
style: TextStyle(
color: Colors.indigo[900],
fontSize: 17.0,
),
),
],
),
SleekCircularSlider(
appearance: CircularSliderAppearance(
infoProperties: InfoProperties(
modifier: (reussite) {
return '${reussite.toInt()} / 5';
},
bottomLabelText: 'Réussite',
bottomLabelStyle:
TextStyle(fontSize: 12, color: Colors.red[900]),
),
size: 90,
customColors: CustomSliderColors(
progressBarColor: Colors.green[900]),
customWidths:
CustomSliderWidths(progressBarWidth: 8)),
min: 0,
max: 5,
initialValue: reussite <= 5 ? reussite : 5,
)
],
),
),
Container(
height: (MediaQuery.of(context).size.height) * 0.8,
child: ListView(
shrinkWrap: true,
children: [
Container(
padding: EdgeInsets.all(12.0),
margin: const EdgeInsets.only(top: 8),
child: Text(
'Ecoute et répète 5 fois le mot en anglais.',
style:
TextStyle(color: Colors.indigo[700], fontSize: 17),
),
),
Container(
margin: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
width: 1.0,
),
borderRadius: BorderRadius.circular(10.0),
),
padding: const EdgeInsets.only(top: 16),
child: Row(
children: [
Container(
height: 200,
child: Image.asset(
'images/avatar_teacher.jpeg',
),
),
Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
child: Text(
'An adult',
style: TextStyle(
color: Colors.red[900],
fontSize: 23,
),
),
),
Container(
margin: const EdgeInsets.only(bottom: 60),
child: Text(
'Un adulte',
style: TextStyle(
color: Colors.indigo[900],
fontSize: 15,
),
),
),
GestureDetector(
child: Container(
height: 45,
margin:
EdgeInsets.fromLTRB(0, 5.0, 0, 15.0),
alignment: Alignment.topRight,
child: Icon(
Icons.volume_up,
color: Colors.indigo[500],
size: 55.0,
),
),
onTap: () {
Tts.speak(
phrase: 'little',
langue: Language.english);
},
),
Container(
alignment: Alignment.topRight,
child: Text('/adult/'),
),
],
),
),
],
),
),
Container(
height: 80,
margin: const EdgeInsets.symmetric(vertical: 20),
alignment: Alignment.center,
child: IconButton(
icon: Icon(
Icons.mic,
color: Colors.red[900],
size: 50,
),
onPressed: () async {
uD.checkSpokenWords('adult', reussite);
}),
),
Container(
alignment: Alignment.center,
child: Text(
'Clique sur le micro et répète le mot',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black45,
fontSize: 15.0,
),
),
),
SizedBox(
height: 50.0,
),
Container(
width: double.infinity,
alignment: Alignment.centerLeft,
margin: const EdgeInsets.only(top: 12),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
width: 1.0,
),
borderRadius: BorderRadius.circular(10.0),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Text('Voici ce que j\'ai compris : '),
Text(uD.spokenWords),
],
),
),
),
],
),
),
Container(
height: (MediaQuery.of(context).size.height) * 0.08,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.orange[100],
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10),
),
),
margin: const EdgeInsets.only(top: 8),
child: RoundedProgressBar(
milliseconds: 1000,
childLeft: Text(
'Réussite de l\'activité : ',
style: TextStyle(color: Colors.indigo[900]),
),
childRight: Text("$reussite%",
style: TextStyle(color: Colors.red[900])),
percent: reussite,
theme: RoundedProgressBarTheme.blue),
),
],
),
),
),
);
You should replace the middle Container (the one with the 0.8 * MediaQuery height) with Expanded so it will take the available space between the 2 other Containers.
Can you help me to implement the scroll View inside the Stack After the keyboard has rendered for the TextField
I have put more textFields inside the column widget,But when the keyboard has been rendered it is covering the text Field so how to put the screen under scrolling after keyboard has rendered
As this is stack singleChildScrollView is not funtioning
Widget build(BuildContext context) {
return SafeArea(
child:Stack(children: <Widget>[
Align(
alignment: Alignment.topCenter,
child: Container(
child: Padding(
padding: EdgeInsets.only(top: 20.0),
child: Center(
child: Image.asset(
"img/xyzlogo.jpg",
width: Short.w * 0.4,
),
),
),
width: Short.w,
height: MediaQuery.of(context).size.height * 0.20,
color: Colors.blue[800],
),
),
Align(
alignment: Alignment.bottomLeft,
child: Container(
height: Short.h * 0.82,
width: Short.w,
color: Colors.white,
child:new LayoutBuilder(
builder:
(BuildContext contex, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints:
BoxConstraints(
maxHeight: viewportConstraints.maxHeight,
// minHeight:viewportConstraints.minHeight
),
child: Column(children: [Form(
key: _formKey,
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(
child: Padding(
padding: EdgeInsets.only(
top: 18,left: Short.w * 0.03,
),
child: Material(
shape: Border(
left: BorderSide(
width: 5.0, color: Colors.blue[800]),
bottom: BorderSide(
width: 1.8, color: Colors.blue[800]),
),
color: Colors.white,
child: Padding(
padding: EdgeInsets.only(left: 9.0),
child: TextFormField(
decoration: InputDecoration(
labelStyle: TextStyle(
color: Colors.grey,
fontSize: Short.h * 0.02),
labelText: ' Email/Phone',
hintText: " Enter your email /Phone",
hintStyle: TextStyle(
color: Colors.grey,
fontSize: Short.h * 0.02),
// border: OutlineInputBorder(
// borderRadius: BorderRadius.circular(
// Short.h * 2.5)),
),
controller: email,
keyboardType:
TextInputType.emailAddress,
),
),
),
),
),
Flexible(
child: Padding(
padding: EdgeInsets.only(
top: 18,
left: Short.w * 0.03,
right: Short.w * 0.02),
child: Material(
shape: Border(
left: BorderSide(
width: 5.0, color: Colors.blue[800]),
bottom: BorderSide(
width: 1.8, color: Colors.blue[800]),
),
color: Colors.white,
child: Padding(
padding: EdgeInsets.only(left: 9.0),
child: TextFormField(
decoration: InputDecoration(
labelStyle: TextStyle(
color: Colors.grey,
fontSize: Short.h * 0.02),
labelText: ' Password',
hintText: " Enter your Password",
hintStyle: TextStyle(
color: Colors.grey,
fontSize: Short.h * 0.02),
),
controller: pwd,
keyboardType:
TextInputType.visiblePassword,
// validator: pwdValidator,
),
),
),
),
),
],
), ]), ), ); },) ), ),
After rendering the keyboard, you cannot use the SingleChildScrollView widget inside the stack or column because the SinglechildScrollView is used when you have a single box that is entirely visible unlike the rendering of any other widget on it. This can be solved by using the stack widget inside the SingleChildSrollView widget into the scaffold through which the entire stack could be scrolled.
Scaffold(
body: SingleChildScrollView(
child: Stack(children: <Widget>[
Align(
alignment: Alignment.topCenter,
child: Container(
child: Padding(
padding: EdgeInsets.only(top: 20.0),
child: Center(
child: Image.asset(
"img/xyzlogo.jpg",
width: Short.w * 0.4,
),
),
),
width: Short.w,
height: MediaQuery.of(context).size.height * 0.20,
color: Colors.blue[800],
),
),
Align(
alignment: Alignment.bottomLeft,
child: Container(
margin: EdgeInsets.only(top: 150),
height: Short.h * 0.75,
width: Short.w,
color: Colors.white,
child: new Column(children: [
Form(
key: _formKey,
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(
child: Padding(
padding: EdgeInsets.only(
top: 18,
left: Short.w * 0.03,
),
child: Material(
shape: Border(
left: BorderSide(
width: 5.0, color: Colors.blue[800]),
bottom: BorderSide(
width: 1.8, color: Colors.blue[800]),
),
color: Colors.white,
child: Padding(
padding: EdgeInsets.only(left: 9.0),
child: TextFormField(
decoration: InputDecoration(
labelStyle: TextStyle(
color: Colors.grey,
fontSize: Short.h * 0.02),
labelText: ' Email/Phone',
hintText: " Enter your email /Phone",
hintStyle: TextStyle(
color: Colors.grey,
fontSize: Short.h * 0.02),
),
controller: email,
keyboardType: TextInputType.emailAddress,
),
),
),
),
),
Flexible(
child: Padding(
padding: EdgeInsets.only(
top: 18,
left: Short.w * 0.03,
right: Short.w * 0.02),
child: Material(
shape: Border(
left: BorderSide(
width: 5.0, color: Colors.blue[800]),
bottom: BorderSide(
width: 1.8, color: Colors.blue[800]),
),
color: Colors.white,
child: Padding(
padding: EdgeInsets.only(left: 9.0),
child: TextFormField(
decoration: InputDecoration(
labelStyle: TextStyle(
color: Colors.grey,
fontSize: Short.h * 0.02),
labelText: ' Password',
hintText: " Enter your Password",
hintStyle: TextStyle(
color: Colors.grey,
fontSize: Short.h * 0.02),
),
controller: pwd,
keyboardType: TextInputType.visiblePassword,
),
),
),
),
),
],
),
],
),
),
]),
),
),
]),
),
));
After that, inside the container use margin which provides space outside the border that makes your screen look good.
Description I am creating the login screen in which I have used the Stack widget, Currently, everything works fine but only one issue of the shrinking the view. When I use the resizeToAvoidBottomPadding: false inside the Scaffold then screen shrinking disappear but another problem arise that whole screen scroll not working, please check below lines of code
class _LoginScreen extends State<LoginScreen> {
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
resizeToAvoidBottomPadding: false,
body: Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
child: Column(
children: <Widget>[
Expanded(
flex: 4,
child: Column(
children: <Widget>[
Expanded(
flex: 9,
child: Container(
color: Colors.blue,
child: Align(
alignment: Alignment.centerLeft,
child: RotatedBox(
quarterTurns: 3,
child: Container(
child: Padding(
padding: EdgeInsets.all(5),
child: Text(
"Login !!",
style: TextStyle(
fontSize: 30.0,
color: Colors.white),
),
),
),
),
)),
),
Expanded(
flex: 1,
child: Container(
color: Colors.white,
),
)
],
)),
Expanded(
flex: 6,
child: Container(
color: Colors.white,
),
)
],
),
),
Padding(
padding: EdgeInsets.only(left: 20.0, right: 20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Image(
image: new AssetImage("images/logo.png"),
color: null,
height: 100.0,
width: 100.0,
fit: BoxFit.scaleDown,
alignment: Alignment.center,
),
SizedBox(
height: 20.0,
),
TextField(
keyboardType: TextInputType.number,
inputFormatters: [
LengthLimitingTextInputFormatter(10),
],
decoration: new InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.blue, width: 2.0),
),
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.grey, width: 2.0),
),
hintText: "Please enter mobile number")),
SizedBox(
height: 10.0,
),
TextField(
obscureText: true,
inputFormatters: [
LengthLimitingTextInputFormatter(16),
],
keyboardType: TextInputType.visiblePassword,
decoration: new InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.blue, width: 2.0),
),
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.grey, width: 2.0),
),
hintText: "Password")),
SizedBox(
height: 3.0,
),
Align(
alignment: Alignment.topRight,
child: Text(
"Forgot Password?",
style: TextStyle(fontSize: 12.0),
)),
SizedBox(
height: 3.0,
),
SizedBox(
height: 10.0,
),
RaisedButton(
onPressed: () {},
color: Colors.blue,
child: const Text(
'Login',
style: TextStyle(fontSize: 15.0, color: Colors.black45),
),
)
],
),
),
],
));
}
}
From Above code, I am getting the following screen
I have used the ListView and SingleChildScrollView but it not working properly, please check my code with SingleChildScrollView, which i have tried
class _LoginScreen extends State<LoginScreen> {
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
resizeToAvoidBottomPadding: false,
body: SingleChildScrollView(
child: IntrinsicHeight(
child: Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
child: Column(
children: <Widget>[
Expanded(
flex: 4,
child: Column(
children: <Widget>[
Expanded(
flex: 9,
child: Container(
color: Colors.blue,
child: Align(
alignment: Alignment.centerLeft,
child: RotatedBox(
quarterTurns: 3,
child: Container(
child: Padding(
padding: EdgeInsets.all(5),
child: Text(
"Login !!",
style: TextStyle(
fontSize: 30.0,
color: Colors.white),
),
),
),
),
)),
),
Expanded(
flex: 1,
child: Container(
color: Colors.white,
),
)
],
)),
Expanded(
flex: 6,
child: Container(
color: Colors.white,
),
)
],
),
),
Padding(
padding: EdgeInsets.only(left: 20.0, right: 20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Image(
image: new AssetImage("images/logo.png"),
color: null,
height: 100.0,
width: 100.0,
fit: BoxFit.scaleDown,
alignment: Alignment.center,
),
SizedBox(
height: 20.0,
),
TextField(
keyboardType: TextInputType.number,
inputFormatters: [
LengthLimitingTextInputFormatter(10),
],
decoration: new InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.blue, width: 2.0),
),
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.grey, width: 2.0),
),
hintText: "Please enter mobile number")),
SizedBox(
height: 10.0,
),
TextField(
obscureText: true,
inputFormatters: [
LengthLimitingTextInputFormatter(16),
],
keyboardType: TextInputType.visiblePassword,
decoration: new InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.blue, width: 2.0),
),
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.grey, width: 2.0),
),
hintText: "Password")),
SizedBox(
height: 3.0,
),
Align(
alignment: Alignment.topRight,
child: Text(
"Forgot Password?",
style: TextStyle(fontSize: 12.0),
)),
SizedBox(
height: 3.0,
),
SizedBox(
height: 10.0,
),
RaisedButton(
onPressed: () {},
color: Colors.blue,
child: const Text(
'Login',
style: TextStyle(fontSize: 15.0, color: Colors.black45),
),
)
],
),
),
],
)),
));
}
}
And From the above code getting this result by using the SingleChildScrollView
Problem:- I want to scroll the whole screen when the keyboard appears, I have used all the Listview and SingleChildScrollView but not getting the solution, please help me on it. Thanks
The problem is you're using Expanded widgets, you see expanded widgets are flexible in nature they will consume and shrink according to the available space. If you don't want that you need to specify a height.
https://i.imgur.com/wVgAUlN.mp4
class StacScroll extends StatefulWidget {
StacScroll({Key key}) : super(key: key);
#override
_StacScrollState createState() => _StacScrollState();
}
class _StacScrollState extends State<StacScroll> {
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: true,
body: Container(
height: double.infinity,
width: double.infinity,
// margin:
// EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: SingleChildScrollView(
child: Stack(
children: <Widget>[
Container(
color: Colors.blue,
height: MediaQuery.of(context).size.height * 0.3,
width: MediaQuery.of(context).size.width,
child: RotatedBox(
quarterTurns: 3,
child: Container(
child: Padding(
padding: EdgeInsets.all(5),
child: Text(
"Login !!",
style:
TextStyle(fontSize: 30.0, color: Colors.white),
),
),
)),
),
Container(
margin: EdgeInsets.only(
top: MediaQuery.of(context).size.height * 0.3),
child: Padding(
padding: EdgeInsets.only(left: 20.0, right: 20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Image(
image: new AssetImage("images/logo.png"),
color: null,
height: 100.0,
width: 100.0,
fit: BoxFit.scaleDown,
alignment: Alignment.center,
),
SizedBox(
height: 20.0,
),
TextField(
keyboardType: TextInputType.number,
decoration: new InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.blue, width: 2.0),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.grey, width: 2.0),
),
hintText: "Please enter mobile number")),
SizedBox(
height: 10.0,
),
TextField(
obscureText: true,
keyboardType: TextInputType.visiblePassword,
decoration: new InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.blue, width: 2.0),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.grey, width: 2.0),
),
hintText: "Password")),
SizedBox(
height: 3.0,
),
Align(
alignment: Alignment.topRight,
child: Text(
"Forgot Password?",
style: TextStyle(fontSize: 12.0),
)),
SizedBox(
height: 3.0,
),
SizedBox(
height: 10.0,
),
RaisedButton(
onPressed: () {},
color: Colors.blue,
child: const Text(
'Login',
style: TextStyle(
fontSize: 15.0, color: Colors.black45),
),
)
],
),
),
),
],
),
),
));
}
}
Thanks #Nadeem by which problem has resolved
Whenever we want to scroll the full screen when keyboard appear then we should not use the Expand widget for it.I was also doing the same mistake, for the other user i have modified the code for full scroll when keyboard appear, I have used the MediaQuery for it,Please check my below code of it.
import 'package:flutter/material.dart';
class LoginScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _LoginScreen();
}
}
class _LoginScreen extends State<LoginScreen> {
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("Login"),
),
body: Container(
height: double.infinity,
width: double.infinity,
child: SingleChildScrollView(
child: Stack(
children: <Widget>[
Container(
color: Colors.blue,
height: MediaQuery.of(context).size.height * 0.3,
),
Container(
color: Colors.white,
height: MediaQuery.of(context).size.height * 0.59,
padding: EdgeInsets.all(10.0),
margin: EdgeInsets.only(
top: MediaQuery.of(context).size.height * 0.3),
child: Container(
margin: EdgeInsets.only(top: 70.0),
child: Column(
children: <Widget>[
TextFormField(
decoration: InputDecoration(
labelText: 'Enter your username')),
TextFormField(
decoration: InputDecoration(labelText: 'Password')),
SizedBox(
height: 20.0,
),
RaisedButton(
color: Colors.yellow,
child: Text("Submit",
style: TextStyle(color: Colors.blue)),
onPressed: () {},
)
],
),
)),
Center(
child: Card(
color: Colors.yellow,
elevation: 8,
margin: EdgeInsets.only(
top: MediaQuery.of(context).size.height * .25),
child: Container(
child: Center(
child: Text(
"Radhe",
style: TextStyle(color: Colors.blue, fontSize: 20.0),
)),
height: MediaQuery.of(context).size.height * .1,
width: MediaQuery.of(context).size.width * .3,
),
),
)
],
),
),
),
);
}
}
Please check the output of it.