【问题标题】:How to show iOS add contact screen from Xamarin Forms?如何从 Xamarin Forms 显示 iOS 添加联系人屏幕?
【发布时间】:2015-07-06 21:49:37
【问题描述】:

我正在尝试使用 Xamarin Forms 显示 iOS 添加联系人屏幕。据我所知,Xamarin Forms 不支持开箱即用,但 Xamarin iOS 支持。不幸的是,我不能让他们一起工作。我所说的“一起”是指我需要从 Xamarin 表单页面访问 NavigationController。

这个可以吗?

我有一个示例解决方案来演示这里的问题:https://github.com/pawelpabich/XamarinFormsContacts。我还在下面放了最重要的代码。

public void ShowContact(NavigationPage page)
{
    var newPersonController = new ABNewPersonViewController();
    var person = new ABPerson();
    person.FirstName = "John";
    person.LastName = "Doe";

    newPersonController.DisplayedPerson = person;
    var controller = page.CreateViewController();

    //!!!!---> controller.NavigationController is null !!!!!<----
    controller.NavigationController.PushViewController(newPersonController, true);
}

我更新了 repo,现在它包含了可以工作的代码。

【问题讨论】:

    标签: xamarin xamarin.ios xamarin.forms


    【解决方案1】:

    使用 Xamarin.Forms 时(使用 NavigationPage 时)有一个 UINavigationController,但您必须搜索它。这是我能抓住它的唯一方法。那些其他方法,CreateViewController 和 RendererFactory 实际上创建了一个新的 ViewController,这不是你想要的。

    public void ShowContact(NavigationPage page)
    {
        var newPersonController = new ABNewPersonViewController();
        var person = new ABPerson();
        person.FirstName = "John";
        person.LastName = "Doe";
        newPersonController.Title = "This is a test";
    
        newPersonController.DisplayedPerson = person;
    
        UINavigationController nav = null;
        foreach (var vc in 
          UIApplication.SharedApplication.Windows[0].RootViewController.ChildViewControllers) 
        {
            if (vc is UINavigationController)
                nav = (UINavigationController)vc;
        }
    
        nav.PresentModalViewController(new UINavigationController (newPersonController), true);
    }
    

    我还尝试创建一个 PersonPage 和 PersonPageRenderer,因为那将是最干净的解决方案,但我无法让它工作。如果您花一些时间,这可能会奏效。

    [assembly: ExportRenderer(typeof(PersonPage), typeof(PersonPageRenderer))] 
    
    public class PersonPageRenderer : ABNewPersonViewController, IVisualElementRenderer, IDisposable, IRegisterable 
    

    【讨论】:

    • 这个示例适合您吗?在我的测试应用程序中,NRE 失败,因为最后一行中的导航为“null”。
    • 顺便说一句,如果我不介意的话,在上一次悉尼移动聚会上,有人展示了他的 X.F 插件,该插件支持与联系人一起工作。
    • 你知道那是谁 :) 吗?
    • rid00z,我只需要添加“newPersonController.NewPersonComplete += (object sender, ABNewPersonCompleteEventArgs e) => { nav.DismissModalViewController(true); };”
    • 不,是这个问题,我不记得了:(
    【解决方案2】:

    Pawel,问题是当您使用 Xamarin.Forms 时没有创建 NavigationController(至少在 X.F 1.3+ 中我知道,也许 Michael 会证明我错了)。如果你想创建新的地址 boo 元素,你可以使用这种方法 - How do you add contacts to the iPhone Address book with monotouch?

    【讨论】:

    • 谢谢阿图尔。我之前看过代码唯一的解决方案,问题是我的要求是显示添加联系人屏幕,其中预先填充了一些字段。你知道我是否可以在不破坏 XF 的情况下手动创建 NavigationController 吗?
    【解决方案3】:

    因为 iOS 添加联系人屏幕是原生 iOS API,并且您的应用程序逻辑位于 PCL 中,您需要使用 DependancyService。

    1) 要在 PCL 中执行此操作,请创建一个提供功能的接口,例如

    public interface ILocalAddContact 
    {   
        void DisplayContactScreen(Contact contact) 
    }
    

    2) 在原生应用中实现接口:

    public class LocalAddContactiOS : ILocalAddContact
    {
        public void DisplayContactScreen(Contact contact)
        {
            //... do iOS Magic
        }
    }
    

    3) 在 Native 文件顶部注册依赖

    [assembly: Xamarin.Forms.Dependency(typeof(LocalAddContactiOS))]
    

    4) 从

    获取 iOS 项目的依赖
    var addContact = DependencyService.Get<ILocalAddContact> ();
    addContact.DisplayContactScreen (contact);
    

    如果您查看 github 上的 this sample application,它非常相似(但用于 CreateCalendar)。

    【讨论】:

    • 对不起,我不够精确。它不是关于如何提供特定于平台的代码。我需要填充 NavigationController。或者您是说我可以使用 UIApplication.SharedApplication.Windows[0].RootViewController 访问?
    【解决方案4】:

    好的,这就是我最终实现的方式。我手动创建了 UINavigationController 并将其用于 Xamarin.Forms 之外的导航。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    using Foundation;
    using UIKit;
    using Xamarin.Forms;
    using AddressBookUI;
    using AddressBook;
    
    namespace TestContacts.iOS
    {
        [Register ("AppDelegate")]
        public partial class AppDelegate : UIApplicationDelegate
        {
            UIWindow window;
            public override bool FinishedLaunching (UIApplication app, NSDictionary options)
            {
                global::Xamarin.Forms.Forms.Init ();
                window = new UIWindow(UIScreen.MainScreen.Bounds);
    
                var nav = 
                    new UINavigationController(new App ().MainPage.CreateViewController());
                ContactsShared.Instance = new TouchContacts (nav);
                window.RootViewController = nav;
    
                window.MakeKeyAndVisible();
    
                return true;
            }
        }
    
        public class TouchContacts : IContactsShared {
            UINavigationController nav;
            public TouchContacts(UINavigationController nav){
                this.nav = nav;
            }
            public void Show() {
    
                var newPersonController = new ABNewPersonViewController();
                newPersonController.NewPersonComplete += 
                   (object sender, ABNewPersonCompleteEventArgs e) => 
                {    
                    nav.PopViewController(true);
                };
                var person = new ABPerson();
                person.FirstName = "John";
                person.LastName = "Doe";
    
    
                newPersonController.DisplayedPerson = person;
                nav.PushViewController(newPersonController, true); 
            }
        }
    }
    

    【讨论】:

    • 顺便说一句,我并不是说这是一个好方法,但它确实有效。
    • 这对我有用,但比 rid00z 建议的更具侵入性,所以我会接受它。感谢您的想法!
    猜你喜欢
    • 1970-01-01
    • 2020-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-15
    • 1970-01-01
    • 1970-01-01
    • 2016-01-23
    相关资源
    最近更新 更多