Flutter: Why doesn't this streambuilder work? - firebase

So, I have just began working on a flutter project and am quite new to the whole experience. I just managed to integrate firebase firestore into my project by creating a few buttons that update, remove, and add documents. However, I also wanted to add a Streambuilder with the list that is being updated on the same page. I tried each task seperately, and they all work fine and dandy, however when I combine the two, the streambuilder shows no data and the buttons won't click. How do I incorporate both buttons and a Streambuilder in one body, or one page? What can I do to combine both of these elements onto one page in the widget build method? Again, the two elements seem to be working okay by themselves if I use the Streambuilder in the body and not a children widget tag.
A picture of what the not working page looks like. Notice how the buttons are not being selected when hovered over and the streambuilder is loading infinitely: https://i.stack.imgur.com/XnfVJ.png
Firebase data screenshot (security settings allow users to access the data): https://i.stack.imgur.com/oSsOL.png
Here is my code for main.dart:
final databaseReference = Firestore.instance;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('FireStore Demo'),
),
body: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
RaisedButton(
child: Text('Create Record'),
onPressed: () {
createRecord();
},
),
RaisedButton(
child: Text('View Record'),
onPressed: () {
getData();
},
),
RaisedButton(
child: Text('Update Record'),
onPressed: () {
updateData();
},
),
RaisedButton(
child: Text('Delete Record'),
onPressed: () {
deleteData();
},
),
StreamBuilder<QuerySnapshot>(
stream: databaseReference.collection('books').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return new Text('Loading...');
return new ListView(
children: snapshot.data.documents.map((DocumentSnapshot document) {
return new ListTile(
title: new Text(document['title']),
subtitle: new Text('${document['description']} description'),
);
}).toList(),
);
},
)
],
)),
//center
);
}
void createRecord() async {
await databaseReference.collection("books")
.document("1")
.setData({
'title': 'Mastering Flutter',
'description': 'Programming Guide for Dart'
});
DocumentReference ref = await databaseReference.collection("books")
.add({
'title': 'Flutter in Action',
'description': 'Complete Programming Guide to learn Flutter'
});
print(ref.documentID);
}
void getData() {
databaseReference
.collection("books")
.getDocuments()
.then((QuerySnapshot snapshot) {
snapshot.documents.forEach((f) => print('${f.data}}'));
});
}
void updateData() {
try {
databaseReference
.collection('books')
.document('1')
.updateData({'description': 'Head First Flutter'});
} catch (e) {
print(e.toString());
}
}
void deleteData() {
try {
databaseReference
.collection('books')
.document('1')
.delete();
} catch (e) {
print(e.toString());
}
}
}

Still don't know why the code above didn't work, but putting the streambuilder within an Expanded block seemed to do the trick! Both widgets are working fine as of now.
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
void main() => runApp(new MediaQuery(
data: new MediaQueryData(), child: new MaterialApp(home: new MyApp())));
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
RaisedButton(
child: Text('Create Record'),
onPressed: () {
createRecord();
},
),
RaisedButton(
child: Text('View Record'),
onPressed: () {
getData();
},
),
RaisedButton(
child: Text('Update Record'),
onPressed: () {
updateData();
},
),
RaisedButton(
child: Text('Delete Record'),
onPressed: () {
deleteData();
},
),
new Expanded(child:
new StreamBuilder<QuerySnapshot>(
stream: databaseReference.collection('books').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return new Text('Loading...');
return new ListView(
children: snapshot.data.documents.map((DocumentSnapshot document) {
return new ListTile(
title: new Text(document['title']),
subtitle: new Text('${document['description']} description'),
);
}).toList(),
);
},
)
)
],
)),
//center
);

Related

Could someone tell me how to turn this into a listview.builder and still have it connected to firebase? btw the name of my collection is 'groceries'

Currently it is a listview, I know how to normally create a listview.builder but I don't know how to connect it to firebase. Im talking about the streambuilder and context and all that stuff. Really appreciate any help, Im new to flutter so sorry if this is an obvious/dumb question.
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(FireApp());
}
class FireApp extends StatefulWidget {
#override
_FireAppState createState() => _FireAppState();
}
class _FireAppState extends State<FireApp> {
final TextController = TextEditingController();
bool isChecked = false;
#override
Widget build(BuildContext context) {
CollectionReference groceries =
FirebaseFirestore.instance.collection('groceries');
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: TextField(
controller: TextController,
),
),
body: Center(
child: StreamBuilder(
stream: groceries.orderBy('name').snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
return ListView(
children: snapshot.data!.docs.map((grocery) {
return Center(
child: Row(
children: [
Container(color: Colors.red,height: 50,child: Text(grocery['name'])),
Checkbox(
materialTapTargetSize: MaterialTapTargetSize.padded,
value: isChecked,
activeColor: Colors.black,
checkColor: Colors.greenAccent,
onChanged: (bool) {
setState(() {
isChecked = !isChecked;
});
}
)],
),
);
}).toList(),
);
},
),
),
floatingActionButton: FloatingActionButton(onPressed: () {
groceries.add({
'name': TextController.text,
});
},),
),
);
}
}
StreamBuilder and listview.builder sample code given below
StreamBuilder<QuerySnapshot<Map<String, dynamic>>>(
stream: groceries.orderBy('name').snapshots(),
builder: (context,
AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> snapshot) {
// your list of groceries
List groceriesList =
snapshot.data.docs.map((e) => e.data()).toList();
return ListView.builder(
itemCount: groceriesList.length,
itemBuilder: (context, i) {
// build your widget here.
return Center(
child: Row(
children: [
Container(
color: Colors.red,
height: 50,
child: Text(groceriesList[i]['name']),
),
Checkbox(
materialTapTargetSize: MaterialTapTargetSize.padded,
value: isChecked,
activeColor: Colors.black,
checkColor: Colors.greenAccent,
onChanged: (bool) {
setState(() => isChecked = !isChecked);
},
)
],
),
);
},
);
},
),

How to get matched user list show in search result [Flutter]

I'm using package search_page
I want to show user name when searching their name like this example
Here is my Firestore, I have user named Test User One and Test User Two
Here is my code for FloatingActionButton( )
FloatingActionButton(
onPressed: () => showSearch(
context: context,
delegate: ChatSearch(),
),
child: Icon(Icons.chat),
),
Here is my code for ChatSearch( )
class ChatSearch extends SearchDelegate {
FirebaseFirestore _fires = FirebaseFirestore.instance;
Future<QuerySnapshot> getUserInfo() async {
return await _fires.collection("Students").where("displayName", isEqualTo: query).get();
}
...
#override
Widget buildResults(BuildContext context) {
return Column(
children: [
FutureBuilder(
future: getUserInfo(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('No user found.');
}
else if (snapshot.connectionState == ConnectionState.waiting) {
return Text('Loading ...');
}
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.docs.length,
itemBuilder: (BuildContext context, int index) {
var result = snapshot.data.docs[index];
return ListTile(
title: Text(result["displayName"]),
subtitle: Text(result["society"]),
leading: CircleAvatar(backgroundImage: NetworkImage(result["photoUrl"]),),
);
},
);
}),
],
);
}
}
Here is my screenshot
How can I get the query (all user name matched with search) instead of isEqualTo?
For example, when I search Test User, it will appear Test User One and Test User Two
Really appreciate if anyone can help me or provide me some direction. Thanks.
It's easy no need to use the plugin here is the code
//it's the code to search for user for name
static Future<QuerySnapshot> getUserInfo(String name) {
Future<QuerySnapshot> users =
usersRef.where('name', isGreaterThanOrEqualTo: name).getDocuments();
return users;
}
and this are some values
TextEditingController _searchController = TextEditingController();
Future<QuerySnapshot> _users;
String _searchText = '';
and it's the search ui code
#override
Widget build(BuildContext context) {
String _currentUserId = Provider.of<UserData>(context).currentUserId;
void _clearSearch() {
WidgetsBinding.instance
.addPostFrameCallback((_) => _searchController.clear());
setState(() {
_users = null;
_searchText = '';
});
}
return Scaffold(
appBar: AppBar(
title: TextField(
controller: _searchController,
decoration: InputDecoration(
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
contentPadding: const EdgeInsets.symmetric(vertical: 15.0),
border: InputBorder.none,
hintText: 'Search for a user...',
prefixIcon: Icon(
Icons.search,
color: Theme.of(context).accentColor.withOpacity(0.6),
size: 30.0,
),
suffixIcon: _searchText.trim().isEmpty
? null
: IconButton(
color: Theme.of(context).accentColor.withOpacity(0.6),
icon: Icon(Icons.clear),
onPressed: _clearSearch,
),
// filled: true,
),
onChanged: (value) {
setState(() {
_searchText = value;
});
},
onSubmitted: (input) {
if (input.trim().isNotEmpty) {
setState(() {
_users = DatabaseService.searchUsers(input);
});
}
},
),
),
body: _users == null
? Center(child: Text('Search for users'))
: FutureBuilder(
future: _users,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
if (snapshot.data.documents.length == 0) {
return Center(
child: Text('No Users found! Please try again.'),
);
}
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index) {
//User user = User.fromDoc(snapshot.data.documents[index]);
// Prevent current user to send messages to himself
return null;
// (widget.searchFrom != SearchFrom.homeScreen &&
// user.id == _currentUserId)
// ? SizedBox.shrink()
// : _buildUserTile(user);
});
},
),
);
}
and this is the user tile
ListTile _buildUserTile(User user) {
return ListTile(
leading: CircleAvatar(
backgroundColor: Colors.grey,
radius: 20.0,
backgroundImage: user.profileImageUrl.isEmpty
? AssetImage(placeHolderImageRef)
: CachedNetworkImageProvider(user.profileImageUrl),
),
title: Row(
children: [Text(user.name)],
),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => ProfileScreen()
),
)
);
}
Hope it works, if something is missing then tell me.

NoSuchMethodError. The getter 'weekday' was called on null. Table_Calendar Flutter

I'm stuck with the table calendar.
In Android Studio I get following error:
The following NoSuchMethodError was thrown building StreamBuilder<List<AppEvent>>(dirty, state: _StreamBuilderBaseState<List<AppEvent>, AsyncSnapshot<List<AppEvent>>>#c5581):
The getter 'weekday' was called on null.
Receiver: null
Tried calling: weekday
This is my code: If necessarily I can post more code such the classes.
The other code works perfekt. even in the red issuescreen in the app I can trigger the floated button and add an event. But I cant see the calendar anymore cause the red issuescreen.
import 'package:app_tennis_sv_schwaig/kalender/add_event.dart';
import 'package:app_tennis_sv_schwaig/kalender/event_details.dart';
import 'package:app_tennis_sv_schwaig/kalender/event_firestore_service.dart';
import 'package:app_tennis_sv_schwaig/kalender/app_event.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:table_calendar/table_calendar.dart';
class TennisKalender extends StatefulWidget {
#override
_TennisKalenderState createState() => _TennisKalenderState();
}
class _TennisKalenderState extends State<TennisKalender> {
CalendarController _calendarController = CalendarController();
Map<DateTime, List<AppEvent>> _groupedEvents;
_groupEvents(List<AppEvent> events) {
_groupedEvents = {};
events.forEach((event) {
DateTime date =
DateTime.utc(event.date.year, event.date.month, event.date.day, 12);
if (_groupedEvents[date] == null) _groupedEvents[date] = [];
_groupedEvents[date].add(event);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.orange,
appBar: AppBar(
backgroundColor: Colors.red,
title: Text("Tenniskalender"),
actions: <Widget>[
IconButton(
icon: Icon(Icons.person),
onPressed: (null),
)
],
),
body: SingleChildScrollView(
child: StreamBuilder(
stream: eventDBS.streamList(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
final events = snapshot.data;
_groupEvents(events);
DateTime selectedDate = _calendarController.selectedDay;
final _selectedEvents = _groupedEvents[selectedDate] ?? [];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Card(
clipBehavior: Clip.antiAlias,
margin: const EdgeInsets.all(8.0),
child: TableCalendar(
calendarController: _calendarController,
events: _groupedEvents,
onDaySelected: (date, events, holidays) {
setState(() {});
},
startingDayOfWeek: StartingDayOfWeek.monday,
headerStyle: HeaderStyle(
decoration: BoxDecoration(
color: Colors.red,
),
headerMargin: const EdgeInsets.only(bottom: 8.0),
),
),
),
Padding(
padding: const EdgeInsets.only(left: 12.0, top: 8.0),
child: Text(
DateFormat('EEEE, dd MMMM, yyyy').format(selectedDate),
style: Theme.of(context).textTheme.headline6,
),
),
ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: _selectedEvents.length,
itemBuilder: (BuildContext context, int index) {
AppEvent event = _selectedEvents[index];
return ListTile(
title: Text(event.title),
subtitle: Text(DateFormat("EEEE, dd MMMM, yyyy")
.format(event.date)),
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => EventDetails(
event: event,
)),
);
},
trailing: IconButton(
icon: Icon(Icons.edit),
onPressed: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => AddEventPage(
event: event,
)));
},
));
},
),
],
);
}
return CircularProgressIndicator();
},
),
),
floatingActionButton: FloatingActionButton(
child: Icon(
Icons.add,
color: Colors.grey[900],
),
backgroundColor: Colors.yellow,
onPressed: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => AddEventPage(
selectedDate: _calendarController.selectedDay,
),
),
);
}),
);
}
}
I dont get it where the weekday is written null.
Can you please help? Thanks a lot!
I solved it. In fact others have a similar issue here's my solution.
The DateFormat in the ListTile from the ListView.builder was the Problem. Don't know why but I deleted it, cause don't needed the view in the app anyway.
Errorcommand:
subtitle: Text(DateFormat("EEEE, dd MMMM, yyyy").format(event.date)),

non-null String must be provided to a Text widget. In Flutter showing the data != null'

I was creating a todo app in flutter with backend support of firebase everything was going ok but when I included the DocumentSnapshot that gives me error. I couldn't find a way to fix this issue.
A non-null String must be provided to a Text widget.
'package:flutter/src/widgets/text.dart':
Failed assertion: line 285 pos 10: 'data != null'
after the line included
documentSnapshot["todoTitle"]
How can I figure this out?
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class todoUi extends StatefulWidget {
#override
_todoUiState createState() => _todoUiState();
}
class _todoUiState extends State<todoUi> {
List todos = List();
String input = "";
createTodos() {
DocumentReference documentReference =
Firestore.instance.collection("MyTodos").document(input);
//Maping
Map<String, String> todos = {"todosTitle": input};
documentReference.setData(todos).whenComplete(() {
print("$input created");
});
}
deleteTodos() {}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Sharjeel's TODO LIST"),
centerTitle: true,
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.purple,
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
title: Text("Add Your Task"),
content: TextField(
onChanged: (String value) {
input = value;
},
),
actions: <Widget>[
FlatButton(
onPressed: () {
createTodos();
Navigator.of(context).pop();
},
child: Text("Add"))
],
);
});
},
child: Icon(
Icons.add,
color: Colors.white,
),
),
body: StreamBuilder(
stream: Firestore.instance.collection("MyTodos").snapshots(),
builder: (context, snapshots) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshots.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot documentSnapshot =
snapshots.data.documents[index];
return Dismissible(
key: Key(index.toString()),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
margin: EdgeInsets.all(8),
child: ListTile(
title: Text(
documentSnapshot["todoTitle"]
),
trailing: IconButton(
icon: Icon(
Icons.delete,
color: Colors.red,
),
onPressed: () {
setState(() {
todos.removeAt(index);
});
})),
),
);
});
}),
);
}
}
I guess that's because when your widget mounts the first time it is yet to get data from the Stream.
Maybe try :
Text(documentSnapshot["todoTitle"] ?? "")

How to make a streambuilder return data in other screens

I am new in Flutter, I have a question about an implementation I want to add my app, I would appreciate your answers, let me know if you need me to give you more information.
I hope, this is clear.
Here is the implementation I want to add my app...
I have a streambuilder in my home page(see below code implementing a container that has a streambuilder as a child) that gets data from firebase(the data is users information) and returns a Listview.builder that builds a list of containers with data like name and email(for each user) in my home screen...now, how can I replace the listView.builder and instead of having those users in a listview.builder, I actually want those users information to be saved one by one into different screens(like creating a user profile for each user).
This is the streambuilder:
Container(
///this is a regular streambuilder as a child of a container
child: StreamBuilder(
stream: Firestore.instance.collection('users').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(themeColor),
),
);
} else {
///THIS IS THE LISTVIEW.BUILDER
return ListView.builder(
padding: EdgeInsets.all(10.0),
///These are some methods that build the containers list with the users information
itemBuilder: (context, index) =>
buildItem(context, snapshot.data.documents[index]),
itemCount: snapshot.data.documents.length,
);
}
},
),
),
COMPLETE CODE FOR MY HOMEPAGE
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:jobly10/chat_implementation/settings.dart';
import 'chat.dart';
import 'const.dart';
import '../main.dart';
class HomeListViewUsers extends StatefulWidget {
final String currentUserId;
HomeListViewUsers({Key key, this.currentUserId}) : super(key: key);
#override
State createState() => HomeListViewUsersState(currentUserId: currentUserId);
}
class HomeListViewUsersState extends State<HomeListViewUsers> {
HomeListViewUsersState({Key key, #required this.currentUserId});
final String currentUserId;
final FirebaseMessaging firebaseMessaging = FirebaseMessaging();
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
final GoogleSignIn googleSignIn = GoogleSignIn();
bool isLoading = false;
List<Choice> choices = const <Choice>[
const Choice(title: 'Settings', icon: Icons.settings),
const Choice(title: 'Log out', icon: Icons.exit_to_app),
];
#override
void initState() {
super.initState();
registerNotification();
configLocalNotification();
}
void registerNotification() {
firebaseMessaging.requestNotificationPermissions();
firebaseMessaging.configure(onMessage: (Map<String, dynamic> message) {
print('onMessage: $message');
Platform.isAndroid
? showNotification(message['notification'])
: showNotification(message['aps']['alert']);
return;
}, onResume: (Map<String, dynamic> message) {
print('onResume: $message');
return;
}, onLaunch: (Map<String, dynamic> message) {
print('onLaunch: $message');
return;
});
firebaseMessaging.getToken().then((token) {
print('token: $token');
Firestore.instance
.collection('users')
.document(currentUserId)
.updateData({'pushToken': token});
}).catchError((err) {
Fluttertoast.showToast(msg: err.message.toString());
});
}
void configLocalNotification() {
var initializationSettingsAndroid =
new AndroidInitializationSettings('app_icon');
var initializationSettingsIOS = new IOSInitializationSettings();
var initializationSettings = new InitializationSettings(
initializationSettingsAndroid, initializationSettingsIOS);
flutterLocalNotificationsPlugin.initialize(initializationSettings);
}
void onItemMenuPress(Choice choice) {
if (choice.title == 'Log out') {
handleSignOut();
} else {
Navigator.push(
context, MaterialPageRoute(builder: (context) => Settings()));
}
}
void showNotification(message) async {
var androidPlatformChannelSpecifics = new AndroidNotificationDetails(
Platform.isAndroid
? 'com.dfa.flutterchatdemo'
: 'com.duytq.flutterchatdemo',
'Flutter chat demo',
'your channel description',
playSound: true,
enableVibration: true,
importance: Importance.Max,
priority: Priority.High,
);
var iOSPlatformChannelSpecifics = new IOSNotificationDetails();
var platformChannelSpecifics = new NotificationDetails(
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
print(message);
await flutterLocalNotificationsPlugin.show(0, message['title'].toString(),
message['body'].toString(), platformChannelSpecifics,
payload: json.encode(message));
}
Future<Null> handleSignOut() async {
this.setState(() {
isLoading = true;
});
await FirebaseAuth.instance.signOut();
await googleSignIn.disconnect();
await googleSignIn.signOut();
this.setState(() {
isLoading = false;
});
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) => MyApp()),
(Route<dynamic> route) => false);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Chat Screen',
style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold),
),
centerTitle: true,
),
body: WillPopScope(
child: Stack(
children: <Widget>[
// List
Container(
///here the chats users are called
child: StreamBuilder(
stream: Firestore.instance.collection('users').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(themeColor),
),
);
} else {
///THIS IS THE LISTVIEW.BUILDER
return ListView.builder(
padding: EdgeInsets.all(10.0),
///These are some methods that build the containers list with the users information
itemBuilder: (context, index) =>
buildItem(context, snapshot.data.documents[index]),
itemCount: snapshot.data.documents.length,
);
}
},
),
),
// Loading
Positioned(
child: isLoading
? Container(
child: Center(
child: CircularProgressIndicator(
valueColor:
AlwaysStoppedAnimation<Color>(themeColor)),
),
color: Colors.white.withOpacity(0.8),
)
: Container(),
)
],
),
// onWillPop: onBackPress,
),
);
}
Widget buildItem(BuildContext context, DocumentSnapshot document) {
if (document['id'] == currentUserId) {
return Container();
} else {
return Container(
child: FlatButton(
child: Row(
children: <Widget>[
Material(
child: document['profileImageUrl-'] != null
? CachedNetworkImage(
placeholder: (context, url) => Container(
child: CircularProgressIndicator(
strokeWidth: 1.0,
valueColor:
AlwaysStoppedAnimation<Color>(themeColor),
),
width: 50.0,
height: 50.0,
padding: EdgeInsets.all(15.0),
),
//i just cange this
imageUrl: document['profileImageUrl'],
width: 50.0,
height: 50.0,
fit: BoxFit.cover,
)
: Icon(
Icons.account_circle,
size: 50.0,
color: greyColor,
),
borderRadius: BorderRadius.all(Radius.circular(25.0)),
clipBehavior: Clip.hardEdge,
),
Flexible(
child: Container(
child: Column(
children: <Widget>[
Container(
child: Text(
'Name: ${document['nickname']}',
style: TextStyle(color: primaryColor),
),
alignment: Alignment.centerLeft,
margin: EdgeInsets.fromLTRB(10.0, 0.0, 0.0, 5.0),
),
Container(
child: Text(
'email: ${document['email']}',
style: TextStyle(color: primaryColor),
),
alignment: Alignment.centerLeft,
margin: EdgeInsets.fromLTRB(10.0, 0.0, 0.0, 5.0),
),
Container(
child: Text(
'About me: ${document['aboutMe'] ?? 'Not available'}',
style: TextStyle(color: primaryColor),
),
alignment: Alignment.centerLeft,
margin: EdgeInsets.fromLTRB(10.0, 0.0, 0.0, 0.0),
)
],
),
margin: EdgeInsets.only(left: 20.0),
),
),
],
),
onPressed: () {
///here is the flat button to go to messages
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Chat(
peerId: document.documentID,
peerAvatar: document['photoUrl'],
),
),
);
},
color: greyColor2,
padding: EdgeInsets.fromLTRB(25.0, 10.0, 25.0, 10.0),
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
),
margin: EdgeInsets.only(bottom: 10.0, left: 5.0, right: 5.0),
);
}
}
}
class Choice {
const Choice({this.title, this.icon});
final String title;
final IconData icon;
}
If you want each item in the ListView.builder to be 'tappable' and send you to a profile screen containing the tapped user's information, try wrapping each ListView element in a GestureDetector:
return ListView.builder(
padding: EdgeInsets.all(10.0),
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) =>
GestureDetector(
onTap: Navigator.push(context,
MaterialPageRoute(builder: (context) => UserProfile(user_name, user_age, user_etc)),);
child: buildItem(context, snapshot.data.documents[index])
),
);
You can pass info from your Stream into a newly made UserProfile (or something to that effect) page, which is navigated to by tapping on either of the ListView panels.
Alternatively, in your buildItem widget definition, you can return a GestureDetector (which will wrap your current Container) instead and place the onTap logic in there.

Resources