How to use Xamarin.Form Controls and Native Controls On the same page

14,429

Solution 1

There's a few things being discussed, so bear with me:

The image snippet, from what I understand:

 "Not only are Xamarin.Forms pages mixable with custom screens" ...

This is like what @Stephane is mentioning allowing an application to use native screens as well as Xamarin.Forms screens. Each platform stub-page can introduce a shared Xamarin.Forms page at any point in the application. You don't have to use the Xamarin.Forms Navigation Stack.

 "but you can embed custom views built directly against Xamarin.IOS and Xamarin.Android into Xamarin.Forms pages."

This is what @Sten is mentioning, where if you create platform specific ContentRenderers you can render any kind of native controls into an existing Xamarin.Forms page, by passing this common View to each platform renderer.

So, for instance if you had a View:-

 public class MyView : ContentView
 {
     // Create some bindable properties here that can be used in your platform specific renderer,
     // i.e. DisplayText etc.
 }

You can use the above in a Xamarin.Forms page definition and then create platform specific renderers that would be called to render the content.

It is from within these platform specific content renderer classes that you can use native controls on each platform.

For instance in the ContentRenderer, for the event OnElementChanged you could do something like the following for WindowsPhone:-

 protected override void OnElementChanged(Xamarin.Forms.Platform.WinPhone.ElementChangedEventArgs<MyView> e)
 {
     base.onElementChanged(e);
     ...
     System.Windows.Controls.TextBox objPlatformSpecificTextBox = new System.Windows.Controls.TextBox();
     ... 
     ...

However, what @Gulshan is really wanting I believe is to have a native page that is center-stage with the Xamarin.Forms content being rendered into a specific point in an already existing native page.

Its kinda-reversed, in thinking, however this is still possible:-

To achieve this you need to stimulate page-generation into a temporary new page.

For instance in WindowsPhone you would do this via:-

        PhoneApplicationPage objInnerPage_Temp = new PhoneApplicationPage();
        UIElement objInnerContent = App.GetMainPage().ConvertPageToUIElement(objInnerPage_Temp);

on the platform specific stub-page.

You can then inject the rendered contents into a native container that is appropriate on the platform, i.e. a Grid.

Update 1:-

==========

Although its very easy to do this on WindowsPhone it doesn't seem that this is possible when attempting something similar in Android unfortunately.

The Android page creation is very locked down, i.e. you can't gain access to the private fields for canvas and/or layout that it internally uses in AndroidActivity.

If this was possible then you could re-use this and take the contents rendered and inject similar to the solution for the WindowsPhone platform.

Furthermore, the Platform class is flagged as internal also, preventing another way to generate the rendered contents.

There was hope I was thinking from approaching this from a Fragment implementation of generating an Activity into it, and this could well work - However - the issue here is that the implementation in Xamarin.Forms is expecting the ActionBar to be available of which it is not, and they aren't checking for a if null scenario to allow execution to continue if it is not available so it throws an exception preventing page content generation.

It doesn't therefore look possible?, unless they open up the layout / canvas fields in AndroidActivity or address the ActionBar expectation issue.

Solution 2

As already discussed it is fairly simple on iOS (with .CreateViewController()) and WP (.ConvertPageToUIElement()).

But on Android all is not lost too: you can use .GetView() extension method from http://www.arturdr.ru/android/xamarin-forms-i-slozhnosti-integratsii-v-android-prilozheniya/

Here is an example on how to wrap Xamarin.Forms page in Android AlertDialog using that method: https://github.com/OlexaLe/XFPageAsAndroidDialog

Solution 3

Xamarin revised its website, so the image above is outdated. As the Xamarin.Forms library has evolved, it appears that it became tougher to mix Xamarin.Forms and platform-specific native views. I would not recommend doing this.

Advanced users can certainly attempt this, but my conversations with other developers suggest that this creates a lot of extra work and overhead. The best path forward is to either use Xamarin.Forms exclusively for your views, or use platform-specific native views.

Here's a screenshot from Xamarin's Xamarin.Forms page (shot taken on May 13, 2015):

enter image description here

Solution 4

You are probably looking for a custom renderer.

  • In your Forms project create a class MyView that inherits from View (or some other suitable class, say ContentView if you'll have child views etc)
  • In your Android project create a renderer class MyViewRenderer that inherits ViewRenderer
  • Add the attribute to that class that indicates it's a renderer before the namespace declaration [assembly: ExportRenderer (typeof(MyView), typeof(MyViewRenderer))]
  • In MyViewRenderer override OnElementChanged, call base.SetNativeView(ctl) where ctl is an instance of your native control

Take a look at Xamarin's guide

Another resource in Xamarin's Forums.

After looking at the issue and implementing my own Border I'd say VisualElementRenderer<TElement> is a better renderer to use. If you use that all you'd need to do is override OnElementChanged and do NativeView.Add(customUIView) and copy properties from the MyView instance. To handle dynamic changes in these properties override OnElementPropertyChanged and update the customUIView instance

Share:
14,429
Gulshan
Author by

Gulshan

Updated on June 08, 2022

Comments

  • Gulshan
    Gulshan almost 2 years

    I want to use Xamarin.Form Control inside my Native Android Page Controls. In my Android native page is there any way to load a Xamarin.Form Page inside my Native Android Fragment or LinearLayout?

    According to Xamarin it's possible. But I cannot find how to achieve this.

    http://xamarin.com/forms

  • Gulshan
    Gulshan over 9 years
    Yes I know that. The problem is Xamarin.Forms.Platform.Android.AndroidActivity has only one Method SetPage(Xamarin.Forms.Page page) which shows the Xamarin.Forms Page in full screen. What I want is, on my Activity I have lot of other native Android Controls. And In between those Controls I want to use my one Xamarin.Forms Page or View.
  • Gulshan
    Gulshan over 9 years
    Yes I am aware of custom renderer. But using a renderer, I think I can only achieve using a native controls inside a Xamarin.Forms Page. But my requirement is totally opposite. I want to use xamarin.Forms Page inside some Native Controls. If you look at the Activity where a Xamarin.Forms page has been used, There is a method "SetContentPage()" Which takes a XamarinForms Page as an input set it to the whole activity. What I am looking for is, A way where I can set my XamarinForm Page or Control inside a Layout or Fragement. Or if I can convert Xamarin.Forms.View to Android.Views.View.
  • Gulshan
    Gulshan over 9 years
    Yes I am aware of custom renderer. But using a renderer, I think I can only achieve using a native controls inside a Xamarin.Forms Page. But my requirement is totally opposite. I want to use xamarin.Forms Page inside some Native Controls. If you look at the Activity where a Xamarin.Forms page has been used, There is a method "SetContentPage()" Which takes a XamarinForms Page as an input set it to the whole activity. What I am looking for is, A way where I can set my XamarinForm Page or Control inside a Layout or Fragement. Or if I can convert Xamarin.Forms.View to Android.Views.View.
  • Sten Petrov
    Sten Petrov over 9 years
    how about a Forms Page that holds the native control in a custom renderer and a NativeChild custom renderer that can move its view as a subview of the native? I don't think it's possible to achieve this in a completely native app
  • Pete
    Pete over 9 years
    The last part of my answer did highlight what I believed your real intention was and suggested an approach. Its possible via WindowsPhone easily, however Android is very locked down. I've updated my answer to reflect new findings (see Update 1). Where are you seeing SetContentPage() for Android as I don't appear to be able to find this method?
  • Pete
    Pete over 9 years
    Its possible in WindowsPhone, however Android is too locked down it appears. I haven't tested this on iOS at present.
  • Gulshan
    Gulshan over 9 years
    Yes very much true. I was actually looking for a similar method in android like "ConvertPageToUIElement" in Windows Phone. I have extracted the code of AndroidActivity. And you are right the Platform class is marked as internal. So may be for now it's not possible.
  • ToolmakerSteve
    ToolmakerSteve about 6 years
    Unfortunately, significant changes would be required to update that code to work with current Xamarin Forms. I've added an issue to XFPageAsAndroidDialog project, briefly describing what is needed.