in this widget there is call to setState but it gives me error because this is a global widget where i am just passing the required data i also want to pass the state so it can access the setState method how can i achieve that ??
Thanks in Advance....
Widget postWidget(Map<dynamic,dynamic> homeMap,index,context){
return Padding(
padding: EdgeInsets.all(MediaQuery.of(context).size.width * 0.02),
child: Card(
elevation: 4.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Stack(children: <Widget>[
Column(crossAxisAlignment: CrossAxisAlignment.start, children: <
Widget>[
SizedBox(
height: 1,
),
commonProfileData(homeMap, index),
SizedBox(
height: height * 0.005,
),
homeMap['homeModelDataList'][index].description != ""
? Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).size.height * 0.008,
left: MediaQuery.of(context).size.height * 0.025,
right: MediaQuery.of(context).size.height * 0.025),
child: Text(
homeMap['homeModelDataList'][index].description,
textAlign: TextAlign.justify,
),
)
: SizedBox(
height: 0,
),
SizedBox(
height: height * 0.005,
),
homeMap['homeModelDataList'][index].photo != ""
? Container(
margin: EdgeInsets.only(
right: MediaQuery.of(context).size.height * 0.02,
left: MediaQuery.of(context).size.height * 0.02),
child: Container(
clipBehavior: Clip.antiAlias,
height: MediaQuery.of(context).size.height * 0.25,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.red,
),
child: Image.network(
homeMap['homeModelDataList'][index].photo,
fit: BoxFit.fill),
),
)
: SizedBox(
height: 0,
),
//////////////////////////// ICON BUTTON //////////////////////////////////
commonButtons(homeMap, index),
openCommentBox &&
postId ==
homeMap['homeModelDataList'][index].postId.toString()
? Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(children: <Widget>[
Container(
margin: EdgeInsets.only(
left:
MediaQuery.of(context).size.height * 0.015,
),
height: MediaQuery.of(context).size.height * 0.05,
width: MediaQuery.of(context).size.height * 0.25,
child: TextFormField(
minLines: 1,
maxLines: 1,
controller: commentDataController,
focusNode: commentDescriptionFocus,
onFieldSubmitted: (value) {
commentDescriptionFocus.unfocus();
},
decoration: InputDecoration(
hintText: "Add Comment",
hintStyle: TextStyle(
color: isCommentDescriptionEmpty
? Colors.red
: Colors.grey),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(
MediaQuery.of(context).size.width *
0.03)),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: Colors.grey),
borderRadius: BorderRadius.circular(
MediaQuery.of(context).size.width *
0.03))),
),
),
Container(
clipBehavior: Clip.antiAlias,
width: MediaQuery.of(context).size.width * 0.3,
height: MediaQuery.of(context).size.width * 0.1,
margin: EdgeInsets.only(
right:
MediaQuery.of(context).size.height * 0.01,
left: MediaQuery.of(context).size.height *
0.01),
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(10)),
child: RaisedButton(
child: Text("Add Comment",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 12.2)),
onPressed: () async {
if (commentDataController.text
.trim()
.length ==
0) {
isCommentDescriptionEmpty = true;
print("i am here");
} else {
isCommentDescriptionEmpty = false;
//progressDialog.show();
await sendCommentDataToServer(
commentDataController.text);
//progressDialog.hide();
(commentInfoMap["status"] == "Success")
? toast.showToastMessage(
message:
"Comment posted Successfully !")
: toast.showToastMessage(
message: "Comment post Failed !");
}
}),
)
]),
InkWell(
child: Padding(
padding: EdgeInsets.only(
top:
MediaQuery.of(context).size.height * 0.01,
left: MediaQuery.of(context).size.height *
0.018,
bottom: MediaQuery.of(context).size.height *
0.015,
),
child: RichText(
text: TextSpan(
style: TextStyle(
fontSize: 13, color: Colors.black),
children: [
TextSpan(
text: showPostCommentsBox
? "Hide "
: "Show ",
style: TextStyle(
color: Colors.blueAccent,
),
),
TextSpan(
text: "Comments",
style: TextStyle(color: Colors.black),
),
])),
),
onTap: () {
setState(() {
showPostCommentsBox = !showPostCommentsBox;
});
print(
"button pressed state : $showPostCommentsBox");
}),
],
),
)
: SizedBox(
height: 0,
),
showPostCommentsBox &&
postId ==
homeMap['homeModelDataList'][index].postId.toString()
? Container(
// color: Colors.red,
margin: EdgeInsets.only(
right: MediaQuery.of(context).size.height * 0.01,
left: MediaQuery.of(context).size.height * 0.01),
height: height * 0.15,
child: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
physics: BouncingScrollPhysics(),
itemCount: listOfComment.length,
itemBuilder:
(BuildContext context, int position) {
return Padding(
padding: EdgeInsets.only(
right: height * 0.01,
left: height * 0.003,
),
child: Card(
color: Colors.grey[100],
child: ListTile(
title: Text(listOfComment[position][4]
.toString()),
trailing: Text("temp")),
),
);
}),
)
],
),
)
: Container(),
]
)
])),
);
}
in this widget there is call to setState but it gives me error because this is a global widget where i am just passing the required data i also want to pass the state so it can access the setState method how can i achieve that ??
Thanks in Advance....
okay for passing state you have to pass this to the global widget.
For example:
Calling from stateful class:
userDrawer(this);
This is global class:
userDrawer(var state){
return Container(
child: RaisedButton(
child: Text("Click"),
onPressed:(){
state.setState(() {
value = newValue;
}) }
)
pass a function which executes when the button is pressed
userDrawer((){setState(){});
in the global class
userDrawer(Function onPressed){
return FlatButton(onPressed: onPressed, child: Text('Click'));
}
or if you want set a value
userDrawer(Function onPressed){
return FlatButton(onPressed: (){
value = newValue;
onPressed();
}, child: Text('Click'));
}
Related
I used same code in the different place, it is working but in here is not working. I do not understand the situation. Could you help me to solve this?
This is not working
void showFilters(){
final width = MediaQuery.of(context).size.width;
final height = MediaQuery.of(context).size.height;
showCupertinoModalPopup(
context: context,
builder: (BuildContext ctx) => Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: col.mostDarkGrey
),
height: height,
child: Column(
//mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
SizedBox(
width: MediaQuery.of(context).size.width*.8,
child: Container(
decoration: BoxDecoration(
color: col.mostLightPurpleAccent,
borderRadius: BorderRadius.all(Radius.circular(10.0)),
shape: BoxShape.rectangle,
border: Border.all(
color: col.mostDarkPurpleAccent,
width: 3,
),
),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Center(
child: DefaultTextStyle(
style: TextStyle(
color: col.mostDarkPurpleAccent,
fontSize: 18,
fontWeight: FontWeight.w800),
child: Text(
'OPERATÖRLER',
),
),
),
)
),
),
SizedBox(
width: width*.8,
height: height*.45,
child: ListView.builder(
padding: EdgeInsets.only(top: 6),
shrinkWrap: true,
primary: false,
itemCount: MaintenanceApi.maintenanceUsers.length,
itemBuilder: (context, index) {
final employee = MaintenanceApi.maintenanceUsers;
return Padding(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
child: Container(
padding: EdgeInsets.all(4),
decoration: BoxDecoration(
color: col.mostLightPurpleAccent,
borderRadius:
BorderRadius.all(Radius.circular(24.0)),
shape: BoxShape.rectangle,
border: Border.all(
color: col.mostDarkPurpleAccent,
width: 3,
),
),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 16),
child: Text(
'${employee[index].userName}',
style: TextStyle(fontSize: 16),
),
),
FlutterSwitch(
width: width >= 750 ? width * .08 : width * .2,
height: width >= 750 ? height * .04 : height * .05,
activeColor: col.mostDarkPurpleAccent,
toggleSize: width >= 750 ? width * .04 : width * .08,
value: employee[index].isActive!,
borderRadius: height * .04,
onToggle: (bool val) {
setState(() {
// debugPrint("1"+employee[index].isActive.toString());//false
employee[index].isActive = val;
// debugPrint("2"+employee[index].isActive.toString());//true
employees[index].isActive = employee[index].isActive;
// debugPrint("3"+employees[index].isActive.toString());//true
});
},
),
],
),
),
);
})
),
],
)
)
);
}
I do not understand why setState is not working. I use debugPrint and debug the value is changing but it is not showing. Could you help me guys?
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
I am using Stack widget in which I have 2 widgets one is just an image and the other is Singlechildscrollview.
I need to add a button on the footer of the screen and fix this (not moveable). Need to be fixed on screen when the Singlechildscrollview scroll or not I need to fix this button. I am not sure how can I do this because if I out the button in Singlechildscrollview then it will show only when I scroll. I need to fix when I scroll or not button should appear.
Here is my code:
Stack(
children: <Widget>[
Container(
padding: EdgeInsets.only(top: statusBarHeight * 0.8),
height: height * 0.4,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
'assets/images/place2.jpg',
),
fit: BoxFit.fill,
),
),
),
SingleChildScrollView(
child: Padding(
padding: EdgeInsets.only(top: height * 0.3),
child: SingleChildScrollView(
child: ClipRRect(
borderRadius: BorderRadius.only(
topRight: Radius.circular(30),
topLeft: Radius.circular(30)),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(
height: height * 0.05,
),
Container(
width: width,
margin: EdgeInsets.only(left: width * 0.03),
child: Text(
'NYC Food Festival',
textAlign: TextAlign.left,
style: TextStyle(fontSize: 30),
),
),
SizedBox(
height: height * 0.02,
),
Container(
margin: EdgeInsets.only(left: width * 0.03),
child: Row(
children: <Widget>[
Icon(
Icons.calendar_today,
size: 20,
color: Color(0xff808080),
),
SizedBox(width: width * 0.02), // give it width
Column(
children: <Widget>[
Text(
'Sat, May 25, 2020',
style: TextStyle(
color: Color(0xff000000),
fontWeight: FontWeight.bold,
fontSize: 15),
),
],
)
],
),
),
SizedBox(
height: height * 0.02,
),
Container(
margin: EdgeInsets.only(left: width * 0.03),
child: Row(
children: <Widget>[
Icon(
Icons.attach_money,
size: 20,
color: Color(0xff808080),
),
SizedBox(width: width * 0.02), // give it width
Column(
children: <Widget>[
Text(
'25,000 PKR',
style: TextStyle(
color: Color(0xff000000),
fontWeight: FontWeight.bold,
fontSize: 15),
),
],
)
],
),
),
SizedBox(
height: height * 0.02,
),
SizedBox(
height: height * 0.02,
),
Container(
width: width,
margin: EdgeInsets.only(left: width * 0.03),
child: Text(
'Snaps',
textAlign: TextAlign.left,
style: TextStyle(fontSize: 25),
),
),
SizedBox(
height: height * 0.02,
),
Container(
child: Column(
children: <Widget>[
CarouselSlider(
options: CarouselOptions(
autoPlay: true,
aspectRatio: 2.0,
enlargeCenterPage: true,
),
items: imageSliders,
),
],
)),
SizedBox(
height: height * 0.02,
),
Container(
width: width,
margin: EdgeInsets.only(left: width * 0.03),
child: Text(
'About',
textAlign: TextAlign.left,
style: TextStyle(fontSize: 25),
),
),
SizedBox(
height: height * 0.02,
),
Container(
padding: EdgeInsets.only(
right: width * 0.03, left: width * 0.03),
child: DescriptionTextWidget(
text:
"Flutter is Google’s mobile UI framework for crafting high-quality native interfaces on iOS and Android in record time. Flutter works with existing code, is used by developers and organizations around the world, and is free and open source.")
),
SizedBox(
height: height * 0.02,
),
Container(
width: width,
margin: EdgeInsets.only(left: width * 0.03),
child: Text(
'Included',
textAlign: TextAlign.left,
style: TextStyle(fontSize: 25),
),
),
SizedBox(
height: height * 0.02,
),
Included(),
SizedBox(
height: height * 0.01,
),
Included(),
SizedBox(
height: height * 0.01,
),
Included(),
SizedBox(
height: height * 0.01,
),
],
),
),
),
),
),
)
],
)
Here is the output of current view:
This is what I want:
You can achieve this look with relative ease.
Here is an example:
class BottomFadeButton extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
title: Text("Bottom Fade Button"),
),
body: Container(
// height: 500,
color: Colors.amberAccent,
child: Stack(
children: <Widget>[
Container(
child: ListView.builder(
itemCount: 100,
itemBuilder: (context, index) {
return ListTile(
title: Text("Hello "),
);
}),
),
// Bottom Button
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
height: 100,
decoration: BoxDecoration(
// color: Color.fromARGB(110, 255, 255, 255),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
gradient: LinearGradient(
colors: [
Color.fromARGB(30, 255, 255, 255),
Color.fromARGB(255, 255, 255, 255),
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
child: Center(
child: InkWell(
child: Container(
padding: EdgeInsets.symmetric(
horizontal: 100,
vertical: 20,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.blueAccent,
),
child: Text(
"BUY TICKETS",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Colors.white),
),
),
onTap: () {
return print("Tap");
},
),
),
),
),
],
),
),
),
);
}
}
Output:
yes you can add the button in stack and then wrap with align widget with alignment.bottom_center
How can I create something like this with Flutter? I want to fill the grey container with an image.
return SafeArea(
child: Scaffold(
key: _scaffoldKey,
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Stack(
overflow: Overflow.clip,
children: <Widget>[
ClipPath(
clipper: CustomShapeClipper(),
child: Container(
height: MediaQuery.of(context).size.height / 2.6,
width: double.infinity,
color: Colors.blue.shade300,
child: Center(
child: Offstage(),
),
),
),
ClipPath(
clipper: CustomShapeClipper2(),
child: Container(
height: MediaQuery.of(context).size.height / 2.6 - 10,
width: double.infinity,
color: Colors.blue,
child: Center(child: Offstage()),
),
),
Positioned(
left: -90,
top: -90,
child: Container(
height: MediaQuery.of(context).size.height / 3,
width: MediaQuery.of(context).size.width / 1.7,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.blue.shade300,
shape: BoxShape.circle),
child: Container(
height: 60,
width: 60,
decoration: BoxDecoration(
color: Colors.blue, shape: BoxShape.circle),
child: Offstage(),
)),
),
Positioned(
right: -120,
top: -100,
child: Container(
height: MediaQuery.of(context).size.height / 2.5,
width: MediaQuery.of(context).size.width / 1.2,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.blue.shade300,
shape: BoxShape.circle),
child: Container(
height: 60,
width: 60,
decoration: BoxDecoration(
color: Colors.blue, shape: BoxShape.circle),
child: Offstage(),
)),
),
Padding(
padding: const EdgeInsets.only(top: 15.0),
child: Center(
child: Image.asset(
'assets/images/loginimage.png',
width: MediaQuery.of(context).size.width / 1,
height: MediaQuery.of(context).size.height / 5,
colorBlendMode: BlendMode.colorBurn,
)),
)
],
),
Form(
key: _formKey,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 15.0),
child: Container(
width: MediaQuery.of(context).size.width / 1.2,
child: TextFormField(
validator: (String value) {
if (value.isEmpty) {
return "Please enter phone number";
} else if (value.length != 10) {
return "Please enter valid Phone number";
} else {
return null;
}
},
controller: mobile,
keyboardType: TextInputType.phone,
inputFormatters: [
WhitelistingTextInputFormatter.digitsOnly,
LengthLimitingTextInputFormatter(10),
],
textInputAction: TextInputAction.done,
decoration: InputDecoration(
labelText: 'Mobile No.',
contentPadding:
EdgeInsets.fromLTRB(0.0, 15.0, 0.0, 15.0),
hintText: 'Mobile No.',
hintStyle: TextStyle(color: Colors.grey),
prefixIcon: Icon(
Icons.phone,
color: Colors.grey,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0))),
),
),
),
// Padding(
// padding: const EdgeInsets.only(top: 15.0),
// child: Container(
// width: MediaQuery.of(context).size.width / 1.2,
// child: TextFormField(
// validator: (String value) {
// if (value.isEmpty) {
// return "Please enter password";
// } else if (value.length < 6) {
// return "Password must have 6 character";
// } else {
// return null;
// }
// },
// controller: userPassword,
// obscureText: true,
// textInputAction: TextInputAction.done,
// focusNode: fpassword,
// decoration: InputDecoration(
// labelText: 'Password',
// hintText: 'Enter your password',
// contentPadding:
// EdgeInsets.fromLTRB(0.0, 15.0, 0.0, 15.0),
// hintStyle: TextStyle(color: Colors.grey),
// prefixIcon: Icon(
// Icons.security,
// color: Colors.grey,
// ),
// border: OutlineInputBorder(
// borderRadius: BorderRadius.circular(25.0))),
// ),
// ),
// ),
],
),
),
Padding(
padding: EdgeInsets.only(
top: 50,
bottom: 10,
left: MediaQuery.of(context).size.width / 10.0,
right: MediaQuery.of(context).size.width / 10.0),
child: ButtonTheme(
minWidth: MediaQuery.of(context).size.width / 1.2,
height: MediaQuery.of(context).size.height / 12,
child: RaisedButton(
onPressed: () {
if (_formKey.currentState.validate() == true) {
_checkinternet().then((onValue) {
if (onValue == true) {
setState(() {
buttonAction = true;
buttonText = spintool;
});
verifyPhone();
// signInWithEmail();
}
});
}
},
color: Colors.blue,
child: buttonText,
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0))),
),
),
Padding(
padding: EdgeInsets.only(
top: 5,
),
child: ButtonTheme(
minWidth: MediaQuery.of(context).size.width / 1.2,
height: MediaQuery.of(context).size.height / 12,
child: FlatButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChatSignUpPage()));
},
child: Text(
'SignUp',
style: TextStyle(
color: Colors.blue,
),
),
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0))),
),
)
],
),
),
),
);
just add clip class
Chatbox app
I am trying to create a form that has a card and a login button:
I have tried the following code:
import 'package:flutter/material.dart';
class LoginScreenDemo extends StatefulWidget {
#override
_LoginScreenState createState() => new _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreenDemo> {
#override
Widget build(BuildContext context) {
final email = TextFormField(
keyboardType: TextInputType.emailAddress,
autofocus: false,
style: TextStyle(fontSize: 25.0),
decoration: InputDecoration(
labelText: 'Email',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(10.0)),
),
);
final password = TextFormField(
obscureText: true,
autofocus: false,
style: TextStyle(fontSize: 25.0),
decoration: InputDecoration(
labelText: 'Password',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(10.0)),
),
);
final loginButton = Padding(
padding: EdgeInsets.only(top: 10.0),
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
onPressed: () {},
padding: EdgeInsets.symmetric(vertical: 12.0, horizontal: 30.0),
color: Colors.lightBlueAccent,
child: Text(
'LOGIN',
style: TextStyle(
color: Colors.white,
fontSize: 25.0,
fontWeight: FontWeight.bold,
),
),
),
);
final goToSignUpScreen = Padding(
padding: EdgeInsets.only(top: 5.0),
child: FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
onPressed: () {
Navigator.of(context).pushNamed('/signup');
},
child: Text(
"New account? Sign Up",
style: TextStyle(
fontSize: 15.0,
),
),
),
);
final loginCard = Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
color: Colors.white,
elevation: 4.0,
child: ListView(
shrinkWrap: true,
padding:
EdgeInsets.only(top: 100.0, left: 50.0, right: 50.0, bottom: 75.0),
children: <Widget>[
email,
SizedBox(height: 15.0),
password,
],
),
);
final buttonsContainer = Container(
alignment: Alignment.bottomCenter,
padding: EdgeInsets.only(
top: MediaQuery.of(context).orientation == Orientation.landscape
? MediaQuery.of(context).size.height * 0.35
: MediaQuery.of(context).size.height * 0.26,
),
child: Column(
children: <Widget>[
loginButton,
goToSignUpScreen,
],
),
);
final backgroundContainer = Container(
height: MediaQuery.of(context).size.height * 0.40,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/background_golf_course.jpeg'),
fit: BoxFit.cover,
),
),
);
final formContainer = Container(
alignment: Alignment.topCenter,
padding: EdgeInsets.only(
top: MediaQuery.of(context).size.height * 0.25,
right: 20.0,
left: 20.0,
),
child: Container(
width: MediaQuery.of(context).size.width * 0.75,
child: Stack(
children: <Widget>[
loginCard,
buttonsContainer,
],
),
),
);
return SafeArea(
child: Container(
color: Color(0xFFEEEEEE),
child: Stack(
children: <Widget>[
backgroundContainer,
formContainer,
],
),
),
);
}
}
I have placed the card and buttons in a stack widget and tried to place the buttons (as seen in buttonsContainer) above the card by defining their height and padding.
As, can be seen, I need to define different padding for portrait and landscape modes and also, it breaks if the screen size changes.
Is there a neater way to implement this?
Thanks
Container does have a property transform. Usage of this is an alternative to the top padding. Then buttonsContainer is placed relative to loginCard but is overlapping.
Widget buttonsContainer has a translation to the top.
final buttonsContainer = Container(
transform: Matrix4.translationValues(0.0, -34.0, 0.0),
alignment: Alignment.bottomCenter,
child: Column(
children: <Widget>[
loginButton,
goToSignUpScreen,
],
),
);
Widget formContainer then uses Column instead of Stack.
final formContainer = Container(
alignment: Alignment.topCenter,
padding: EdgeInsets.only(
top: MediaQuery.of(context).size.height * 0.25,
right: 20.0,
left: 20.0,
),
child: Container(
width: MediaQuery.of(context).size.width * 0.75,
child: Column(
children: <Widget>[
loginCard,
buttonsContainer,
],
),
),
);