Reputation: 904
I need help with animating my AppBar.
My AppBar hides on DoubleTap, but there's no animation in it, it hides immediately. I want it to be animated. I tried to wrap my AppBar with SlideTransition and AnimatedContainer widget, but none of these work, because the error says I need a PreferredSize widget.
I would be extremely glad, if someone helped me!
I already checked out this answer, but the guy, who answered to this question, has the same problem. There's no animation. Show (slide in) or hide (slide out) flutter AppBar on screen tap
Here's the video of my AppBar: https://streamable.com/it7ib
Here's the photo how my AppBar looks like:
Code:
import 'package:flutter/material.dart';
class GeneratedCouponScreen extends StatefulWidget {
@override
_GeneratedCouponScreenState createState() => _GeneratedCouponScreenState();
}
class _GeneratedCouponScreenState extends State<GeneratedCouponScreen> {
bool showAppBar = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: showAppBar ? AppBar() : null ,
backgroundColor: Colors.white,
body: GestureDetector(
onDoubleTap: () {
if (showAppBar) {
setState(() {
showAppBar = false;
});
}
else {
setState(() {
showAppBar = true;
});
}
},
child: SafeArea(
child: Container(
padding: EdgeInsets.all(16.0),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('DATA WYDANIA:', style: TextStyle(color: Colors.black),),
Text('10/09/2019', style: TextStyle(color: Colors.black))
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('UNIKALNY KOD:', style: TextStyle(color: Colors.black)),
Text('e-86-tC-9', style: TextStyle(color: Colors.black))
],
)
],
),
Column(
children: [
SizedBox(height: 8.0),
Image.asset('assets/images/coupon_hamburger.png',)
],
)
],
)
),
)));
}
}
Upvotes: 5
Views: 9549
Reputation: 408
We can achieve this with animated container widget. We have to make a custom AnimatedAppBar widget that manages the animation.
class AnimatedAppBar extends StatelessWidget implements PreferredSizeWidget { //implements PreferredSizeWidget
const AnimatedAppBar({super.key, required this.showAppBar});
final bool showAppBar;
@override
Widget build(BuildContext context) {
return AnimatedContainer(
// when showAppBar value is true appbar will show with animation
// when showAppBar value is false appbar will hide with animation
height: showAppBar ? kToolbarHeight : 0,
//adjust your duration
duration: const Duration(milliseconds: 400),
child: AppBar(),
);
}
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}
Upvotes: 3
Reputation: 1585
One way of doing it is by using stack and AnimatedBuilder.
class GeneratedCouponScreen extends StatefulWidget {
@override
_GeneratedCouponScreenState createState() => _GeneratedCouponScreenState();
}
class _GeneratedCouponScreenState extends State<GeneratedCouponScreen>
with SingleTickerProviderStateMixin {
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: Duration(milliseconds: 300),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: AnimatedBuilder(
animation: _controller,
builder: (context, child) => Stack(
children: <Widget>[
Transform.translate(
offset: Offset(0, -_controller.value * 64),
child: Container(
height: 56.0,
child: AppBar(
title: Text('Title'),
leading: Icon(
Icons.arrow_back,
),
),
),
),
GestureDetector(
onDoubleTap: () {
if (_controller.isCompleted) {
_controller.reverse();
} else {
_controller.forward();
}
},
child: Container(
margin: const EdgeInsets.only(top: 56.0),
padding: EdgeInsets.all(16.0),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'DATA WYDANIA:',
style: TextStyle(color: Colors.black),
),
Text('10/09/2019',
style: TextStyle(color: Colors.black))
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('UNIKALNY KOD:',
style: TextStyle(color: Colors.black)),
Text('e-86-tC-9',
style: TextStyle(color: Colors.black))
],
)
],
),
Column(
children: [
SizedBox(height: 8.0),
Image.network(
'http://via.placeholder.com/640x360',
)
],
)
],
),
),
),
],
),
),
),
);
}
}
Upvotes: 6
Reputation: 2839
First you have to create a new class
class MyAppBar extends StatefulWidget implements PreferredSizeWidget {
num height = 70.0;
@override
_MyAppBarState createState() => _MyAppBarState();
@override
Size get preferredSize => Size.fromHeight(height);
}
class _MyAppBarState extends State<MyAppBar> {
@override
Widget build(BuildContext context) {
return Container(
child: GestureDetector(
onDoubleTap: () {
// Your logic here
// You can do any stuff like animating your this appBar
//e.g: using Opacitiy or Transform and any other Widget depending on what kind of animation you want
// You can also descrease height by calling widget.height
},
child: AppBar(
//Your logic here
),
),
);
}
}
Then call it like this
return Scaffold(
appBar: MyAppBar(),);
Upvotes: 1