How to handle Login Screen scroll in Flutter? - flutter

I am new to Flutter where I am trying to create a Login Screen, but I am not able to handle proper scroll of an field. Below is the code I had written.The main problem is that the text form field go above image which should not happen when it push up.
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Image.asset(
"assets/ic_login_stack.png",
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
fit: BoxFit.cover,
),
Scaffold(
key: scaffoldKey,
backgroundColor: Colors.transparent,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
),
body: Center(
child: SingleChildScrollView(
padding: EdgeInsets.only(left: 24.0, right: 24.0),
child: Column(
children: <Widget>[
SizedBox(height: 55.0),
Form(key: formKey, child: _getUIForm()),
SizedBox(
width: double.infinity,
height: 50,
child: GestureDetector(
child: RaisedButton(
child: Text(AppLocalizations.of(context).buttonText,
style: TextStyle(
color: Colors.white, fontSize: 18.0)),
elevation: 5.0,
color: Color(0xffE9446A),
//onPressed: _submit,
onPressed: () => {
/*Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CompanyWall()
)
)*/
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => CompanyWall()),
(r) => false)
},
),
)),
SizedBox(height: 20.0),
GestureDetector(
onTap: () =>
Navigator.of(context).pushNamed(ResetPassword.tag),
child: Text(
AppLocalizations.of(context).forgotPasswordText,
style: TextStyle(
decoration: TextDecoration.underline,
color: Colors.grey[800],
fontSize: 16.0),
),
),
SizedBox(height: 30.0),
GestureDetector(
onTap: () =>
Navigator.of(context).pushNamed(SignUpScreen.tag),
child: Text(AppLocalizations.of(context).signUpFreeText,
style: TextStyle(
color: Color(0xffE9446A),
fontSize: 18.0,
fontWeight: FontWeight.bold)),
),
],
),
),
),
)
],
);
}
_getUIForm() {
Multiple Text Form Feild
}
And below are the out put I obtained while running code.How should I handle scroll that textformfeild should remain below the logo.

You are using a Stack with 2 children - the Image and the scrolling content. The image is outside the scrolling content so it will not change its position as you scroll.
If you want the image to scroll along with the content, change your layout so that your Stack is within the SingleChildScrollView. It should end up roughly like so:
Scaffold -> SingleChildScrollView -> Stack -> [Image, Column]

In the scaffold add this
return Scaffold(
resizeToAvoidBottomPadding: false, // <-- add this
);

Related

showModalBottomSheet adaptive size Flutter

I have the next problem, having a little number of children allows users to scroll even though there is an empty space
Future<void> buildScrollableSheet([Widget? header]) {
return showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) => makeDismissible(
child: DraggableScrollableSheet(
initialChildSize: 0.3,
maxChildSize: 0.9, // this one should be adaptive
builder: (_, controller) => Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(
top: Radius.circular(25),
),
),
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
// crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Padding(
padding: EdgeInsets.all(24),
child: Center(
child: Text(
'My header',
style: TextStyle(
color: Color(0xff757575),
fontSize: 14,
),
),
),
),
Flexible(
child: Material(
color: Colors.white,
child: ListView(
shrinkWrap: true,
controller: controller,
children: [
SimpleHeader(
title: 'title',
text: 'text',
),
SimpleHeader(
title: 'title',
text: 'text',
),
SimpleHeader(
title: 'title',
text: 'text',
),
],
),
),
),
],
),
),
),
),
);
}
Here you can see maxChildSize is being set as 0.9 which is fine with a lot of children inside ListView, but in this case, there are only 3 elements and I want to prevent scrolling to full size, also it would be great to set initialChildSize to childs size, so if I have a huge list of items it would always open full.
Thank you!

How to make ExpansionTile scrollable when end of screen is reached?

In the project I'm currently working on, I have a Scaffold that contains a SinlgeChildScrollView. Within this SingleChildScrollView the actual content is being displayed, allowing for the possibility of scrolling if the content leaves the screen.
While this makes sense for ~90% of my screens, however I have one screen in which I display 2 ExpansionTiles. Both of these could possibly contain many entries, making them very big when expanded.
The problem right now is, that I'd like the ExpansionTile to stop expanding at latest when it reaches the bottom of the screen and make the content within the ExpansionTile (i.e. the ListTiles) scrollable.
Currently the screen looks like this when there are too many entries:
As you can clearly see, the ExpansionTile leaves the screen, forcing the user to scroll the actual screen, which would lead to the headers of both ExpansionTiles disappearing out of the screen given there are enought entries in the list. Even removing the SingleChildScrollView from the Scaffold doesn't solve the problem but just leads to a RenderOverflow.
The code used for generating the Scaffold and its contents is the following:
class MembershipScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() => _MembershipScreenState();
}
class _MembershipScreenState extends State<MembershipScreen> {
String _fontFamily = 'OpenSans';
Widget _buildMyClubs() {
return Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Color(0xFFD2D2D2),
width: 2
),
borderRadius: BorderRadius.circular(25)
),
child: Theme(
data: ThemeData().copyWith(dividerColor: Colors.transparent),
child: ExpansionTile(
title: Text("My Clubs"),
trailing: Icon(Icons.add),
children: getSearchResults(),
),
)
);
}
Widget _buildAllClubs() {
return Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Color(0xFFD2D2D2),
width: 2
),
borderRadius: BorderRadius.circular(25)
),
child: Theme(
data: ThemeData().copyWith(dividerColor: Colors.transparent),
child: SingleChildScrollView(
child: ExpansionTile(
title: Text("All Clubs"),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.add)
],
),
children: getSearchResults(),
),
)
)
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
extendBody: true,
body: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.light,
child: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
decoration: BoxDecoration(
gradient: kGradient //just some gradient
),
),
Center(
child: Container(
height: double.infinity,
constraints: BoxConstraints(maxWidth: 500),
child: SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
padding: EdgeInsets.symmetric(horizontal: 40.0, vertical: 20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Clubs',
style: TextStyle(
fontSize: 30.0,
color: Colors.white,
fontFamily: _fontFamily,
fontWeight: FontWeight.bold),
),
SizedBox(
height: 20,
),
_buildMyClubs(),
SizedBox(height: 20,),
_buildAllClubs()
],
),
),
),
),
],
),
)
),
);
}
List<Widget> getSearchResults() {
return [
ListTile(
title: Text("Test1"),
onTap: () => print("Test1"),
),
ListTile(
title: Text("Test2"),
onTap: () => print("Test2"),
), //etc..
];
}
}
I hope I didn't break the code by removing irrelevant parts of it in order to reduce size before posting it here. Hopefully, there is someone who knows how to achieve what I intend to do here and who can help me with the solution for this.
EDIT
As it might not be easy to understand what I try to achieve, I tried to come up with a visualization for the desired behaviour:
Thereby, the items that are surrounded with dashed lines are contained with the list, however cannot be displayed because they would exceed the viewport's boundaries. Hence the ExpansionTile that is containing the item needs to provide a scroll bar for the user to scroll down WITHIN the list. Thereby, both ExpansionTiles are visible at all times.
Try below code hope its help to you. Add your ExpansionTile() Widget inside Column() and Column() wrap in SingleChildScrollView()
Refer SingleChildScrollView here
Refer Column here
You can refer my answer here also for ExpansionPanel
Refer Lists here
Refer ListView.builder() here
your List:
List<Widget> getSearchResults = [
ListTile(
title: Text("Test1"),
onTap: () => print("Test1"),
),
ListTile(
title: Text("Test2"),
onTap: () => print("Test2"),
), //etc..
];
Your Widget using ListView.builder():
SingleChildScrollView(
padding: EdgeInsets.all(20),
child: Column(
children: [
Card(
child: ExpansionTile(
title: Text(
"My Clubs",
),
trailing: Icon(
Icons.add,
),
children: [
ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Column(
children: getSearchResults,
);
},
itemCount: getSearchResults.length, // try 50 length just testing
),
],
),
),
],
),
),
Your Simple Widget :
SingleChildScrollView(
padding: EdgeInsets.all(20),
child: Column(
children: [
Card(
child: ExpansionTile(
title: Text(
"My Clubs",
),
trailing: Icon(
Icons.add,
),
children:getSearchResults
),
),
],
),
),
Your result screen ->

flutter: how to customize cuperinoAlertDialog style?

I'm working with flutter. I want to make a CupertinoAlertDialog(iOS style is required). My problem is UI designers require the background color of the alert dialog should be #F0F0F0. But I can only adjust its theme into dark or light(e.g. following picture). The code I completed is placed below.
showCupertinoDialog(
context: context,
builder: (BuildContext context){
return Theme(
data: ThemeData.dark(),
child: CupertinoAlertDialog(
title: Text('Title'),
content: Text('Some message here'),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('Cancle'),
),
FlatButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('OK'),
),
],
),
);
}
);
Is that possible? Thanks for any advice.
If I recall correctly, the background color for CupertinoAlertDialog is hardcoded. However, you can create a custom dialog that can change the background color of it as well as the functions of the buttons.
You need to create a type Dialog for the showDialog function instead of showCupertinoDialog:
Dialog customDialog = Dialog(
backgroundColor: Color(0xfff0f0f0), // your color
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)), // change 40 to your desired radius
child: CustomAlertDialog(),
);
I also created a stateless widget called CustomAlertDialog, but if you don't want to, you can replace the CustomAlertDialog() with its content.
class CustomAlertDialog extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
height: 150,
child: Column(
children: [
Expanded(
flex: 2,
child: Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(color: Colors.grey, width: 1),
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
child: Center(
child: Text(
"Title",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 20),
),
),
),
Container(
child: Center(
child: Text("Some message here"),
),
),
],
),
),
),
Expanded(
flex: 1,
child: Row(
children: [
Expanded(
flex: 1,
child: GestureDetector(
child: Container(
decoration: BoxDecoration(
border: Border(
right: BorderSide(color: Colors.grey, width: 1),
),
),
child: Center(
child: Text("Cancel"),
),
),
onTap: () {
Navigator.of(context).pop(); // replace with your own functions
},
),
),
Expanded(
flex: 1,
child: GestureDetector(
child: Container(
child: Center(
child: Text("OK"),
),
),
onTap: () {
Navigator.of(context).pop(); // replace with your own functions
},
),
),
],
),
),
],
),
);
}
}
Lastly, replace your whole showCupertinoDialog with this showDialog function:
showDialog(
barrierDismissible: true, // set false if you dont want the dialog to be dismissed when user taps anywhere [![enter image description here][1]][1]outside of the alert
context: context,
builder: (context) {
return customDialog;
},
);
Result: https://i.stack.imgur.com/cV13A.png

How to remove the background when clicking on the text of a link?

I have a Text widget with a link to another screen, when clicked, the background appears. How do I remove the background when clicked?
More in the photo
Align(
alignment: AlignmentDirectional.topStart,
child: FlatButton(
//color: Colors.redAccent,
onPressed: () => Navigator.of(context).push(
new MaterialPageRoute(builder: (context){
return new SettingPage();
}
),
),
padding: EdgeInsets.only(left:20.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child:SvgPicture.asset(iconSvgS5, height: 30.0, color:Colors.blueAccent),
),
Padding(
padding: const EdgeInsets.only(left:20.0),
child: GestureDetector(
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => FaqPage()),
),
child:Text(
"Вопросы и ответы",
style: TextStyle(
fontSize: 18.0
),
),
),
),
],
),
),
If you are wrapping your text widget inside of a button then the button by default have feedback to let users know when they are pressed, if you don't need the feedback consider wrapping the button with a GestureDetector widget, and passing a function to the onTap property
Removed the background color on click with this code:
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
You can use the hoverColor property of the FlatButton to set the hoverColor to your liking, here is the modified code that disables the hoverColor (simply sets it to transparent Colors.transparent) -
Align(
alignment: AlignmentDirectional.topStart,
child: FlatButton(
//setting the hover color to transparent.
hoverColor : Colors.transparent,
onPressed: () => Navigator.of(context).push(
new MaterialPageRoute(builder: (context) {
return new SettingPage();
}),
),
padding: EdgeInsets.only(left: 20.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: SvgPicture.asset(iconSvgS5,
height: 30.0, color: Colors.blueAccent),
),
Padding(
padding: const EdgeInsets.only(left: 20.0),
child: GestureDetector(
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => FaqPage()),
),
child: Text(
"Вопросы и ответы",
style: TextStyle(fontSize: 18.0),
),
),
),
],
),
),
),
Also side note having a GestureDetector inside of a FlatButton is redundant, and in your case it is ambiguous as well since they are do two separate navigation.
Set all color properties of the FlatButton to transparent.
The example below also includes a convenient hack, how to make the clickable area wider, so if the user will press near the icon, the button will work.
It improves button responsiveness.
Example
FlatButton(
color: Colors.transparent,
focusColor: Colors.transparent,
hoverColor: Colors.transparent,
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
padding: const EdgeInsets.all(0.0),
minWidth: 24,
onPressed: () => Get.back(),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
CupertinoIcons.clear,
color: Theme.of(context).colorScheme.pureBlack,
size: 18,
),
],
),
),

Cupetino navigation bar middle title not showing

Hello i am trying to give title to the app bar for cupertinonavigationbar middle widget but the text is not showing up.I tried to change the middle title text color still not showing up.What am i missing here?
static buildAppBar(
{bool isIOS,
Function onPressedShoppingSearch,
String heroTag,
String middleTitle}) {
return (isIOS == true)
? CupertinoNavigationBar(
middle: (middleTitle != null)
? Text(
middleTitle,
style: TextStyle(color: Colors.grey, fontSize: 18),
)
: Text(''),
transitionBetweenRoutes: false,
automaticallyImplyMiddle: true,
automaticallyImplyLeading: true,
heroTag: heroTag,
backgroundColor: Colors.white,
trailing: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
GestureDetector(
child: Icon(
FrinoIcons.f_search_classic,
color: Colors.red,
size: 23,
),
onTap: onPressedShoppingSearch,
),
const SizedBox(width: 6),
const Icon(
FrinoIcons.f_cart,
color: Colors.red,
size: 23,
),
],
),
)
I've just had a similar problem and found that the middle widget wasn't being displayed because my trailing widget was deemed (somehow) to be too large for that section of the navigation bar.
There are a few people that seem to be having similar issues due to leading and trailing widgets requiring a smaller size: https://github.com/flutter/flutter/issues/36689
Here's the code that I used in order to get it working (both old & new).
ORIGINAL CODE (Which wasn't working):
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
leading: Container(),
middle: Text(
'Filters'.tr,
),
trailing: _closeButton(),
),
backgroundColor: Colors.white,
child: SafeArea(
child: Stack(
children: [_closeButton()],
),
),
);
}
Widget _closeButton() {
return Align(
alignment: Alignment.topRight,
child: Padding(
padding: EdgeInsets.fromLTRB(0, 0, 0, 0),
child: Container(
height: 32,
width: 32,
child: TextButton(
onPressed: () => _closeView(),
child: Image(
color: Colors.black,
image: AssetImage(SignalAsset.imagePath('icon_cross')),
)),
),
),
);
}
NEW CODE (Which works):
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
leading: Container(),
middle: Text(
'Filters'.tr,
),
trailing: GestureDetector(
child: Image(
color: Colors.black,
image: AssetImage(SignalAsset.imagePath('icon_cross')),
),
onTap: () => _closeView(),
),
),
backgroundColor: Colors.white,
child: SafeArea(
child: Stack(
children: [_closeButton()],
),
),
);
}