I have a login-page where I want the transition of the logo from large to small (and back) to be smoother. As it is now, it just pops between the two.
When the keyboard opens, I would like the logo to animate to the smaller position, instead of just instantly changing.
Does anyone know a way to do this?
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
resizeToAvoidBottomInset: true,
backgroundColor: AppColors.yellowLight,
// appBar: MainAppBar(),
body: SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
padding: EdgeInsets.symmetric(vertical: 90),
child: Image(
image: ExactAssetImage('assets/icons/app_logo.png'),
height: MediaQuery.of(context).viewInsets.bottom == 0
? size.height * 0.3
: size.height * 0.15,
fit: BoxFit.fitHeight,
alignment: Alignment.center,
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 50),
child: MainTextField(
controller: emailController,
labelText: 'E-post',
hintText: 'Skriv e-post som [email protected]'),
),
Padding(
padding: const EdgeInsets.only(
left: 50.0, right: 50.0, top: 30, bottom: 30),
child: MainTextField(
controller: passwordController,
obscureText: true,
labelText: 'Passord',
hintText: 'Skriv inn sikkert passord',
),
),
LoginButton(
text: 'Logg inn',
isLoading: isLoading,
onPressed: _login,
),
// Text('New User? Create Account')
],
),
),
),
);
}
CodePudding user response:
AnimatedContainer(
height: MediaQuery.of(context).viewInsets.bottom != 0 ? 100.0 : 200.0,
width: MediaQuery.of(context).viewInsets.bottom != 0 ? 100 : 200.0,
duration:const Duration(milliseconds: 750),
curve: Curves.fastOutSlowIn,
child: Image.network("https://picsum.photos/200/300"),
),
but MediaQuery.of(context).viewInsets.bottom it won't give you accuracy as if it's real time when changing the keyboard state, so I advice you to use another method to know the current state of the keyboard like the code below
you can use this package to listen for keyboard change flutter_keyboard_visibility here is the code
class _MyHomePageState extends State<MyHomePage> {
late StreamSubscription<bool> keyboardSubscription;
bool _isVisible = false;
@override
void initState() {
super.initState();
var keyboardVisibilityController = KeyboardVisibilityController();
// Subscribe
keyboardSubscription = keyboardVisibilityController.onChange.listen((bool visible) {
if(mounted) {
setState(() {
_isVisible = visible;
});
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
AnimatedContainer(
height: _isVisible ? 100.0 : 200.0,
width: _isVisible ? 100 : 200.0,
duration:const Duration(milliseconds: 750),
curve: Curves.fastOutSlowIn,
child: Image.network("https://picsum.photos/200/300"),
),
Spacer(),
const Text(
'You have pushed the button this many times:',
),
TextFormField(
),
Spacer(),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: (){},
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
@override
void dispose() {
keyboardSubscription.cancel();
super.dispose();
}
}
if you don't want to use package for keyboard visibility so you can use this code
class _MyHomePageState extends State<MyHomePage> {
final FocusNode _myNode = FocusNode();
bool _isVisible = false;
@override
void initState() {
super.initState();
_myNode.addListener(_listener);
}
void _listener(){
if(_myNode.hasFocus){
// keyboard appeared
if(mounted){
setState(() {
_isVisible = true;
});
}
}else{
// keyboard dismissed
if(mounted){
setState(() {
_isVisible = false;
});
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
AnimatedContainer(
height: _isVisible ? 100.0 : 200.0,
width: _isVisible ? 100 : 200.0,
duration:const Duration(milliseconds: 750),
curve: Curves.fastOutSlowIn,
child: Image.network("https://picsum.photos/200/300"),
),
Spacer(),
const Text(
'You have pushed the button this many times:',
),
TextFormField(
focusNode: _myNode,
),
Spacer(),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: (){},
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
@override
void dispose() {
_myNode.removeListener(_listener);
super.dispose();
}
}
CodePudding user response:
I found a way that kind of works. At least the animation does. But as it is based on MediaQuery.of(context).viewInsets.bottom == 0
still, the animation does not start until the keyboard is all the way out of view.
AnimatedContainer(
duration: Duration(milliseconds: 400),
curve: Curves.fastOutSlowIn,
padding: MediaQuery.of(context).viewInsets.bottom == 0
? EdgeInsets.symmetric(vertical: 100)
: EdgeInsets.only(top: 75, bottom: 10),
height: MediaQuery.of(context).viewInsets.bottom == 0
? _height.height * 0.5
: _height.height * 0.25,
child: Image(
image: ExactAssetImage('assets/icons/app_logo.png'),
),
),