Lor*_*kel 6 listview dart flutter stream-builder
在我的 Flutter 应用程序中,我有一个包含所有用户的屏幕。用户列表由 a 生成StreamBuilder,它从 Cloud Firestore 获取数据并在 a 中显示用户ListView。为了改进功能,我希望能够使用Appbar.
我已经尝试过这个答案并且效果很好,但我不知道如何让它StreamBuilder在我的情况下工作。作为一个颤振初学者,我将不胜感激任何帮助!下面我包括了我的用户屏幕和StreamBuilder.
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
class UsersScreen extends StatefulWidget {
static const String id = 'users_screen';
@override
_UsersScreenState createState() => _UsersScreenState();
}
class _UsersScreenState extends State<UsersScreen> {
static Map<String, dynamic> userDetails = {};
static final String environment = userDetails['environment'];
Widget appBarTitle = Text('Manage all users');
Icon actionIcon = Icon(Icons.search);
final TextEditingController _controller = TextEditingController();
String approved = 'yes';
getData() async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
return await _firestore
.collection('users')
.document(user.uid)
.get()
.then((val) {
userDetails.addAll(val.data);
}).whenComplete(() {
print('${userDetails['environment']}');
setState(() {});
});
}
_printLatestValue() {
print('value from searchfield: ${_controller.text}');
}
@override
void initState() {
getData();
_controller.addListener(_printLatestValue);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: appBarTitle,
actions: <Widget>[
IconButton(
icon: actionIcon,
onPressed: () {
setState(() {
if (this.actionIcon.icon == Icons.search) {
this.actionIcon = Icon(Icons.close);
this.appBarTitle = TextField(
controller: _controller,
style: TextStyle(
color: Colors.white,
),
decoration: InputDecoration(
prefixIcon: Icon(Icons.search, color: Colors.white),
hintText: "Search...",
hintStyle: TextStyle(color: Colors.white)),
onChanged: (value) {
//do something
},
);
} else {
this.actionIcon = Icon(Icons.search);
this.appBarTitle = Text('Manage all users');
// go back to showing all users
}
});
},
),
]),
body: SafeArea(
child: StreamUsersList('${userDetails['environment']}', approved),
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
class StreamUsersList extends StatelessWidget {
final String environmentName;
final String approved;
StreamUsersList(this.environmentName, this.approved);
static String dropdownSelected2 = '';
@override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: Firestore.instance
.collection('users')
.where('environment', isEqualTo: environmentName)
.where('approved', isEqualTo: approved)
.snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.lightBlueAccent,
),
);
} else if (snapshot.connectionState == ConnectionState.done &&
!snapshot.hasData) {
return Center(
child: Text('No users found'),
);
} else if (snapshot.hasData) {
return ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
itemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index) {
DocumentSnapshot user = snapshot.data.documents[index];
return Padding(
padding: EdgeInsets.symmetric(
horizontal: 7.0,
vertical: 3.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
//This CardCustom is just a Card with some styling
CardCustomUsers(
title: user.data['unit'],
weight: FontWeight.bold,
subTitle:
'${user.data['name']} - ${user.data['login']}',
),
],
),
);
});
} else {
return Center(
child: Text('Something is wrong'),
);
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
编辑
我设法以更简单的方式实现搜索功能,而无需更改大部分代码。对于其他初学者,我添加了以下代码:
在我的内部,_UsersScreenState我添加了String searchResult = '';其他变量。然后我将 的 更改onChanged为TextField:
onChanged: (String value) {
setState(() {
searchResult = value;
});
},```
Run Code Online (Sandbox Code Playgroud)
我将其传递给StreamUsersList并添加到初始化中。在ListView.Builder我添加了一个 if 语句与(snapshot.data.documents[index].data['login'].contains(searchResult)). 请参阅我的下面的代码ListView.Builder作为示例。
else if (snapshot.hasData) {
return ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
itemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index) {
DocumentSnapshot user = snapshot.data.documents[index];
final record3 = Record3.fromSnapshot(user);
String unitNr = user.data['unit'];
if (user.data['login'].contains(searchResult) ||
user.data['name'].contains(searchResult) ||
user.data['unit'].contains(searchResult)) {
return Padding(
padding: EdgeInsets.symmetric(
horizontal: 7.0,
vertical: 3.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
//This CardCustom is just a Card with some styling
CardCustomUsers(
title: unitNr,
color: Colors.white,
weight: FontWeight.bold,
subTitle:
'${user.data['name']}\n${user.data['login']}',
),
],
),
);
} else {
return Visibility(
visible: false,
child: Text(
'no match',
style: TextStyle(fontSize: 4.0),
),
);
}
});
} else {
return Center(
child: Text('Something is wrong'),
);
}
Run Code Online (Sandbox Code Playgroud)
您可以采取以下方法。
我希望这会有所帮助,如有任何疑问,请告诉我。
编辑
您不需要 ValueNotifier,而是需要 StreamBuilder。所以你的小部件的最终层次结构将是: StreamBuilder( StreamBuilder>( ListView.Builder ) )
我没有像你这样的环境,所以我模拟了它并创建了一个例子。您可以参考一下,希望它能给您一些解决问题的思路。以下是工作代码,您可以参考:
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: SearchWidget(),
),
));
class SearchWidget extends StatelessWidget {
SearchWidget({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: <Widget>[
TextField(onChanged: _filter),
StreamBuilder<List<User>>( // StreamBuilder<QuerySnapshot> in your code.
initialData: _dataFromQuerySnapShot, // you won't need this. (dummy data).
// stream: Your querysnapshot stream.
builder:
(BuildContext context, AsyncSnapshot<List<User>> snapshot) {
return StreamBuilder<List<User>>(
key: ValueKey(snapshot.data),
initialData: snapshot.data,
stream: _stream,
builder:
(BuildContext context, AsyncSnapshot<List<User>> snapshot) {
print(snapshot.data);
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return Text(snapshot.data[index].name);
},
);
},
);
},
)
],
),
);
}
}
StreamController<List<User>> _streamController = StreamController<List<User>>();
Stream<List<User>> get _stream => _streamController.stream;
_filter(String searchQuery) {
List<User> _filteredList = _dataFromQuerySnapShot
.where((User user) => user.name.toLowerCase().contains(searchQuery.toLowerCase()))
.toList();
_streamController.sink.add(_filteredList);
}
List<User> _dataFromQuerySnapShot = <User>[
// every user has same enviornment because you are applying
// such filter on your query snapshot.
// same is the reason why every one is approved user.
User('Zain Emery', 'some_enviornment', true),
User('Dev Franco', 'some_enviornment', true),
User('Emilia ONeill', 'some_enviornment', true),
User('Zohaib Dale', 'some_enviornment', true),
User('May Mcdougall', 'some_enviornment', true),
User('LaylaRose Mitchell', 'some_enviornment', true),
User('Beck Beasley', 'some_enviornment', true),
User('Sadiyah Walker', 'some_enviornment', true),
User('Mae Malone', 'some_enviornment', true),
User('Judy Mccoy', 'some_enviornment', true),
];
class User {
final String name;
final String environment;
final bool approved;
const User(this.name, this.environment, this.approved);
@override
String toString() {
return 'name: $name environment: $environment approved: $approved';
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8264 次 |
| 最近记录: |