Flutter stack layout container use remaining height - flutter

I'm starting with Flutter.
I'm building a layout to look like
I'm using Stack to build this layout, where the part in background color is another Stack child with parent Container height to a fixed value.
The code I have written till now is
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:whatsappwithoutcontact/components/form_fields.dart';
import 'package:whatsappwithoutcontact/screens/info/info-screen.dart';
class MessageScreen extends StatefulWidget {
#override
_MessageScreenState createState() => _MessageScreenState();
}
class _MessageScreenState extends State<MessageScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('WhatsApp without Contact'),
backgroundColor: Colors.transparent,
elevation: 0.0,
actions: [
IconButton(
icon: Icon(Icons.info),
onPressed: _onInfoPressed,
)
],
),
extendBodyBehindAppBar: true,
body: MessageContainer()
);
}
void _onInfoPressed() {
Navigator.of(context).push(
MaterialPageRoute<void> (
builder: (BuildContext context) {
return InfoScreen();
}
)
);
}
}
class MessageContainer extends StatefulWidget {
#override
_MessageContainerState createState() => _MessageContainerState();
}
class _MessageContainerState extends State<MessageContainer> {
static const double avatarRadius = 35;
static const double titleBottomMargin = (avatarRadius * 2) + 18;
static const double _headerHeight = 350.0;
final _formKey = GlobalKey<FormState>();
final _messageFieldFocusNode = FocusNode();
#override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Stack(
children: [
Container(
height: _headerHeight,
child: Stack(
children: <Widget>[
Container(
child: ClipPath(
clipper: HeaderClipper(avatarRadius: avatarRadius),
child: CustomPaint(
size: Size(MediaQuery.of(context).size.width, _headerHeight),
painter: HeaderPainter(
color: Colors.green,
avatarRadius: avatarRadius
),
),
),
),
Positioned(
left: 0,
right: 0,
child: Container(
padding: EdgeInsets.only(top: 80.0),
margin: EdgeInsets.all(50.0),
child: Column(
children: <Widget>[
FormTextField(
labelText: 'Country Code',
validator: (value) {
if (value.isEmpty) {
return 'Required';
}
return null;
}
),
SizedBox(height: 15.0,),
FormTextField(
labelText: 'Phone Number',
validator: (value) {
if (value.isEmpty) {
return 'Required';
}
return null;
},
)
],
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: CircleAvatar(
radius: avatarRadius,
backgroundColor: Colors.green,
child: IconButton(icon: Icon(Icons.message), onPressed: _onAddMessageButtonClick,),
),
)
],
),
),
SingleChildScrollView(
child: Padding(
padding: EdgeInsets.symmetric(
vertical: _headerHeight,
horizontal: 50
),
child: Column(
children: [
TextFormField(
keyboardType: TextInputType.multiline,
maxLines: 4,
focusNode: _messageFieldFocusNode,
decoration: InputDecoration(
labelText: 'Message',
fillColor: Colors.white,
labelStyle: TextStyle(
color: _messageFieldFocusNode.hasFocus ? Colors.green : Colors.grey
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.grey
)
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.green
)
)
),
)
],
),
),
),
],
)
);
}
}
The first Container inside the first Stack is the green background part and SingleChildScrollView is the part below the green color background.
The SingleChildScrollView is making the lower part scrollable whereas I want it to be fixed and take up remaining space below the message icon in the center.
I tried using Container but then the Message input field is not displayed.
How can I use the remaining space below the Stack layout?
Is my layout structure good according to the design. I need suggestions on how to improve it, if not good.

Replace the first Stack widget with Column, now you can wrap your SingleChildScrollView widget into an Expanded widget, the Expanded widget works only inside Column and Row to fill the available space.
Don't forget to remove vertical padding from the Message input field.

Related

How to show textinput box above the Keyboard while entering the input in flutter

I am using TextField widget in my project. I need to show the InputBox above the keyboard if the user clicks and start typing on the TextField, WhatsApp has this functionality in Landscape mode:
I need this functionality in my flutter application too, any little help will be very welcome, Thank you in advance.
Issue updated it here
below code will help you
import 'package:chat_system_flutter/utils/common_logic.dart';
import 'package:chat_system_flutter/utils/common_string.dart';
import 'package:flutter/material.dart';
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
import 'package:get/get.dart';
class ChatScreen extends StatefulWidget {
const ChatScreen({
Key? key,
}) : super(key: key);
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> with AutomaticKeepAliveClientMixin {
TextEditingController messageController = TextEditingController();
#override
void initState() {
super.initState();
}
#override
bool get wantKeepAlive => true;
#override
Widget build(BuildContext context) {
super.build(context);
return KeyboardVisibilityBuilder(
builder: (BuildContext context, bool isKeyboardVisible) {
if (isKeyboardVisible) {
// blok of code
}
return Obx(
() => Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
body: body(),
),
);
},
);
}
Widget body() {
return GestureDetector(
onTap: () {
hideKeyboard(context);
},
child: SafeArea(
child: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//message listview
],
),
),
),
Divider(
color: Theme.of(context).cardColor,
thickness: 2,
),
Container(
padding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 0,
),
child: Row(
children: [
Expanded(
child: TextField(
controller: messageController,
autocorrect: true,
enableSuggestions: true,
maxLines: 2,
onChanged: (val) {
// block of code
},
style: TextStyle(
fontSize: 16,
color: Theme.of(context).canvasColor,
),
decoration: InputDecoration(
hintText: typeYourMsgStr,
hintStyle: TextStyle(
fontSize: 16,
color: Theme.of(context).hintColor,
),
border: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.transparent,
),
),
enabledBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.transparent,
),
),
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.transparent,
),
),
),
textInputAction: TextInputAction.newline,
/* onSubmitted: (_) {
sendMsg();
},*/
),
),
GestureDetector(
onTap: () {
// send message
},
child: Container(
padding: const EdgeInsets.all(8),
child: Icon(
Icons.arrow_upward,
color: Theme.of(context).canvasColor,
),
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
borderRadius: BorderRadius.circular(10)),
),
),
],
),
),
],
),
),
);
}
}
output
You need to add a padding in your main Container which contains your TextField like this:
padding: EdgeInsets.only(
top: 10,
right: 10,
left: 10,
bottom: MediaQuery.of(context).viewInsets.bottom + 10,
),
What MediaQuery.of(context).viewInsets.bottom does is that it takes the height of onscreen keyboard and adds it to padding whenever the keyboard appears on the screen. This makes your TextField to move 10 pixels above your keyboard (that's because we added 10 to bottom padding separately).
Another Widget that would help with scrolling is wrapping your main widget with a SingleChildScrollView.
Feel free to clear up any confusions in the comments :)

State of my Widget not changing in flutter when updating value

What I am aiming for is, when a user long presses on a particular date, they should be able to enter their weight value, and upon submitting, the modal bottom sheet should close, and the updated weight should be visible as soon as the modal sheet is out of view. But It does not happen.
Instead I have to go to other date and come back to see the changes. Please help me. I am new to flutter.
Here is the demo of the problem :
problem i am facing
Here is the code:
void _modalBottomSheetMenu(DateTime dt) {
showModalBottomSheet(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
context: context,
isScrollControlled: true,
builder: (builder) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text("Add a weight"),
Container(
width: 200.0,
child: TextField(
controller: myController,
keyboardType: TextInputType.number,
textAlign: TextAlign.center,
autofocus: true,
maxLength: 4,
onSubmitted: (value) {
weightValue = double.parse(value);
print("Weight entered is $weightValue");
print("Date passed is $dt");
setState(() {
_events[dt] = [weightValue].toList();
Navigator.pop(context);
});
print(_events[dt][0]);
},
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Weight',
hintText: 'Enter your weight'),
),
),
],
);
},
);
}
BuildEventList : This contains the weight to be printed
import 'package:flutter/material.dart';
class BuildEventList extends StatefulWidget {
String weight;
BuildEventList(this.weight);
#override
_BuildEventListState createState() => _BuildEventListState();
}
class _BuildEventListState extends State<BuildEventList> {
#override
void setState(fn) {
// TODO: implement setState
super.setState(fn);
}
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
border: Border.all(width: 0.8),
borderRadius: BorderRadius.circular(12.0),
),
margin: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
child: Container(
width: double.infinity,
child: Center(child: Text("${widget.weight}")),
),
);
}
}
This is where it is called :
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.title), actions: [
IconButton(
icon: Icon(Icons.add),
color: Colors.white,
onPressed: () {},
)
]),
body: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
_buildTableCalendar(),
const SizedBox(height: 8.0),
//_buildButtons(),
const SizedBox(height: 8.0),
Expanded(
child: BuildEventList(_selectedEvents.length > 0
? _selectedEvents[0].toString()
: "No weight given!")),
],
),
);
}

How to get static container background but scrollable loginform?

I want to scroll the loginform but NOT the background, but i noticed that the cointaner that contains these "circles" are moved to the up when keyboards appears, so i added
resizeToAvoidBottomInset: true,
To the scaffold, but now i cant scroll anything in the loginform and thats is what i dont want, i want to scroll ONLY the loggin form..
Here is the screenshot of the emulator, just click this
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:landscapes/bloc/inherited_provider.dart';
import 'package:landscapes/bloc/login_bloc.dart';
import 'package:landscapes/pages/register_page.dart';
class LoginPage extends StatefulWidget {
LoginPage({Key key}) : super(key: key);
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: true,
body: Form(
key: formKey,
child: Stack(
children: <Widget>[
_crearFondo(),
_loginForm(context),
],
),
));
}
Widget _crearFondo() {
Size size = MediaQuery.of(context).size;
final fondoGris = Container(
height: size.height, width: size.width, color: Colors.grey[850]);
final circulo = Container(
width: 90.0,
height: 90.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100.0),
color: Color.fromRGBO(255, 255, 255, 0.05)),
);
return Stack(
children: <Widget>[
fondoGris,
Positioned(top: 50.0, left: 30.0, child: circulo),
Positioned(top: 150.0, right: 50.0, child: circulo),
Positioned(bottom: 180.0, right: 20.0, child: circulo),
Positioned(bottom: 280.0, left: 40.0, child: circulo),
],
);
}
Widget _loginForm(context) {
final bloc = InheritedProvider.loginBlocInherit(context);
final size = MediaQuery.of(context).size;
return SingleChildScrollView(
child: Column(
children: <Widget>[
SafeArea(child: Container(height: size.height * 0.05)),
SizedBox(height: size.height * 0.05),
welcomeBackForm(),
SizedBox(height: 55.0),
_formEmail(bloc),
SizedBox(height: 30.0),
_formPassword(),
SizedBox(height: 38),
_button(),
SizedBox(height: 50),
_crearCuenta(),
],
),
);
}
//MENSAJE BIENVENIDA
Widget welcomeBackForm() {
return Container(
alignment: Alignment.topLeft,
margin: EdgeInsets.only(left: 40.0),
child: Text(
'Hello!\nWelcome back',
style: GoogleFonts.playfairDisplay(
fontSize: 30, fontWeight: FontWeight.w600, color: Colors.white),
),
);
}
//TEXTFORMFIELD DEL EMAIL
Widget _formEmail(LoginBloc bloc) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 30.0),
child: TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
icon: Icon(
Icons.email,
color: Colors.white,
),
hintText: 'Email adress',
filled: true,
fillColor: Colors.grey[600],
enabledBorder: OutlineInputBorder(borderSide: BorderSide.none),
border: OutlineInputBorder(borderSide: BorderSide.none)),
style: TextStyle(height: 1),
validator: (value) {
Pattern pattern =
r'^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
RegExp regExp = new RegExp(pattern);
if (regExp.hasMatch(value)) {
return null;
} else {
return ('El email no es correcto');
}
},
),
);
}
//TEXTFORMFIELD DEL PASSWORD
Widget _formPassword() {
return Container(
padding: EdgeInsets.symmetric(horizontal: 30.0),
child: TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
icon: Icon(
Icons.lock,
color: Colors.white,
),
hintText: 'Password',
filled: true,
fillColor: Colors.grey[600],
enabledBorder: OutlineInputBorder(borderSide: BorderSide.none),
border: OutlineInputBorder(borderSide: BorderSide.none),
),
style: TextStyle(height: 1),
),
);
}
//BOTON INGRESAR
Widget _button() {
return RaisedButton(
color: Color.fromRGBO(254, 200, 140, 1),
padding: EdgeInsets.symmetric(horizontal: 90.0, vertical: 15.0),
child: Text('ingresar'),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
),
elevation: 0.0,
onPressed: () => _submit(),
);
}
//FLATBUTTON DE CREAR CUENTA
Widget _crearCuenta() {
return FlatButton(
onPressed: () => Navigator.pushReplacementNamed(context, 'registerpage'),
child: Text(
'Crear una nueva cuenta',
style: TextStyle(fontSize: 14),
),
textColor: Colors.white,
);
}
//SUBMIT DEL BOTON
void _submit() async {
if (!formKey.currentState.validate()) return null;
formKey.currentState.save();
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (BuildContext context) => RegisterPage()));
// Navigator.pushReplacementNamed(context, HomePage.routName).then((value) { setState(() { });});
}
}
You may try wrapping your _loginForm with SingleChildScrollView as follows :
SingleChildScrollView(child: _loginForm(context)),
By doing so the widgets within _crearFondo() will not scroll, however the widgets within _loginForm will scroll.
Please review the Flutter Documentation for SingleChildScrollView
SingleChildScrollView
A box in which a single widget can be scrolled.
This widget is useful when you have a single box that will normally be
entirely visible, for example a clock face in a time picker, but you
need to make sure it can be scrolled if the container gets too small
in one axis (the scroll direction).
It is also useful if you need to shrink-wrap in both axes (the main
scrolling direction as well as the cross axis), as one might see in a
dialog or pop-up menu. In that case, you might pair the
SingleChildScrollView with a ListBody child.
When you have a list of children and do not require cross-axis
shrink-wrapping behavior, for example a scrolling list that is always
the width of the screen, consider ListView, which is vastly more
efficient that a SingleChildScrollView containing a ListBody or Column
with many children.

How to reduce the white space beside the drawer icon in Flutter?

In my flutter project, I have set one custom drawer.
Here's code for custom drawer-
class AppDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
double defaultScreenWidth = 400.0;
double defaultScreenHeight = 810.0;
ScreenUtil.instance = ScreenUtil(
width: defaultScreenWidth,
height: defaultScreenHeight,
allowFontScaling: true,
)..init(context);
return SizedBox(
width: MediaQuery.of(context).size.width * 0.70,
child: Drawer(
child: Container(
color: Colors.black87,
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
SizedBox(height: ScreenUtil.instance.setHeight(30),),
_createDrawerItem(
icon: Icons.keyboard_arrow_right,
text: 'English to Bangla',
onTap: () =>
Navigator.pushReplacementNamed(context, Routes.englishToBangla)),
Padding(
padding: EdgeInsets.only(left:ScreenUtil.instance.setWidth(20), right: ScreenUtil.instance.setWidth(20)),
child: Divider(
height: ScreenUtil.instance.setHeight(10),
color: Colors.grey,
),
),
],
),
),
),
);
}
Widget _createHeader() {
return DrawerHeader(
margin: EdgeInsets.zero,
padding: EdgeInsets.zero,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.fill,
image: AssetImage('path/to/header_background.png'))),
child: Stack(children: <Widget>[
Positioned(
bottom: 12.0,
left: 16.0,
child: Text("Flutter Step-by-Step",
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.w500))),
]));
}
Widget _createDrawerItem(
{IconData icon, String text, GestureTapCallback onTap}) {
return ListTile(
title: Padding(
padding: EdgeInsets.only(left: ScreenUtil.instance.setWidth(10)),
child: Row(
children: <Widget>[
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.teal
),
child: Icon(icon, color: Colors.white,)
),
Padding(
padding: EdgeInsets.only(left: ScreenUtil.instance.setWidth(10)),
child: Text(text, style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: ScreenUtil.instance.setSp(14) ),),
)
],
),
),
onTap: onTap,
);
}
}
Here's code for the toolBar which is shown beside the drawer icon-
class SearchAppBar extends StatefulWidget implements PreferredSizeWidget {
final PatternCallback onPatternSelected;
SearchAppBar(this.onPatternSelected, {Key key})
: preferredSize = Size.fromHeight(90),
super(key: key);
#override
final Size preferredSize; // default is 56.0
#override
_SearchAppBarState createState() => _SearchAppBarState();
}
class _SearchAppBarState extends State<SearchAppBar> {
TextEditingController _searchTextController = TextEditingController();
#override
Widget build(BuildContext context) {
double defaultScreenWidth = 400.0;
double defaultScreenHeight = 810.0;
ScreenUtil.instance = ScreenUtil(
width: defaultScreenWidth,
height: defaultScreenHeight,
allowFontScaling: true,
)..init(context);
return Container(
color: Colors.white,
child: Row(
children: <Widget>[
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(3),
),
child: Theme(
data:
Theme.of(context).copyWith(primaryColor: Color(0xFFff9900)),
child: TextFormField(
autofocus: false,
style: TextStyle(fontSize: ScreenUtil.instance.setSp(18)),
keyboardType: TextInputType.text,
controller: _searchTextController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Search for any word you want',
hintStyle:
TextStyle(fontSize: ScreenUtil.instance.setSp(16)),
contentPadding: EdgeInsets.symmetric(
vertical: 14,
horizontal: 10),
),
onChanged: (String value) {
widget.onPatternSelected(value);
},
),
),
),
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(0),
),
child: InkWell(onTap: (){
if(_searchTextController.text.isNotEmpty) {
Navigator.of(context).push(MaterialPageRoute(builder: (context)=>WordDetailScreen(_searchTextController.text.toLowerCase())));
}
},
child: Icon(Icons.search, color: Colors.blue,))),
SizedBox(width: 15)
],
),
);
}
}
And then, in the class where I want to use this drawer, I have called inside Scaffold like below-
drawer: AppDrawer()
But the problem is this causing a white space beside the drawer icon like below image-
And I am having no idea from where this extra padding or margin is happening. So, I need a solution to reduce this extra white space beside the drawer icon.
You can use Transform.translate to move the search bar to the left:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Builder(builder: (context) {
return IconButton(
icon: Icon(Icons.menu),
onPressed: () => Scaffold.of(context).openDrawer(),
);
}),
title: Transform.translate(
offset: Offset(-30.0, 0.0),
child: Text('this is the title') // here you can put the search bar
),
),
drawer: Drawer(
),
);
}
Just add a property called "titleSpacing" in your AppBar Tag,
Sample
appBar: AppBar(
titleSpacing: 0, //Add this line to your code
title: Text(widget.title),
leading: Icon(Icons.android),
),

Flutter Animated Container

I have a RaisedButton widget and an AnimatedContainer widget in a screen, and the idea is that upon pressing the RaisedButton the width of the AnimatedContainer would then decrease in a given duration. The documentation of the AnimatedContainer states that all I would need to do is declare the width of the widget as a variable, and then setState(() {}) after changing the value and it will automatically change to that value during the duration. I have tried to implement this and upon pressing the RaisedButton the variables value definitely changes (based on printing the value of it after pressing it), however the widget's width does not change with it. Am I missing something obvious?
My Widgets are within a container in a PageView and my code for the RaisedButton and AnimatedContainer is as follows:
RaisedButton (
onPressed: () {
setState(() {
loginWidth = 70.0;
});
},
),
AnimatedContainer (
duration: new Duration (seconds: 2),
width: loginWidth,
height: 40,
color: Colors.red,
)
Here is my widget tree:
pages.add(
Container(
color: chSecondary,
child: Stack(
children: <Widget>[
Container (
child: Align (
child: Image(image: AssetImage("graphics/signin.png")),
alignment: Alignment.bottomCenter,
),
),
Form(
key: _formKey,
child: new Container(
padding: EdgeInsetsDirectional.only(top: 100, start: 15, end: 15, bottom: 15),
child: new Column(
children: <Widget>[
Container (
child: Image(image: AssetImage("graphics/login.png"), height: 200, width: 200,),
margin: EdgeInsetsDirectional.only(bottom: 20),
),
Container (
padding: EdgeInsets.all(25.0),
decoration: new BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: Colors.white,
),
child: Column (
children: <Widget>[
Align(
child: new Text("Email:", style: TextStyle(fontSize: tonSubTitle, color: Colors.black)),
alignment: Alignment.centerLeft,
),
new Container(
child: new TextFormField(
keyboardType: TextInputType.emailAddress,
controller: _email,
style: TextStyle(fontSize: tonText, color: Colors.black),
decoration: InputDecoration(
border: OutlineInputBorder(borderRadius: new BorderRadius.circular(tonRadius)),
contentPadding: EdgeInsetsDirectional.only(top: 15, start: 7.5),
focusedBorder: OutlineInputBorder(borderSide: new BorderSide(color: Colors.grey)),
hintText: "Email Address",
hintStyle: TextStyle(color: Colors.black),
),
validator: (value) {
if (value.isEmpty) {
return "Please enter an email";
}
if (!value.contains("#tonbridge-school.org")) {
return "Please enter a valid email address";
}
},
),
padding: const EdgeInsets.only(top: 10, bottom: 10)
),
Align (
child: new Text("Password:", style: TextStyle(fontSize: tonSubTitle, color: Colors.black)),
alignment: Alignment.centerLeft,
),
new Container(
child: new TextFormField(
obscureText: true,
controller: _password,
style: TextStyle(color: Colors.black, fontSize: tonText),
decoration: InputDecoration(
contentPadding: EdgeInsetsDirectional.only(top: 15, start: 7.5),
border: OutlineInputBorder(borderRadius: new BorderRadius.circular(tonRadius)),
focusedBorder: OutlineInputBorder(borderSide: new BorderSide(color: Colors.grey)),
hintText: "Password",
hintStyle: TextStyle(color: Colors.black),
),
validator: (value) {
if (value.isEmpty) {
return "Please enter a password";
}
},
),
padding: const EdgeInsets.only(top: 10, bottom: 10)
),
RaisedButton (
onPressed: () {
setState(() {
loginWidth = 70.0;
});
},
),
AnimatedContainer (
duration: new Duration (seconds: 2),
width: loginWidth,
height: 40,
color: Colors.red,
)
],
),
)
],
),
)
),
],
),
),
);
The code snippet you've posted is already correct.
Make sure that:
loginWidth is initialized
the new loginWidth value is actually different from the default value
I've copied it and built a minimal example so you can double check the rest of your code. This example also include a surrounding PageView:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: MyBody(),
),
);
}
}
class MyBody extends StatefulWidget {
#override
_MyBodyState createState() => _MyBodyState();
}
class _MyBodyState extends State<MyBody> {
double loginWidth = 40.0;
#override
Widget build(BuildContext context) {
return Center(
child: PageView(
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
RaisedButton (
child: Text('Animate!'),
onPressed: () {
setState(() {
loginWidth = 250.0;
});
},
),
AnimatedContainer (
duration: Duration (seconds: 1),
width: loginWidth,
height: 40,
color: Colors.red,
),
],
)
],
),
);
}
}
do you initialised loginWidth ?
var loginWidth =0.0;
Curve _curve = Curves.fastOutSlowIn;
_doanimation(){
setState(() {
loginWidth ==0.0? loginWidth =100: loginWidth =0.0;
});
}
change function with your case
Column(
children: <Widget>[
Text("welcome"),
RaisedButton(
onPressed: (){
_doanimation();
},
),
AnimatedContainer(
curve: _curve,
duration: Duration(seconds: 1),
width: loginWidth,
height:100
)
],
),
Where do you have loginWidth declared? It needs to outside the scope of the builder function or its value will get reinitialized on every build.
Can you update your example to show where you declare?
Correct:
class _WidgetState extends State<Widget> {
double loginWidth = 0;
#override
Widget build(BuildContext context) {
// return the new widget tree
}
}
Incorrect:
class _WidgetState extends State<Widget> {
#override
Widget build(BuildContext context) {
double loginWidth = 0;
//return the new widget tree
}
}