我正在为xamarin表单应用程序开发联系人搜索模块。我使用依赖注入来启动本机联系人选择器。搜索功能具有四个过滤器。
以下是我的Xamarin.ios代码。
public async Task<List<CNContact>> LaunchContact(IViewContext context, ContactsSearch contactsSearch)
{
List<CNContact> contactsList = new List<CNContact>();
CNContactPickerViewController contactPickerViewController = new CNContactPickerViewController();
var emailPredicate = NSPredicate.FromFormat("emailAddresses.@count > 0");
var phoneNumbersPredicate = NSPredicate.FromFormat("phoneNumbers.@count > 0");
var compoundPredicate = new List<NSPredicate>();
switch (contactsSearch.SearchOption)
{
case SearchOption.OnlyEmail:
compoundPredicate.Add(emailPredicate);
break;
case SearchOption.OnlyPhoneNumber:
compoundPredicate.Add(phoneNumbersPredicate);
break;
case SearchOption.EmailOrPhoneNumber:
compoundPredicate.Add(NSPredicate.FromFormat("emailAddresses.@count > 0 OR phoneNumbers.@count > 0"));
break;
case SearchOption.EmailAndPhoneNumber:
compoundPredicate.Add(emailPredicate);
compoundPredicate.Add(phoneNumbersPredicate);
break;
default:
break;
}
var predicateListCount = compoundPredicate.Count;
if (predicateListCount > 0)
{
var compoundPredicateArray = new NSPredicate[predicateListCount];
for (int index = 0; index < predicateListCount; index++)
{
compoundPredicateArray[index] = compoundPredicate[index];
}
contactPickerViewController.PredicateForEnablingContact =
NSCompoundPredicate.CreateAndPredicate(compoundPredicateArray);
}
TaskCompletionSource<List<CNContact>> promise = new TaskCompletionSource<List<CNContact>>();
bool contactPickerPresented = false;
try
{
var displayWaitingIndicator = WaitingIndicator.IsWaitingIndicatorVisible;
var currentContext = ((PageRenderer)context.Renderer);
contactPickerViewController.PredicateForSelectionOfContact = NSPredicate.FromValue(true);
contactPickerViewController.Delegate = new ContactPickerDelegate(promise);
contactPickerViewController.DisplayedPropertyKeys = KeysToFetch;
if (displayWaitingIndicator)
{
await WaitingIndicator.HideWaitingIndicatorAsync(true);
}
currentContext.PresentViewController(contactPickerViewController, true, null);
contactPickerPresented = true;
if (displayWaitingIndicator)
{
await WaitingIndicator.ShowWaitingIndicatorAsync();
}
contactsList = await promise.Task;
if (contactsList.Count == 0)
{
throw new Exception();
}
}
catch (TaskCanceledException ex)
{
Console.WriteLine(ex.Message);
if (contactPickerViewController != null && contactPickerPresented)
{
contactPickerViewController.DismissModalViewController(true);
}
}
return contactsList;
}
我为此实现了CNContactPickerDelegate。
以下是我的Xamarin.android代码
public async Task<ICursor> LaunchContact(IViewContext context, ContactsSearch contactsSearch)
{
var currentActivity = (Activity)((PageRenderer)context.Renderer).Context;
var contentResolver = currentActivity.ContentResolver;
var promise = new TaskCompletionSource<ICursor>();
var type = string.Empty;
switch (contactsSearch.SearchOption)
{
case SearchOption.OnlyEmail:
type = ContactsContract.CommonDataKinds.Email.ContentType;
break;
case SearchOption.OnlyPhoneNumber:
type = ContactsContract.CommonDataKinds.Phone.ContentType;
break;
case SearchOption.EmailOrPhoneNumber:
break;
case SearchOption.EmailAndPhoneNumber:
break;
default:
break;
}
ContactsActivity.ContactsPickerPromise = promise;
var contactsActivityIntent = new Intent(currentActivity, typeof(ContactsActivity));
contactsActivityIntent.PutExtra(ContactsActivity.INTENT_TYPE_KEY, type);
currentActivity.StartActivity(contactsActivityIntent);
ICursor selectedContactsCursor = await promise.Task;
return selectedContactsCursor;
}
ContactsActivity
public class ContactsActivity : Activity
{
private const int REQUEST_CODE = 101;
private readonly TaskCompletionSource<ICursor> promise;
public static TaskCompletionSource<ICursor> ContactsPickerPromise { get; set; }
public const string IntentExtraContext = "ActivityContext";
public const string INTENT_TYPE_KEY = "CONTACT_PICKER_URL_INTENT";
public ContactsActivity()
{
promise = ContactsPickerPromise;
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
LaunchContactPicker();
}
private void LaunchContactPicker()
{
var contactPickerType = Intent.GetStringExtra(INTENT_TYPE_KEY);
var contactPickerIntent = new Intent(Intent.ActionPick);
if (contactPickerType != "")
{
contactPickerIntent.SetType(contactPickerType);
}
else
{
contactPickerIntent.SetData(ContactsContract.Contacts.ContentUri);
}
StartActivityForResult(contactPickerIntent, REQUEST_CODE);
}
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
Finish();
Task.Factory.StartNew(() =>
{
try
{
if (requestCode == REQUEST_CODE && resultCode == Result.Ok)
{
Android.Net.Uri uri = data.Data;
var contentResolver = this.ContentResolver;
var contactsCursor = contentResolver.Query(uri, null, null, null, null);
promise.TrySetResult(contactsCursor);
}
else
{
promise.TrySetCanceled();
return;
}
}
catch (Exception ex)
{
promise.SetException(ex);
}
});
}
}
代码结果如下。
Android联系人选择器启动时会过滤掉联系人,但仅允许选择一个电子邮件或电话号码。如果通过电子邮件过滤联系人,则无法选择其电话号码,反之亦然。
iOS联系人选择器视图控制器显示所有联系人,但与给定条件不匹配的联系人显示为灰色且无法选择。可以进行多项选择,并且可以看到所选联系人的所有详细信息。
我的问题是,可以将Android联系人选择器设置为选择多个联系人吗?如果可以,如何在选择单个联系人和多个联系人之间切换?
编辑-找到了一种解决方法,可以在iOS中选择/取消选择多个联系人。 您只需要实现两个CNContactPickerDelegate类。一个用于DidSelectContact()方法,另一个用于DidSelectContacts()方法。剩下的就是寻找一种在Android联系人选择器中启用多项选择的方法。