I like to hide the floatingActionButton
on scroll down and to show it when scrolling up. But it only works after hot restart or reload.
transaction.dart
class Transaction extends StatefulWidget {
const Transaction({Key? key}) : super(key: key);
@override
State<Transaction> createState() => _TransactionState();
}
bool isFab = false;
class _TransactionState extends State<Transaction> {
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
body: SafeArea(
child: NestedScrollView(
floatHeaderSlivers: true,
headerSliverBuilder: (context, innerBoxIsScrolled) => [
SliverAppBar(
pinned: true,
floating: true,
snap: true,
centerTitle: true,
title: Text(
"Money Manager",
style: TextStyle(letterSpacing: 1.5),
strutStyle: StrutStyle(
fontSize: 20, fontStyle: FontStyle.normal),
),
bottom: TabBar(tabs: [
Tab(
child: Text(
"Income",
style:
TextStyle(fontSize: 18, letterSpacing: 1.5),
),
),
Tab(
child: Text(
"Expense",
style:
TextStyle(fontSize: 18, letterSpacing: 1.5),
),
)
]),
)
],
body: TabBarView(children: [Income(), Expense()]))),
floatingActionButton: isFab ? Fab() : null,
),
);
}
}
expense.dart
class Expense extends StatefulWidget {
const Expense({Key? key}) : super(key: key);
@override
State<Expense> createState() => _ExpenseState();
}
class _ExpenseState extends State<Expense> {
@override
Widget build(BuildContext context) {
return NotificationListener<UserScrollNotification>(
onNotification: (notification) {
if (notification.direction == ScrollDirection.forward) {
setState(() => isFab = true);
} else if (notification.direction == ScrollDirection.reverse) {
setState(() => isFab = false);
}
return true;
},
child: ListView.separated(
itemBuilder: (context, index) {
return ListTile(
leading: CircleAvatar(),
trailing: Text("- ₹2000"),
title: Text("category"),
subtitle: Text(formatter),
);
},
separatorBuilder: (context, index) {
return Divider();
},
itemCount: 30),
);
}
}
CodePudding user response:
In your code, isFab
is declared false
as a global variable, so it won't be changed by a setState
call. I don't exactly know why it starts to work after a hot reload or restart though.
To make it work you have to make it part of _TransactionState
, and you also have to make it accessible from ExpenseState
since you put the NotificationListener
there.
But probably the simplest solution is to move the NotificationListener
in Transaction
as the body of the Scaffold
, then declare the isFab
variable as part of the _TransactionState
.
You can see it here: I had to change something (like using the default FAB) to make the dartpad run, but now the FAB appears only when on top.