I'm working on simple chat features in my app. I have used OTP login method to do this application. Firebase Authentication is working well in my application. I have already done the code for the simple chat app but I would like to display the user's phone number when they send chat. Example pic added below for better understanding about the need:
This is my code:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import '../forum/message.dart';
class ForumScreen extends StatefulWidget {
String email;
ForumScreen({required this.email});
#override
_ForumScreenState createState() => _ForumScreenState(email: email);
}
class _ForumScreenState extends State<ForumScreen> {
String email;
_ForumScreenState({required this.email});
final fs = FirebaseFirestore.instance;
final _auth = FirebaseAuth.instance.currentUser;
final TextEditingController message = new TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Farmer's Forum"),
centerTitle: true,
automaticallyImplyLeading: false,
),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
height: MediaQuery.of(context).size.height * 0.73,
child: messages(
email: email,
),
),
Row(
children: [
Expanded(
child: TextFormField(
controller: message,
decoration: InputDecoration(
filled: true,
fillColor: Colors.lightGreen,
hintText: 'message',
enabled: true,
contentPadding: const EdgeInsets.only(
left: 14.0, bottom: 8.0, top: 8.0),
focusedBorder: OutlineInputBorder(
borderSide: new BorderSide(color: Colors.black),
borderRadius: new BorderRadius.circular(10),
),
enabledBorder: UnderlineInputBorder(
borderSide: new BorderSide(color: Colors.black),
borderRadius: new BorderRadius.circular(10),
),
),
validator: (value) {},
onSaved: (value) {
message.text = value!;
},
),
),
IconButton(
onPressed: () {
if (message.text.isNotEmpty) {
fs.collection('Messages').doc().set({
'message': message.text.trim(),
'time': DateTime.now(),
'email': email,
});
message.clear();
}
},
icon: Icon(Icons.send_sharp),
),
],
),
],
),
),
);
}
}
message.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class messages extends StatefulWidget {
String email;
messages({required this.email});
#override
_messagesState createState() => _messagesState(email: email);
}
class _messagesState extends State<messages> {
String email;
_messagesState({required this.email});
Stream<QuerySnapshot> _messageStream = FirebaseFirestore.instance
.collection('Messages')
.orderBy('time')
.snapshots();
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: _messageStream,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text("something is wrong");
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
itemCount: snapshot.data!.docs.length,
physics: ScrollPhysics(),
shrinkWrap: true,
primary: true,
itemBuilder: (_, index) {
QueryDocumentSnapshot qs = snapshot.data!.docs[index];
Timestamp t = qs['time'];
DateTime d = t.toDate();
print(d.toString());
return Padding(
padding: const EdgeInsets.only(top: 8, bottom: 8),
child: Column(
crossAxisAlignment: email == qs['email']
? CrossAxisAlignment.end
: CrossAxisAlignment.start,
children: [
SizedBox(
width: 300,
child: ListTile(
shape: RoundedRectangleBorder(
side: BorderSide(
color: Colors.green,
),
borderRadius: BorderRadius.circular(10),
),
title: Text(
qs['email'],
style: TextStyle(
fontSize: 15,
),
),
subtitle: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
width: 200,
child: Text(
qs['message'],
softWrap: true,
style: TextStyle(
fontSize: 15,
),
),
),
Text(
d.hour.toString() + ":" + d.minute.toString(),
)
],
),
),
),
],
),
);
},
);
},
);
}
}
How should I read the phone number? I'm not sure how do we related both firebase authentication and cloud firestore.
If you have the information of the phone number you have to provide it to messages(email)
Also Widget names (like all class names) should begin with an uppercase
Something like:
class Messages extends StatefulWidget {
String email;
Messages({required this.email});
#override
_MessagesState createState() => _MessagesState(email: email);
}
class _MessagesState extends State<Messages> {
String email;
_MessagesState({required this.email});
Stream<QuerySnapshot> _messageStream = FirebaseFirestore.instance
.collection('Messages')
.orderBy('time')
.snapshots();
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: _messageStream,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text("something is wrong");
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
itemCount: snapshot.data!.docs.length,
physics: ScrollPhysics(),
shrinkWrap: true,
primary: true,
itemBuilder: (_, index) {
QueryDocumentSnapshot qs = snapshot.data!.docs[index];
DateTime time = qs['time'].toDate();
String message = qs['message'];
String messageEmail = qs['email'];
String messagePhoneNumber = qs['phoneNumber'];
return Padding(
padding: const EdgeInsets.only(top: 8, bottom: 8),
child: Column(
crossAxisAlignment: email == messageEmail
? CrossAxisAlignment.end
: CrossAxisAlignment.start,
children: [
SizedBox(
width: 300,
child: ListTile(
shape: RoundedRectangleBorder(
side: BorderSide(
color: Colors.green,
),
borderRadius: BorderRadius.circular(10),
),
title: Text(
messageEmail == email ? email : messagePhoneNumber,
style: TextStyle(
fontSize: 15,
),
),
subtitle: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
width: 200,
child: Text(
message,
softWrap: true,
style: TextStyle(
fontSize: 15,
),
),
),
Text(
time.hour.toString() + ":" + time.minute.toString(),
)
],
),
),
),
],
),
);
},
);
},
);
}
}
As I said, it depends on your provided data if there is a phoneNumber
Related
Hi guys i'm a begginer in flutter development , i am stuck in a problem,
problem is i want to redirect from selected (homepage.dart file) user in the list to chatroom where i can chat this user but i am not able to do, here is problem i'm facing: Anyone give me solution .
code:-
homepage.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:jobong/model/chatroom_model.dart';
import 'package:jobong/model/signup.dart';
import 'package:jobong/view/chatroom.dart';
class HomePage extends StatefulWidget {
final List<User>? users;
const HomePage({Key? key, this.users}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final auth = FirebaseAuth.instance;
final systemColor =
const SystemUiOverlayStyle(statusBarColor: Colors.transparent);
final User? currentUser = FirebaseAuth.instance.currentUser;
final String uid = FirebaseAuth.instance.currentUser!.uid;
final searchController = TextEditingController();
String search = '';
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(systemColor);
return Scaffold(
backgroundColor: Colors.grey[300],
drawer: const Drawer(
child: DrawerPage(),
),
appBar: AppBar(
titleSpacing: 0,
backgroundColor: Colors.blue[900],
title: Text(
"ChatApp",
style: GoogleFonts.raleway(),
),
actions: [
IconButton(
onPressed: () async {
await FirebaseAuth.instance.signOut();
setState(() {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SignUp()),
);
});
},
icon: const Icon(Icons.logout_outlined),
),
],
),
body: Column(
children: [
const SizedBox(height: 20),
Padding(
padding: const EdgeInsets.all(20.0),
child: TextFormField(
controller: searchController,
onChanged: (String value) {
search = value;
},
decoration: InputDecoration(
hintText: 'Search user',
prefixIcon: const Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
hintStyle: GoogleFonts.raleway(
fontSize: 16, fontWeight: FontWeight.normal),
),
),
),
ElevatedButton(
onPressed: () {
setState(() {});
},
child: Text(
"Search",
style: GoogleFonts.raleway(),
),
),
Expanded(
child: StreamBuilder<QuerySnapshot>(
stream:
FirebaseFirestore.instance.collection('Users')
.where('uid',isNotEqualTo: currentUser!.uid).snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
} else if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot snap = snapshot.data!.docs[index];
final chatRoomModel = ChatRoomModel(
friendName: currentUser!.displayName.toString(),
friendUid: currentUser!.uid,
friendEmail: currentUser!.email.toString(),
);
final targetUserName = chatRoomModel.friendName;
final targetUserEmail = chatRoomModel.friendEmail ;
final targetUserUid = chatRoomModel.friendUid;
if (search.isEmpty) {
return ListTile(
title: Text(snap['name']),
subtitle: Text(snap['email']),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
ChatRoom(
friendName: snap['name'] ,
friendEmail: snap['email'],
friendUid: snap['uid'],
),
),
);
},
leading: Container(
height: 45,
width: 45,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: Colors.white),
child: const Center(
child: Icon(Icons.person),
),
),
);
}
if (snap['name'].toString().toLowerCase().startsWith(search.toLowerCase()) ||
snap['name'].toString().toUpperCase().startsWith(search.toUpperCase())) {
return ListTile(
title: Text(snap['name']),
subtitle: Text(snap['email']),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
ChatRoom(
friendName: snap['name'] ,
friendEmail: snap['email'],
friendUid: snap['uid'],
),
),
);
},
leading: Container(
height: 45,
width: 45,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: Colors.white),
child: const Center(
child: Icon(Icons.person),
),
),
);
}
return Container();
},
);
} else if (snapshot.hasError) {
return const Center(
child: Text("Something went wrong!"),
);
} else {
return Container();
}
},
),
),
],
),
);
}
}
//..............................User Details Fetch here ??..........................................
class DrawerPage extends StatefulWidget {
const DrawerPage({Key? key}) : super(key: key);
#override
State<DrawerPage> createState() => _DrawerPageState();
}
class _DrawerPageState extends State<DrawerPage> {
#override
void initState() {
super.initState();
getUserData();
}
String name = '';
String email = '';
String password = '';
final currentUser = FirebaseAuth.instance.currentUser;
Future<void> getUserData() async {
final user = await FirebaseFirestore.instance
.collection('Users')
.doc(currentUser!.uid)
.get();
setState(() {
name = user.data()!['name'];
email = user.data()!['email'];
password = user.data()!['password'];
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Name: $name',
style: GoogleFonts.raleway(
fontWeight: FontWeight.normal, fontSize: 16),
),
const SizedBox(height: 10),
Text(
'Email: $email',
style: GoogleFonts.raleway(
fontWeight: FontWeight.normal, fontSize: 16),
),
const SizedBox(height: 10),
Text(
'Password: $password',
style: GoogleFonts.raleway(
fontWeight: FontWeight.normal, fontSize: 16),
),
],
),
),
);
}
}
second chatroom.dart file =================================
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:jobong/model/chatroom_model.dart';
class ChatRoom extends StatefulWidget {
final ChatRoomModel friendName;
final ChatRoomModel friendUid;
final ChatRoomModel friendEmail;
const ChatRoom({
Key? key,
required this.friendName, required this.friendUid ,
required this.friendEmail
}) : super(key: key);
#override
State<ChatRoom> createState() => _ChatRoomState();
}
class _ChatRoomState extends State<ChatRoom> {
void showToast(String message) {
Fluttertoast.showToast(
msg: message,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0
);
}
final email = FirebaseAuth.instance.currentUser!.email;
void sendMessage() async {
try{
await FirebaseFirestore.instance.collection('chats')
.doc(uid).collection('messages').doc()
.set({
'sender':email,
'receiver':widget.friendUid,
'message':_message.text.trim(),
'time':FieldValue.serverTimestamp(),
});
}on FirebaseAuthException catch (e) {
showToast('${e.message}');
}
}
final bool isMe = false;
final _message = TextEditingController();
final uid = FirebaseAuth.instance.currentUser!.uid;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Column(
children: [
Text(
widget.friendName.toString(),
style: GoogleFonts.lato(),
),
Text(
widget.friendEmail.toString(),
style: GoogleFonts.lato(),
),
],
),
),
body: Column(
children: [
Expanded(
child: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('chats')
.doc(uid)
.collection('messages')
.doc()
.snapshots(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(color: Colors.blue),
);
} else {
return ListView.builder(
shrinkWrap: true,
reverse: true,
itemCount: snapshot.data!.doc.length,
itemBuilder: (BuildContext context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: isMe
? CrossAxisAlignment.end
: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.all(15),
decoration: BoxDecoration(
borderRadius: isMe
? BorderRadius.circular(15.0)
: BorderRadius.circular(15.0),
color: isMe
? Colors.green[500]
: Colors.red[500]),
child: Center(
child: Text(_message.toString(),
style: isMe
? GoogleFonts.lato(color: Colors.black)
: GoogleFonts.lato(
color: Colors.white)),
),
),
],
),
);
},
);
}
},
),
),
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 8.0),
child: Container(
height: 60,
width: double.infinity,
decoration: BoxDecoration(
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(25),
bottomRight: Radius.circular(25),
topLeft: Radius.circular(10),
topRight: Radius.circular(10),
),
color: Colors.grey[900],
),
child: TextFormField(
controller: _message,
style: GoogleFonts.lato(color: Colors.white),
decoration: InputDecoration(
hintText: 'send a message ...',
hintStyle: GoogleFonts.lato(color: Colors.white),
border: InputBorder.none,
prefixIcon: const Icon(Icons.file_present_rounded,
color: Colors.white),
suffixIcon: GestureDetector(
onTap:sendMessage,
child: const Icon(Icons.near_me, color: Colors.white),
),
),
),
),
),
],
),
);
}
}
class that i have the variable in
...
class _ActivitiesParticipantsState extends State<ActivitiesParticipants> {
final activityController = TextEditingController();
final user = FirebaseAuth.instance.currentUser!;
//Activities participants
List<String> docIDs = [];
//get docIDS
Future getDocId() async {
await FirebaseFirestore.instance
.collection(
activityController.text.trim(),
)
.get()
.then(
(snapshot) => snapshot.docs.forEach(
(element) {
docIDs.add(element.reference.id);
},
),
);
//stuff
}
#override
void dispose() {
activityController.dispose();
super.dispose();
}
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
controller: activityController,
decoration: InputDecoration(
labelText: 'e',
border: InputBorder.none,
),
),
GestureDetector(
onTap: () async {
setState(
() {
getDocId();
},
);
},
child: Container(
padding: EdgeInsets.all(
20,
),
decoration: BoxDecoration(
color: Colors.deepPurple,
borderRadius: BorderRadius.circular(12),
),
child: Center(
child: Text(
'Test',
style: TextStyle(
color: Colors.white,
fontFamily: 'Quicksand',
fontWeight: FontWeight.w600,
fontSize: 18,
),
),
),
),
),
Expanded(
child: FutureBuilder(
builder: (context, snapshot) {
return ListView.builder(
itemCount: wee(),
//docIDs.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 15),
child: ListTile(
dense: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8)),
tileColor: Color.fromARGB(255, 235, 235, 235),
title: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10, vertical: 20),
child: Column(
children: [
SizedBox(
height: 5,
),
Align(
alignment: Alignment.centerLeft,
child: Title(
color: Colors.black,
child: InterestedName(
documentID: docIDs[index]),
),
),
SizedBox(
height: 20,
),
],
),
),
),
);
},
);
},
),
),
],
),
),
),
);
}
}
...
How do I get the variable "activityController" to another class?
This other class is used to get Text to fill the ListTile
class that I want to get the variable
final String documentID;
InterestedName({required this.documentID});
#override
Widget build(BuildContext context) {
// get the collection
CollectionReference users = FirebaseFirestore.instance.collection('Project Koalas [test]');
return FutureBuilder<DocumentSnapshot>(
future: users.doc(documentID).get(),
builder: ((context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data =
snapshot.data!.data() as Map<String, dynamic>;
return Text(
'Name: ${data['name']}',
style: TextStyle(
fontSize: 16,
fontFamily: 'Quicksand',
fontWeight: FontWeight.w600),
);
}
return Text('loading...');
}),
);
}
}
I would like to get the variable to be able to get the collection name that I want to take data from, as the collection I would like to take from is dependent on the user's choice.
If there is any way else to somehow fill the List tile in the same class, please let me know how.
Any help appreciated!
I needed to insert a TextField to search/filter records, but I don't know what's going on.
When I click on the "Cães" option of the BottomNavigationBar, on main.dart,
I only get a CircularProgressIndicator and the data does show up.
Have any of you experienced this problem?
Does anyone know why my Listview doesn't show up?
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:ssk_final/addeditpage.dart';
//import 'package:flutter_localizations/flutter_localizations.dart';
List<dynamic> list = [];
class CaesPage extends StatefulWidget {
// CaesPage({Key key}) : super(key: key);
#override
_CaesPageState createState() => _CaesPageState();
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text("Cadastro de Cães"),
),
);
}
}
class _CaesPageState extends State<CaesPage> {
String searchString = "";
Future<List<Caes>> caes;
Future getData() async {
var url = 'http://.../api2.php?opcao=read';
var response = await http.get(Uri.parse(url));
return json.decode(response.body);
}
/*
Future _showMyDialog(id, nome) async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button
builder: (BuildContext context) {
return AlertDialog(
title: Text('Exclusão'),
content: SingleChildScrollView(
child: Column(
children: <Widget>[
Text('Confirma a exclusão de ' + nome + '?'),
],
),
),
actions: <Widget>[
TextButton(
child: Text('Confirma'),
onPressed: () {
setState(() {
var url = 'http://.../api.php?opt=delete';
http.post(Uri.parse(url), body: {
'id': id,
});
});
Navigator.pop(context, true);
},
),
TextButton(
child: Text('Cancelar'),
onPressed: () {
Navigator.pop(context);
},
),
],
);
},
);
}
*/
#override
void initState() {
super.initState();
caes = fetchCaes();
}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
backgroundColor: Color.fromRGBO(1, 87, 155, 1),
focusColor: Colors.blue,
foregroundColor: Colors.white,
hoverColor: Colors.green,
splashColor: Colors.tealAccent,
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddEditPage(),
),
);
debugPrint('Clicked FloatingActionButton Button');
},
),
body: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Divider(),
//SizedBox(height: 10),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 15.0),
child: TextField(
onChanged: (value) {
setState(() {
searchString = value.toLowerCase();
});
},
decoration: const InputDecoration(
//contentPadding: EdgeInsets.symmetric(vertical: 10),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 1.0),
borderRadius: BorderRadius.all(Radius.circular(25.0))),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 1.0),
borderRadius: BorderRadius.all(Radius.circular(25.0)),
),
labelText: 'Pesquisa',
suffixIcon: Icon(Icons.search))),
),
SizedBox(height: 10),
Expanded(
child: FutureBuilder<List<Caes>>(
builder: (context, snapshot) {
if (snapshot.hasData) {
return Center(
child: ListView.separated(
padding: const EdgeInsets.all(8),
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return snapshot.data[index].nome
.toLowerCase()
.contains(searchString)
? Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new InkWell(
onTap: () {
print(index);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddEditPage(
caes: snapshot.data,
index: index,
),
),
);
},
child: new Container(
child: Column(
children: [
Text(
(snapshot.data[index].nome),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold),
),
Text(
('${snapshot.data[index].microchip}'),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 13,
),
),
Text(
('${snapshot.data[index].pedigree}'),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 13,
),
),
Text(
(snapshot
.data[index].data_nascimento),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 13,
),
),
Text(
(snapshot.data[index].sexo),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 13,
),
),
Text(
(snapshot.data[index].castrado),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 13,
),
),
],
),
),
),
])
: Container();
},
separatorBuilder: (BuildContext context, int index) {
return snapshot.data[index].nome
.toLowerCase()
.contains(searchString)
? Divider()
: Container();
},
),
);
} else if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
}
return Center(
child: CircularProgressIndicator(),
);
},
// future: list,
),
),
],
),
);
}
}
class Caes {
final int id;
final String nome;
final int microchip;
final int pedigree;
final String data_nascimento;
final String castrado;
final String sexo;
Caes({
this.id,
this.nome,
this.microchip,
this.pedigree,
this.data_nascimento,
this.castrado,
this.sexo,
});
factory Caes.fromJson(Map<String, dynamic> json) {
return Caes(
id: json['id'],
nome: json['nome'],
microchip: json['microchip'],
pedigree: json['pedigree'],
data_nascimento: json['data_nascimento'],
castrado: json['castrado'],
sexo: json['sexo'],
);
}
}
class Titulos {
Titulos({this.data, this.titulo, this.exposicao});
// non-nullable - assuming the score field is always present
final String data;
final String titulo;
final String exposicao;
factory Titulos.fromJson(Map<String, dynamic> json) {
final data = json['data'] as String;
final titulo = json['titulo'] as String;
final exposicao = json['exposicao'] as String;
return Titulos(data: data, titulo: titulo, exposicao: exposicao);
}
Map<String, dynamic> toJson() {
return {
'data': data,
'titulo': titulo,
'exposicao': exposicao,
};
}
}
Future<List<Caes>> fetchCaes() async {
final response = await http.get(Uri.parse('http://.../api.php?opt=read'));
if (response.statusCode == 200) {
var caesJson = jsonDecode(response.body) as List;
return caesJson.map((caes) => Caes.fromJson(caes)).toList();
} else {
throw Exception('Failed to load Caes');
}
}
Screen
I cant really provide an answer in your list view cause it needs more files to run for me. However I can provide you a nice way to search in a list for items and update it with a text field. You can copy and run the code in the main of a test project to see how it is working.
import 'dart:async';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final StreamController<List<String>> _exercisesStreamController =
StreamController<List<String>>();
late Stream<List<String>> _exercisesStream;
final List<String> _exercises = [
"Running",
"Swimming",
"Football",
"Basketball",
"Volleyball",
"Karate",
"Ski",
"Snowboard",
"Baseball",
"Running1",
"Swimming1",
"Football1",
"Basketball1",
"Volleyball1",
"Karate1",
"Ski1",
"Snowboard1",
"Baseball1",
"Running2",
"Swimming2",
"Football2",
"Basketball2",
"Volleyball2",
"Karate2",
"Ski2",
"Snowboard2",
"Baseball2",
"Running3",
"Swimming3",
"Football3",
"Basketball3",
"Volleyball3",
"Karate3",
"Ski3",
"Snowboard3",
"Baseball3",
];
#override
void initState() {
super.initState();
_exercisesStreamController.sink.add(_exercises);
_exercisesStream = _exercisesStreamController.stream.asBroadcastStream();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(),
body: Padding(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Column(
children: [
TextFormField(
maxLines: 1,
style: TextStyle(color: Colors.white),
onChanged: (String value) async {
List<String> temp = List.from(_exercises);
temp.removeWhere((element) =>
!element.toLowerCase().contains(value.toLowerCase()));
_exercisesStreamController.sink.add(temp);
},
decoration: InputDecoration(
prefixIcon: Icon(
Icons.search,
color: Colors.white,
),
border: OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.circular(15.0),
),
contentPadding: EdgeInsets.only(left: 15),
filled: true,
fillColor: Colors.blueGrey,
hintText: "search",
hintStyle: TextStyle(
color: Colors.white,
),
),
),
_listViewWidget()
],
),
),
);
}
Widget _listViewWidget() {
return Expanded(
child: StreamBuilder<List<String>>(
initialData: [],
stream: _exercisesStream,
builder: (context, snapshot) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: Colors.blueGrey,
borderRadius: BorderRadius.all(
Radius.circular(15),
),
),
padding: EdgeInsets.all(15),
margin: EdgeInsets.symmetric(vertical: 10),
child: Center(
child: Text(
snapshot.data![index],
style: TextStyle(color: Colors.white),
),
),
);
});
},
),
);
}
}
If you need further instructions i am happy to help.
I want to update my Collection with an NumberPicker in a Alert Dialog. I do not get any errors in code or from the emulator. When i press the button to update the code the terminal do not give any errors. Everything looks fine but for some reason i do not work. When you need more Information just leave a comment with what you excactly need. :)
import 'package:flutter/material.dart';
import 'package:numberpicker/numberpicker.dart';
import 'package:percent_indicator/circular_percent_indicator.dart';
import 'package:testapp/services/Services.dart';
import 'models/Goals.dart';
class Statistics extends StatefulWidget {
#override
_StatisticsState createState() => _StatisticsState();
}
class _StatisticsState extends State<Statistics> {
int _currentFirstValue = 1;
int totalFirst;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: 260,
child: StreamBuilder(
stream: FirestoreService().getGoals(),
builder: (context, AsyncSnapshot<List<Goal>> snapshot) {
if (snapshot.hasError || !snapshot.hasData) {
return Center(child: CircularProgressIndicator(
backgroundColor: Color(0XFF1954A1),
));
}
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 1,
itemBuilder: (BuildContext context, int index) {
// ignore: missing_return
Goal goal = snapshot.data[index];
return Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
margin: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
height: 230,
width: 350,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(10.0)),
boxShadow: [
BoxShadow(
color: Colors.grey[300],
offset: const Offset(0.5, 1),
blurRadius: 4.0,
spreadRadius: 0.1,
),
]),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Text('WeekGoals', style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.w500,
),),
SizedBox(width: 100),
SizedBox(
height: 20,
width: 87,
child: FlatButton(
child: Text('edit', style: TextStyle(
fontSize: 17,
color: Colors.yellow[700]
),),
onPressed: () {
return showDialog(
context: context,
barrierDismissible: true,
builder: (context) => AlertDialog(
content: Column(
children: <Widget>[
Text('weekly goals'),
NumberPicker.integer(
initialValue: _currentFirstValue,
minValue: 1,
maxValue: 100,
onChanged: (newGoal) => setState(() => {
_currentFirstValue = newGoal,
totalFirst = _currentFirstValue,
})
),
Row(
children: <Widget>[
RaisedButton(
child: Text('edit goals'),
onPressed: () async {
Goal goal = Goal(
weekActivityGoal: totalFirst,
);
await FirestoreService().updateGoal(goal);
Navigator.pop(context, false);
},
),
FlatButton(
child: Text('Close'),
onPressed: () {
Navigator.pop(context, false);
},
)
],
)
],
),
)
);
},
),
)
],
),
SizedBox(height: 10),
Row(
children: <Widget>[
Container(
padding: EdgeInsets.symmetric(horizontal: 17.5),
child: CircularPercentIndicator(
header: Text('activitys', style: TextStyle(
fontSize: 17,
),),
radius: 130,
progressColor: Colors.red,
lineWidth: 8,
backgroundColor: Colors.grey[200],
percent: goal.weekActivity*100/goal.weekActivityGoal,
center: Text('${goal.weekActivity}/${goal.weekActivityGoal}'),
),
),
],
),
],
),
),
],
);
});
}),
),
);
}
}
Here this has been helping a lot of people try i out might help you too.
StreamBuilder(
stream: Firestore.instance.collection('Hearings').snapshots(),
builder: (context, snapshot) {
if (snapshot.hasError) return Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('Select lot');
case ConnectionState.waiting:
return Text('Awaiting bids...');
case ConnectionState.active:
{
print('active');
return Text('${snapshot.data}');
}
case ConnectionState.done:
{
print('Done');
return _buildList(context, snapshot.data);
}
}
return null;
}),
));
}
Widget _buildList(BuildContext context, List<DocumentSnapshot> snapshot) {
return ListView(
padding: const EdgeInsets.only(top: 20.0),
children: snapshot.map((data) => _buildListItem(context, data)).toList(),
);
}
Widget _buildListItem(BuildContext context, DocumentSnapshot data) {
final record = Record.fromSnapshot(data);
return Padding(
key: ValueKey(record.name),
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(5.0),
),
child: ListTile(
title: Text(record.name),
trailing: Text(record.votes.toString()),
onTap: () => Firestore.instance.runTransaction((transaction) async {
final freshSnapshot = await transaction.get(record.reference);
final fresh = Record.fromSnapshot(freshSnapshot);
await transaction
.update(record.reference, {'votes': fresh.votes + 1});
}),
),
),
);
}
}
class Record {
final String name;
final int votes;
final DocumentReference reference;
Record.fromMap(Map<String, dynamic> map, {this.reference})
: assert(map['name'] != null),
assert(map['votes'] != null),
name = map['name'],
votes = map['votes'];
Record.fromSnapshot(DocumentSnapshot snapshot)
: this.fromMap(snapshot.data, reference: snapshot.reference);
#override
String toString() => "Record<$name:$votes>";
}
This is where the link this info came from.
I am newbie into flutter. I have created a Navigation Drawer and it has multiple selection. In each seletion of drawer i have screen which consists of List of Data coming from server.
Now i want add Search Icon to Navigation Bar with Editfield to filter the list detials and update on the screen of any selected item from Navigation Drawer.
Please help me out.. and will be appreciated.
NavigationDrawer Screen
import 'package:flutter/material.dart';
import 'package:innovation_bridge/fragments/AnnouncementsScreen.dart';
import 'package:innovation_bridge/fragments/AttendeesScreen.dart';
import 'package:innovation_bridge/fragments/BookmarksScreen.dart';
import 'package:innovation_bridge/fragments/ExibitorsScreen.dart';
import 'package:innovation_bridge/fragments/HomeScreen.dart';
import 'package:innovation_bridge/fragments/InnovationsScreen.dart';
import 'package:innovation_bridge/fragments/MeetingsScreen.dart';
import 'package:innovation_bridge/fragments/PrivacyPolicyScreen.dart';
import 'package:innovation_bridge/fragments/ProgramScreen.dart';
import 'package:innovation_bridge/fragments/SpeedSessionScreen.dart';
import 'package:innovation_bridge/fragments/TermsConditionsScreen.dart';
import 'package:innovation_bridge/utils/Utils.dart';
class HomeDashboard extends StatefulWidget {
final drawerItems = [
new DrawerItem("Dashboard"),
new DrawerItem("Program"),
new DrawerItem("Exibitors"),
new DrawerItem("Innovations"),
new DrawerItem("Attendees"),
new DrawerItem("Speed Session"),
new DrawerItem("Bookmarks"),
new DrawerItem("Announcements"),
new DrawerItem("Privacy Policy"),
new DrawerItem("Terms & Conditions"),
new DrawerItem("Logout")
];
#override
_HomeDashboardState createState() => _HomeDashboardState();
}
class _HomeDashboardState extends State<HomeDashboard> {
int _selectedDrawerIndex = 0;
//Let's use a switch statement to return the Fragment for a selected item
_getDrawerFragment(int pos) {
switch (pos) {
case 0:
return new HomeScreen();
case 1:
return new ProgramScreen();
case 2:
return new ExibitorsScreen();
case 3:
return new InnovationsScreen();
case 4:
return new AttendeesScreen();
case 5:
return new SpeedSessionScreen();
case 6:
return new BookmarksScreen();
case 7:
return new AnnouncementsScreen();
case 8:
return new PrivacyPolicyScreen();
case 9:
return new TermsConditionsScreen();
default:
return new Text("Error");
}
}
//Let's update the selectedDrawerItemIndex the close the drawer
_onSelectItem(int index) {
setState(() => _selectedDrawerIndex = index);
//we close the drawer
Navigator.of(context).pop();
}
#override
Widget build(BuildContext context) {
List<Widget> drawerOptions = [];
//Let's create drawer list items. Each will have an icon and text
for (var i = 0; i < widget.drawerItems.length; i++) {
var d = widget.drawerItems[i];
drawerOptions.add(
ListTile(
title: new Text(d.title),
selected: i == _selectedDrawerIndex,
onTap: () => _onSelectItem(i),
)
);
}
//Let's scaffold our homepage
return new Scaffold(
appBar: new AppBar(
// We will dynamically display title of selected page
title: new Text(widget.drawerItems[_selectedDrawerIndex].title),
actions: <Widget>[
IconButton(
tooltip: 'Search',
icon: const Icon(Icons.search),
onPressed: (){
},
),
IconButton(
tooltip: 'Search',
icon: const Icon(Icons.filter_list),
onPressed: (){
},
)
],
),
// Let's register our Drawer to the Scaffold
drawer: SafeArea(
child: new Drawer(
child: new Column(
children: <Widget>[
Container(
color: Utils.hexToColor("#F24A1C"),
height: MediaQuery.of(context).size.height / 10,
width: MediaQuery.of(context).size.width,
child: Padding(
padding: EdgeInsets.only(left: 20),
child: Align(
alignment: Alignment.centerLeft,
child: Text('Menu', style: TextStyle(
fontSize: 18,
color: Colors.white
))
),
),
),
new Column(children: drawerOptions)
],
),
),
),
body: _getDrawerFragment(_selectedDrawerIndex),
);
}
}
//Let's define a DrawerItem data object
class DrawerItem {
String title;
IconData icon;
DrawerItem(this.title);
}
Here, in NavigationDrawer Screen, onclick of search icon TextField should enable and in List Screen filter should happen when user starting typing.
List Screen
import 'dart:math';
import 'package:connectivity/connectivity.dart';
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:innovation_bridge/detailScreens/ProgramDetailScreen.dart';
import 'package:innovation_bridge/dialogs/CommonMessageDialog.dart';
import 'package:innovation_bridge/utils/Utils.dart';
import 'package:table_calendar/table_calendar.dart';
class ProgramScreen extends StatefulWidget {
#override
_ProgramScreenState createState() => _ProgramScreenState();
}
class _ProgramScreenState extends State<ProgramScreen> {
var meteors = [
"Tunguska",
"Crab Pulsar",
"Geminga",
"Calvera",
"Vela X-1",
];
final String uri = 'https://jsonplaceholder.typicode.com/users';
Future<List<Users>> _fetchUsers() async {
print('## inside fetch user == ');
var response = await http.get(Uri.encodeFull(uri));
if (response.statusCode == 200) {
final items = json.decode(response.body).cast<Map<String, dynamic>>();
List<Users> listOfUsers = items.map<Users>((json) {
return Users.fromJson(json);
}).toList();
return listOfUsers;
} else {
throw Exception('Failed to load internet');
}
}
CalendarController _calendarController;
#override
void initState() {
super.initState();
_calendarController = CalendarController();
}
#override
void dispose() {
_calendarController.dispose();
super.dispose();
}
void _onDaySelected(DateTime day, List events) {
print('## CALLBACK: _onDaySelected' +day.toIso8601String());
setState(() {
});
}
void _onVisibleDaysChanged(DateTime first, DateTime last, CalendarFormat format) {
print('CALLBACK: _onVisibleDaysChanged');
}
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Container(
color: Colors.grey[350],
child: _buildTableCalendar(),
),
Expanded(
child: StreamBuilder(
stream: Connectivity().onConnectivityChanged,
builder: (BuildContext context, AsyncSnapshot<ConnectivityResult> snapShot){
if (!snapShot.hasData) return Center(child: CircularProgressIndicator());
var result = snapShot.data;
switch (result) {
case ConnectivityResult.none:
print("no net");
return Center(child: Text("No Internet Connection! none "));
case ConnectivityResult.mobile:
return _listDetials();
case ConnectivityResult.wifi:
print("yes net");
return _listDetials();
default:
return Center(child: Text("No Internet Connection! default"));
}
},
),
)
],
),
);
}
FutureBuilder _listDetials(){
return FutureBuilder(
future: _fetchUsers(),
builder: (context, snapshot){
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
}
if (snapshot.hasError){
return Text('${snapshot.error}');
}
else{
return ListView.builder(
itemCount: 5,
scrollDirection: Axis.vertical,
itemBuilder: (BuildContext context, int index){
return Padding(
padding: EdgeInsets.fromLTRB(15.0, 10.0, 15.0, 4),
child: Container(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
GestureDetector(
onTap: (){
Navigator.push(context, MaterialPageRoute(
builder: (context) => ProgramDetailScreen()
));
},
child: Text('Program Activity Title', style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w400
)),
),
Padding(padding: EdgeInsets.only(top: 6)),
Row(
children: <Widget>[
Expanded(
flex: 2,
child: Text('Location Name', style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: Colors.blueAccent,
)),
),
Expanded(
flex: 2,
child: Align(
alignment: Alignment.centerRight,
child: Text('Start time - End time', style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: Colors.blueAccent,
))
),
)
],
),
Padding(padding: EdgeInsets.only(top: 6)),
Text('Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w400,
),),
ExpansionTile(
title: Text(''),
trailing: Icon(
Icons.face,
size: 36.0,
),
children: <Widget>[
GridView.count(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
crossAxisCount: 3,
crossAxisSpacing: 5.0,
mainAxisSpacing: 5,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 4),
children: <Widget>[
GestureDetector(
onTap: (){
},
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 0.9
),
borderRadius: BorderRadius.all(
Radius.circular(5.0) // <--- border radius here
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(6, 5, 0, 0),
child: Text('Session Title',
softWrap: true,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.bold
)),
),
Padding(
padding: EdgeInsets.fromLTRB(6, 1, 0, 0),
child: Text('10:00 - 10:30',
softWrap: true,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 9
)),
),
Padding(
padding: EdgeInsets.fromLTRB(6, 1, 0, 0),
child: Text('Hall B',
softWrap: true,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 9
)),
),
],
),
),
)
]),
],
// onExpansionChanged: (bool expanding) => setState(() => this.isExpanded = expanding),
)
],
),
),
);
},
);
}
},
);
}
// Simple TableCalendar configuration (using Styles)
Widget _buildTableCalendar() {
return TableCalendar(
calendarController: _calendarController,
startingDayOfWeek: StartingDayOfWeek.monday,
headerVisible: true,
initialCalendarFormat: CalendarFormat.week, availableCalendarFormats: const { CalendarFormat.week: 'Week', },
calendarStyle: CalendarStyle(
selectedColor: Colors.deepOrange[400],
todayColor: Colors.deepOrange[200],
markersColor: Colors.brown[700],
outsideDaysVisible: true
),
headerStyle: HeaderStyle(
formatButtonTextStyle: TextStyle().copyWith(color: Colors.white, fontSize: 15.0),
formatButtonDecoration: BoxDecoration(
color: Colors.deepOrange[400],
borderRadius: BorderRadius.circular(10.0),
),
),
onDaySelected: _onDaySelected,
onVisibleDaysChanged: _onVisibleDaysChanged,
);
}
}
Widget createGridView(BuildContext context, List<String> cosmicBodies) {
//I will shuffle my data
cosmicBodies.shuffle();
// Then build my GridView and return it
return new GridView.builder(
itemCount: cosmicBodies.length,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, mainAxisSpacing: 15.0),
itemBuilder: (BuildContext context, int index) {
return new GestureDetector(
child: new Card(
elevation: 5.0,
child: new Container(
alignment: Alignment.centerLeft,
margin: new EdgeInsets.only(top: 10.0, bottom: 10.0, left: 10.0),
child: new Text(cosmicBodies[index]),
),
),
);
});
}
class Users {
int id;
String name;
String username;
String email;
Users({
this.id,
this.name,
this.username,
this.email,
});
factory Users.fromJson(Map<String, dynamic> json) {
return Users(
id: json['id'],
name: json['name'],
email: json['email'],
username: json['username'],
);
}
}