Flutter 中的标签栏
Tab Bar in Flutter
我想在长度为 2 的名为“Need Help”和“Help Requests”的应用程序中实现 Tab Bar。在“需要帮助”选项卡中,我想要我的第一个容器(即将数据上传到 Firestore 数据库),在“帮助请求”选项卡中,我想要我的第二个容器(即从 Firestore 数据库中检索数据)。我是 flutter 的新手,如果你能帮助我,我将不胜感激。
源代码:
import 'package:chat_app/group_chats/group_info.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import '../constants.dart';
import '../global_data.dart';
class FinancialRoom extends StatelessWidget {
final String groupChatId, groupName;
FinancialRoom({required this.groupName, required this.groupChatId, Key? key})
: super(key: key);
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
final FirebaseAuth _auth = FirebaseAuth.instance;
final _formKey = GlobalKey<FormState>();
TextEditingController amountValue = TextEditingController();
void onSend() async {
Map<String, dynamic> data = {
"amount": amountValue.text,
"sendBy": _auth.currentUser!.displayName,
"type": "text",
"time": FieldValue.serverTimestamp(),
};
amountValue.clear();
await _firestore
.collection('groups')
.doc(groupChatId)
.collection('chats')
.add(data);
}
@override
Widget build(BuildContext context) {
final Size size = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
title: Text(groupName),
actions: [
IconButton(
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => GroupInfo(
groupName: groupName,
groupId: groupChatId,
),
),
),
icon: Icon(Icons.more_vert)),
],
),
body: SafeArea(
child: ListView(padding: EdgeInsets.all(20.0), children: [
Container(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
height: 10.0,
),
TextFormField(
controller: amountValue,
decoration: InputDecoration(
hintText: 'Enter the amount you want',
labelText: 'Enter the amount you want',
prefixIcon: Icon(Icons.account_balance_wallet_outlined),
enabledBorder: kEnabledBorder,
focusedBorder: kFocusedBorder,
errorBorder: kErrorBorder,
focusedErrorBorder: kErrorBorder,
),
onTap: () {
},
// The validator receives the text that the user has entered.
validator: (value) {
if (value!.isEmpty) {
return 'Please enter the amount you want';
}
return null;
},
),
SizedBox(
height: kInputSpacing,
),
SizedBox(
width: double.infinity,
child: FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)),
color: Colors.blue,
textColor: Colors.white,
padding: EdgeInsets.only(top: 16.0, bottom: 16.0),
onPressed: onSend,
child: Text(
'SEND',
style: kButtonTextStyle,
),
),
),
],
),
),
Container(
height: size.height / 1.27,
width: size.width,
child: StreamBuilder<QuerySnapshot>(
stream: _firestore
.collection('groups')
.doc(groupChatId)
.collection('chats')
.orderBy('time')
.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
Map<String, dynamic> data =
snapshot.data!.docs[index].data()
as Map<String, dynamic>;
return messageTile(size, data);
},
);
} else {
return Container();
}
},
),
),
]),
),
);
}
Widget messageTile(Size size, Map<String, dynamic> data) {
return Builder(builder: (_) {
if (data['type'] == "text") {
return Container(
width: size.width,
alignment: data['sendBy'] == _auth.currentUser!.displayName
? Alignment.centerRight
: Alignment.centerLeft,
child: Container(
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 14),
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: Colors.blue,
),
child: Column(
children: [
Text(
data['sendBy'],
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
SizedBox(
height: size.height / 200,
),
Text(
data['amount'],
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
],
)),
);
} else if (data['type'] == "img") {
return Container(
width: size.width,
alignment: data['sendBy'] == _auth.currentUser!.displayName
? Alignment.centerRight
: Alignment.centerLeft,
child: Container(
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 14),
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 8),
height: size.height / 2,
child: Image.network(
data['amount'],
),
),
);
} else if (data['type'] == "notify") {
return Container(
width: size.width,
alignment: Alignment.center,
child: Container(
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8),
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Colors.black38,
),
child: Text(
data['message'],
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
);
} else {
return SizedBox();
}
});
}
}
在您的应用中实现一个简单的 TabBar
非常简单。您只需要一个 TabController
和两个名为 TabBar
和 TabBarView
的小部件。这是一个简单的例子:
DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(tabs: [
Tab(text: 'Tab 1'),
Tab(text: 'Tab 2'),
]),
),
body: TabBarView(children: [
// Tab 1
Container(color: Colors.red),
// Tab 2
Container(color: Colors.blue),
]),
),
);
现在您需要做的就是将 TabBarView
中的 children
替换为您想要显示的内容。
我想在长度为 2 的名为“Need Help”和“Help Requests”的应用程序中实现 Tab Bar。在“需要帮助”选项卡中,我想要我的第一个容器(即将数据上传到 Firestore 数据库),在“帮助请求”选项卡中,我想要我的第二个容器(即从 Firestore 数据库中检索数据)。我是 flutter 的新手,如果你能帮助我,我将不胜感激。
源代码:
import 'package:chat_app/group_chats/group_info.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import '../constants.dart';
import '../global_data.dart';
class FinancialRoom extends StatelessWidget {
final String groupChatId, groupName;
FinancialRoom({required this.groupName, required this.groupChatId, Key? key})
: super(key: key);
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
final FirebaseAuth _auth = FirebaseAuth.instance;
final _formKey = GlobalKey<FormState>();
TextEditingController amountValue = TextEditingController();
void onSend() async {
Map<String, dynamic> data = {
"amount": amountValue.text,
"sendBy": _auth.currentUser!.displayName,
"type": "text",
"time": FieldValue.serverTimestamp(),
};
amountValue.clear();
await _firestore
.collection('groups')
.doc(groupChatId)
.collection('chats')
.add(data);
}
@override
Widget build(BuildContext context) {
final Size size = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
title: Text(groupName),
actions: [
IconButton(
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => GroupInfo(
groupName: groupName,
groupId: groupChatId,
),
),
),
icon: Icon(Icons.more_vert)),
],
),
body: SafeArea(
child: ListView(padding: EdgeInsets.all(20.0), children: [
Container(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
height: 10.0,
),
TextFormField(
controller: amountValue,
decoration: InputDecoration(
hintText: 'Enter the amount you want',
labelText: 'Enter the amount you want',
prefixIcon: Icon(Icons.account_balance_wallet_outlined),
enabledBorder: kEnabledBorder,
focusedBorder: kFocusedBorder,
errorBorder: kErrorBorder,
focusedErrorBorder: kErrorBorder,
),
onTap: () {
},
// The validator receives the text that the user has entered.
validator: (value) {
if (value!.isEmpty) {
return 'Please enter the amount you want';
}
return null;
},
),
SizedBox(
height: kInputSpacing,
),
SizedBox(
width: double.infinity,
child: FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)),
color: Colors.blue,
textColor: Colors.white,
padding: EdgeInsets.only(top: 16.0, bottom: 16.0),
onPressed: onSend,
child: Text(
'SEND',
style: kButtonTextStyle,
),
),
),
],
),
),
Container(
height: size.height / 1.27,
width: size.width,
child: StreamBuilder<QuerySnapshot>(
stream: _firestore
.collection('groups')
.doc(groupChatId)
.collection('chats')
.orderBy('time')
.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
Map<String, dynamic> data =
snapshot.data!.docs[index].data()
as Map<String, dynamic>;
return messageTile(size, data);
},
);
} else {
return Container();
}
},
),
),
]),
),
);
}
Widget messageTile(Size size, Map<String, dynamic> data) {
return Builder(builder: (_) {
if (data['type'] == "text") {
return Container(
width: size.width,
alignment: data['sendBy'] == _auth.currentUser!.displayName
? Alignment.centerRight
: Alignment.centerLeft,
child: Container(
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 14),
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: Colors.blue,
),
child: Column(
children: [
Text(
data['sendBy'],
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
SizedBox(
height: size.height / 200,
),
Text(
data['amount'],
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
],
)),
);
} else if (data['type'] == "img") {
return Container(
width: size.width,
alignment: data['sendBy'] == _auth.currentUser!.displayName
? Alignment.centerRight
: Alignment.centerLeft,
child: Container(
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 14),
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 8),
height: size.height / 2,
child: Image.network(
data['amount'],
),
),
);
} else if (data['type'] == "notify") {
return Container(
width: size.width,
alignment: Alignment.center,
child: Container(
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8),
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Colors.black38,
),
child: Text(
data['message'],
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
);
} else {
return SizedBox();
}
});
}
}
在您的应用中实现一个简单的 TabBar
非常简单。您只需要一个 TabController
和两个名为 TabBar
和 TabBarView
的小部件。这是一个简单的例子:
DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(tabs: [
Tab(text: 'Tab 1'),
Tab(text: 'Tab 2'),
]),
),
body: TabBarView(children: [
// Tab 1
Container(color: Colors.red),
// Tab 2
Container(color: Colors.blue),
]),
),
);
现在您需要做的就是将 TabBarView
中的 children
替换为您想要显示的内容。