无法在颤动的列表视图小部件中显示 phone 中的联系人姓名
Unable to display contact names from phone in a list view widget in flutter
我正在尝试使用 bloc 从联系人服务中获取联系人,并在列表视图的覆盖小部件中显示联系人姓名。您能否检查我的代码并让我知道哪里出了问题,因为它无法获取任何联系人并显示姓名。
提前感谢您抽出时间。
P.S。我添加了打印语句,但其中 none 显示了联系方式(姓名)。
文件 1:main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:invite_friends/contactsBloc.dart';
import 'accessContacts.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(
theme: ThemeData(scaffoldBackgroundColor: Colors.white),
home: BlocProvider
(create: (BuildContext context) => ContactCubit(),
child: AccessContacts()),
);
}
}
File 2: accessContacts.dart
import 'package:contacts_service/contacts_service.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:permission_handler/permission_handler.dart';
import 'contactDetails.dart';
import 'contactsBloc.dart';
class AccessContacts extends StatelessWidget {
late OverlayEntry _overlayEntry;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Padding(
padding: const EdgeInsets.only(left: 16, top: 80),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ElevatedButton(onPressed: () {
_overlayEntry = showOverlayContacts(context);
Overlay.of(context)?.insert(_overlayEntry);
}, child: const Text('Grant permission to access contacts'),
style: ElevatedButton.styleFrom(
minimumSize: const Size(199, 41),
elevation: 5.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0)),
shadowColor: const Color(0xFFE5E5E5),
primary: const Color(0xFFE5E5E5),
onPrimary: const Color(0xFFB13937),
textStyle: const TextStyle(fontFamily: 'Poppins',
fontSize: 14)),),
],
),
),
);
}
// check contacts permission
Future<PermissionStatus> _getPermission() async {
final PermissionStatus permission = await Permission.contacts.request();
print(permission);
return permission;
}
showOverlayContacts(BuildContext context) {
final ContactCubit _contactBloc = BlocProvider.of<ContactCubit>(context);
BlocProvider.of<ContactCubit>(context).getContacts();
TextEditingController editingController = TextEditingController();
OverlayState? overlayState = Overlay.of(context);
return OverlayEntry(builder: (context) =>
Positioned(
bottom: 350,
width: MediaQuery
.of(context)
.size
.width,
height: MediaQuery
.of(context)
.size
.height / 2,
child: Card(
elevation: 20,
child: searchContacts(editingController,_contactBloc),
),
), opaque: false);
}
Column searchContacts(TextEditingController editingController,_contactBloc) {
List<Contact> contacts;
return Column(
// mainAxisAlignment: MainAxisAlignment.start,
// crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(top: 22, left: 16, right: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: const [
Text('Find contacts (upto 5) ',
style: TextStyle(fontFamily: 'Poppins',
fontSize: 14)),
Icon(Icons.cancel),
],
),
),
const Divider(
color: Colors.grey
),
Padding(
padding: const EdgeInsets.only(left: 16),
child: TextField(
onChanged: (value) {
print(value);
},
controller: editingController,
showCursor: true,
autofocus: true,
decoration: const InputDecoration(
border: InputBorder.none,
isDense: true,
suffixIcon: Padding(
padding: EdgeInsets.only(right: 16),
child: Icon(Icons.search, size: 30,),
),
suffixIconConstraints: BoxConstraints(
minWidth: 20,
minHeight: 20,
),
),
),
),
const Divider(
color: Colors.grey
),
BlocBuilder<ContactCubit, List<Contact>>(bloc: _contactBloc, builder: (BuildContext context, List<Contact> contacts){
return Expanded(
child: ListView.builder(itemCount: 3,itemBuilder: (context, index) {
Contact contact = contacts.elementAt(index);
return Text(contact.displayName ?? '');
},
),
);},)
],);
}}
File3: contactsBloc.dart
import 'package:contacts_service/contacts_service.dart';
import 'package:invite_friends/contactDetails.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:invite_friends/getContactList.dart';
import '';
class ContactCubit extends Cubit<List<Contact>> {
ContactCubit() : super([]);
final _dataService = DataService();
Future getContacts() async {
await _dataService.getPhoneContacts();
print(state.length);
// _dataService.getPhoneContacts();
emit(state);
}
}
File 4: getContactList.dart
import 'package:contacts_service/contacts_service.dart';
import 'package:permission_handler/permission_handler.dart';
import 'contactDetails.dart';
class DataService {
Future getPhoneContacts() async {
try{
Contact contact;
final PermissionStatus permissionStatus = await Permission.contacts.request();
if (permissionStatus == PermissionStatus.granted) {
// Get all contacts without thumbnail (faster)
List<Contact> contacts = await ContactsService.getContacts(withThumbnails: false);
for(contact in contacts){
print(contact.displayName);
}
} }
catch(e){
rethrow;
}
return [];
}
}
在您的数据服务 class 中,当您调用 getPhoneContacts() 时,您会获取联系人列表 List<Contact> contacts
但仅将其打印到控制台。
我想你想要做的是 return 它到你的 Bloc,所以你必须添加 return contacts;
并将 getPhoneContacts() 的 return 类型更改为 Future<List<Contact>>
.
在您的 ContactCubit 中,您必须将 await _dataService.getPhoneContacts();
的结果分配给一个变量并将其作为状态发出,例如:
Future getContacts() async {
final contacts = await _dataService.getPhoneContacts();
print(contacts.length);
emit(contacts);
}
然后在您的小部件中,您可以像这样使用 BlocBuilder 访问联系人:
BlocBuilder.of<ContactCubit, List<Contact>>(
bloc: _contactBloc,
(context, contacts) {
return Expanded(
child: ListView.builder(
itemCount: contacts.length,
itemBuilder: (context, index) {
Contact contact = contacts.elementAt(index);
return Text(contact.displayName ?? '');
},
),
),
}
)
我正在尝试使用 bloc 从联系人服务中获取联系人,并在列表视图的覆盖小部件中显示联系人姓名。您能否检查我的代码并让我知道哪里出了问题,因为它无法获取任何联系人并显示姓名。
提前感谢您抽出时间。
P.S。我添加了打印语句,但其中 none 显示了联系方式(姓名)。
文件 1:main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:invite_friends/contactsBloc.dart';
import 'accessContacts.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(
theme: ThemeData(scaffoldBackgroundColor: Colors.white),
home: BlocProvider
(create: (BuildContext context) => ContactCubit(),
child: AccessContacts()),
);
}
}
File 2: accessContacts.dart
import 'package:contacts_service/contacts_service.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:permission_handler/permission_handler.dart';
import 'contactDetails.dart';
import 'contactsBloc.dart';
class AccessContacts extends StatelessWidget {
late OverlayEntry _overlayEntry;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Padding(
padding: const EdgeInsets.only(left: 16, top: 80),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ElevatedButton(onPressed: () {
_overlayEntry = showOverlayContacts(context);
Overlay.of(context)?.insert(_overlayEntry);
}, child: const Text('Grant permission to access contacts'),
style: ElevatedButton.styleFrom(
minimumSize: const Size(199, 41),
elevation: 5.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0)),
shadowColor: const Color(0xFFE5E5E5),
primary: const Color(0xFFE5E5E5),
onPrimary: const Color(0xFFB13937),
textStyle: const TextStyle(fontFamily: 'Poppins',
fontSize: 14)),),
],
),
),
);
}
// check contacts permission
Future<PermissionStatus> _getPermission() async {
final PermissionStatus permission = await Permission.contacts.request();
print(permission);
return permission;
}
showOverlayContacts(BuildContext context) {
final ContactCubit _contactBloc = BlocProvider.of<ContactCubit>(context);
BlocProvider.of<ContactCubit>(context).getContacts();
TextEditingController editingController = TextEditingController();
OverlayState? overlayState = Overlay.of(context);
return OverlayEntry(builder: (context) =>
Positioned(
bottom: 350,
width: MediaQuery
.of(context)
.size
.width,
height: MediaQuery
.of(context)
.size
.height / 2,
child: Card(
elevation: 20,
child: searchContacts(editingController,_contactBloc),
),
), opaque: false);
}
Column searchContacts(TextEditingController editingController,_contactBloc) {
List<Contact> contacts;
return Column(
// mainAxisAlignment: MainAxisAlignment.start,
// crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(top: 22, left: 16, right: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: const [
Text('Find contacts (upto 5) ',
style: TextStyle(fontFamily: 'Poppins',
fontSize: 14)),
Icon(Icons.cancel),
],
),
),
const Divider(
color: Colors.grey
),
Padding(
padding: const EdgeInsets.only(left: 16),
child: TextField(
onChanged: (value) {
print(value);
},
controller: editingController,
showCursor: true,
autofocus: true,
decoration: const InputDecoration(
border: InputBorder.none,
isDense: true,
suffixIcon: Padding(
padding: EdgeInsets.only(right: 16),
child: Icon(Icons.search, size: 30,),
),
suffixIconConstraints: BoxConstraints(
minWidth: 20,
minHeight: 20,
),
),
),
),
const Divider(
color: Colors.grey
),
BlocBuilder<ContactCubit, List<Contact>>(bloc: _contactBloc, builder: (BuildContext context, List<Contact> contacts){
return Expanded(
child: ListView.builder(itemCount: 3,itemBuilder: (context, index) {
Contact contact = contacts.elementAt(index);
return Text(contact.displayName ?? '');
},
),
);},)
],);
}}
File3: contactsBloc.dart
import 'package:contacts_service/contacts_service.dart';
import 'package:invite_friends/contactDetails.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:invite_friends/getContactList.dart';
import '';
class ContactCubit extends Cubit<List<Contact>> {
ContactCubit() : super([]);
final _dataService = DataService();
Future getContacts() async {
await _dataService.getPhoneContacts();
print(state.length);
// _dataService.getPhoneContacts();
emit(state);
}
}
File 4: getContactList.dart
import 'package:contacts_service/contacts_service.dart';
import 'package:permission_handler/permission_handler.dart';
import 'contactDetails.dart';
class DataService {
Future getPhoneContacts() async {
try{
Contact contact;
final PermissionStatus permissionStatus = await Permission.contacts.request();
if (permissionStatus == PermissionStatus.granted) {
// Get all contacts without thumbnail (faster)
List<Contact> contacts = await ContactsService.getContacts(withThumbnails: false);
for(contact in contacts){
print(contact.displayName);
}
} }
catch(e){
rethrow;
}
return [];
}
}
在您的数据服务 class 中,当您调用 getPhoneContacts() 时,您会获取联系人列表 List<Contact> contacts
但仅将其打印到控制台。
我想你想要做的是 return 它到你的 Bloc,所以你必须添加 return contacts;
并将 getPhoneContacts() 的 return 类型更改为 Future<List<Contact>>
.
在您的 ContactCubit 中,您必须将 await _dataService.getPhoneContacts();
的结果分配给一个变量并将其作为状态发出,例如:
Future getContacts() async {
final contacts = await _dataService.getPhoneContacts();
print(contacts.length);
emit(contacts);
}
然后在您的小部件中,您可以像这样使用 BlocBuilder 访问联系人:
BlocBuilder.of<ContactCubit, List<Contact>>(
bloc: _contactBloc,
(context, contacts) {
return Expanded(
child: ListView.builder(
itemCount: contacts.length,
itemBuilder: (context, index) {
Contact contact = contacts.elementAt(index);
return Text(contact.displayName ?? '');
},
),
),
}
)