2015-04-28 46 views
0

我试图用Xamarin Forms显示iOS添加联系人屏幕。从我所看到的Xamarin Forms不支持这个开箱即用,但Xamarin iOS。不幸的是,我无法让他们一起工作。 “我在一起”的意思是我需要从Xamarin Forms Page访问NavigationController。如何显示iOS从Xamarin Forms添加联系人屏幕?

可以这样做吗?

我有一个示例解决方案,演示这里的问题: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); 
} 

我更新了回购,现在包含了代码工作。

回答

1

有一个UINavigationController使用Xamarin.Forms时(使用NavigationPage时),但你必须寻找它。这是我能得到它的唯一途径。那些其他的方法,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 
+0

这个样本是否适合您?在我的测试应用程序中,它以NRE失败,因为nav在最后一行是“null”。 –

+0

顺便说一句,如果大脑不跟我玩技巧,在上次的悉尼移动聚会上,有人提出了他的X.F插件,它支持联系人的工作。 –

+0

你知道那是谁吗? –

0

由于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)注册本机文件顶部的依赖性

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

4)从

var addContact = DependencyService.Get<ILocalAddContact>(); 
addContact.DisplayContactScreen (contact); 

从iOS项目获取扶养如果你在github上看看this sample application,这是非常类似(但用于CreateCalendar)。

+0

对不起,我不够精确。这不是关于如何提供平台特定的代码。我需要NavigationController来填充。或者你说我可以访问使用UIApplication.SharedApplication.Windows [0] .RootViewController? –

0

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

+0

谢谢Artur。我以前只见过代码解决方案,问题是我的要求是显示添加了一些预填充字段的联系人屏幕。你知道我是否可以在不破坏XF的情况下手工创建NavigationController? –

0

好的,这是我最终如何实现。我手动创建了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); 
     } 
    } 
} 
+0

顺便说一句,我不是说这是一个好方法,但它的工作。 –

+0

这适用于我,但比rid00z提出的更具有侵略性,所以我会继续使用它。感谢您的想法! –

相关问题