I have added a TabBar to my flutter app. It was pretty easy. I have created a new page for tab 1 and moved an existing page to tab 2. Both of these pages should display data from a Firestore QuerySnapshot but I don't know how to do this.
I have a screen, AgentDashBoardScreen, that creates a QuerySnapshot and builds a ListView with the data retrieved by the query.
In the onTap property of each ListTile the user is taken to the TransactionHomeScreen which has the TabBar widget in it. Also, I want to pass the QuerySnapshot to this page. Below is the code for AgentDashBoardScreen.
class AgentDashboardScreen extends StatefulWidget {
static const String id = 'agent_dashboard_screen';
@override
_AgentDashboardScreenState createState() => _AgentDashboardScreenState();
}
class _AgentDashboardScreenState extends State<AgentDashboardScreen> {
bool showSpinner = false;
//int _selectedIndex = 0;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('assets/images/Appbar_logo.png',
fit: BoxFit.cover, height: 56),
],
),
),
drawer: Drawer(
child: ListView(
children: <Widget>[
ListTile(
title: Text("Agent Profile"),
onTap: () {
MainScreen.of(context)?.setIndex(3); // Added this for BottomNavigationBar sync
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => AgentProfileScreen()));
},
),
],
),
),
body: SafeArea(
child: Container(
child: StreamBuilder(
stream: FirestoreService().getAgencyTrxns(context),
builder: (context, snapshot) {
if (!snapshot.hasData)
return Center(
child: const Text(
'Loading...',
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.bold),
));
return new ListView.builder(
itemCount: (snapshot.data! as QuerySnapshot).docs.length,
itemBuilder: (BuildContext context, int index) {
Trxns trxns = Trxns.fromFirestore(
(snapshot.data! as QuerySnapshot).docs[index]
.data() as Map<String, dynamic>);
return ListTile(
isThreeLine: true,
title: Text(
'Client: ${trxns.clientFName ?? 'n/a'} ${trxns
.clientLName ?? 'n/a'}',
style: TextStyle(
fontWeight: FontWeight.w900,
color: Colors.blueAccent),
),
subtitle: Text.rich(TextSpan(
text:
'${trxns.propertyAddress ?? 'n/a'}, ${trxns
.propertyCity ?? 'n/a'}, ${trxns
.propertyState ?? 'n/a'}',
children: <TextSpan>[
TextSpan(
text:
'\nPrice: ${trxns!.contractPrice == null ? 'n/a' : NumberFormat.simpleCurrency().format(trxns.contractPrice)}\nStatus: ${trxns.trxnStatus ?? 'n/a'}',
style: TextStyle(
fontWeight: FontWeight.w900,
color: Colors.blueGrey),
)
])),
trailing: Text('MLS#: ${trxns.mlsNumber ?? 'n/a'}\n${trxns.clientType}'),
onTap: () {
MainScreen.of(context)?.setIndex(2); // Added this for BottomNavigationBar sync
globals.newTrxn = false;
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
**TrxnHomeScreen(
(snapshot.data! as QuerySnapshot).docs[index])));**
},
);
});
},
),
),
),
));
}
}
Here is the code for the TrxnHomeScreen.
class TrxnHomeScreen extends StatefulWidget {
static const String id = 'trxn_home_screen';
final QueryDocumentSnapshot? trxns;
TrxnHomeScreen([this.trxns]);
@override
_TrxnHomeScreenState createState() => _TrxnHomeScreenState();
}
class _TrxnHomeScreenState extends State<TrxnHomeScreen> with SingleTickerProviderStateMixin {
bool showSpinner = false;
TabController? _trxnTabController;
@override
void initState() {
super.initState();
_trxnTabController = TabController(length: 3, vsync: this);
}
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
child: MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('assets/images/Appbar_logo.png',
fit: BoxFit.cover, height: 56),
],
),
bottom: TabBar(
indicatorWeight: 5,
indicatorColor: Colors.orange,
controller: _trxnTabController,
tabs: [
Tab(
text: "STATUS"
),
Tab(
text: "DETAILS",
),
Tab(
text: "TASKS",
),
],
),
),
body: SafeArea(
child: Container(
child: TabBarView(
controller: _trxnTabController,
children: <Widget>[
TransactionStatusScreen(widget.trxns),
TransactionDetailScreen(widget.trxns),
Text('Tasks'),
])
),
),
)),
);
}
}
Here is the code for the TransactionDetailScreen.
class TransactionDetailScreen extends StatefulWidget {
static const String id = 'transaction_detail_screen';
final QueryDocumentSnapshot? trxns;
TransactionDetailScreen([this.trxns]);
@override
_TransactionDetailScreenState createState() =>
_TransactionDetailScreenState();
}
class _TransactionDetailScreenState extends State<TransactionDetailScreen> {
getTrxn() async {
final DocumentSnapshot _mlsId =
await mlsRef.doc(globals.mlsId).get();
_mlsSearchLink = _mlsId.get('mlsNbrSearch');
if (widget.trxns == null) {
globals.newTrxn = true;
} else {
globals.newTrxn = false;
}
@override
void initState() {
getTrxn();
super.initState();
}
@override
Widget build(BuildContext context) {
}
}