CNContactPickerViewController和Android联系人选择器-切换到单个或多个联系人

时间:2018-09-18 09:30:27

标签: android swift xamarin.ios xamarin.android

我正在为xamarin表单应用程序开发联系人搜索模块。我使用依赖注入来启动本机联系人选择器。搜索功能具有四个过滤器。

  • 仅电子邮件 联系人必须至少有一个电子邮件地址。
  • 仅电话号码 联系人必须至少有一个电话号码。
  • 电子邮件或电话号码 联系人必须至少具有一个电子邮件地址或电话号码。
  • EmailAndPhoneNumber 联系人必须至少具有一个电子邮件地址和一个电话号码。

以下是我的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联系人选择器中启用多项选择的方法。

0 个答案:

没有答案