【问题标题】:ViewGroup in ContentPage - ExportRenderer issue XamarinContentPage 中的 ViewGroup - ExportRenderer 问题 Xamarin
【发布时间】:2018-11-06 14:33:49
【问题描述】:

我想在 ContentPage 中添加一个 Android.Widget.RelativeLayout。为此,我遵循了多个在线示例:

Xamarin Forms Custom Renderer for Android not displaying

Adding an "Android.Views.ViewGroup" to a Xamarin XAML page

和其他人。

但我无法让它工作。

在我的共享项目中,我有:

namespace SharedProject
{
  public partial class App : Application
    {

        public App ()
        {
            InitializeComponent();

            MainPage = new NavigationPage(new MainPage());
        }
     ....
    }

空格

namespace SharedProject
{
    public class MyCustomViewControl : View
    {
        public MyCustomViewControl()
        {

        }
    }
}

以及正在呈现的 MainPage.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:SharedProject="clr-namespace:SharedProject;assembly=SharedProject"
             x:Class="SharedProject.MainPage">
    <ContentPage.Content>
        <StackLayout>
            <SharedProject:MyCustomViewControl
                                 HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

在 MonoAndroid 项目中:

[assembly: ExportRenderer(typeof(MyCustomViewControl), typeof(MyCustomViewRenderer))]
namespace SharedProject.Mobile.Droid
{
    public class MyCustomViewRenderer : ViewRenderer<MyCustomViewControl, RelativeLayout>
    {
        public MyCustomViewRenderer(Context context) : base(context)
        {

        }

        private Android.Widget.RelativeLayout rlMainContainer;

        protected override void OnElementChanged(ElementChangedEventArgs<MyCustomViewControl> e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null || Element == null)
            {
                return;
            }

            rlMainContainer = new RelativeLayout(Context);
            rlMainContainer.SetMinimumHeight(50);
            rlMainContainer.SetMinimumWidth(100);
            rlMainContainer.LayoutParameters = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MatchParent, RelativeLayout.LayoutParams.MatchParent);

            if (Control == null)
                SetNativeControl(rlMainContainer);

            MainActivity.instance.setActiveReader(Control);
        }
    }
}

在我的 MainActivity.OnCreate 我有:

protected override void OnCreate(Bundle savedInstanceState)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(savedInstanceState);
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);


            instance = this;

            LoadApplication(new App());

我期待在渲染 MainPage 时,也会根据 MainPage.xaml 和 OnElementChanged 将 rlMainContainer 添加到其中,但未请求 MyCustomViewRenderer 内部的任何内容(没有断点命中)。

我做错了什么?

【问题讨论】:

    标签: xamarin xamarin.forms xamarin.android


    【解决方案1】:

    我刚刚将您的代码插入到一个新项目中,只要我明确说明我想使用哪个 RelativeLayout,它就可以正常工作。有 2 种可能,Xamarin.Forms.RelativeLayout 和 Android.Widget.Relative 布局。我假设您想要后者,但我不认为它是完全合格的,并且因为我假设您对 Xamarin.Forms(ExportRenderer 属性需要)和 Android.Widget(RelativeLayout 需要)都有 using 语句,所以它是不清楚您是否在所有地方都使用了正确的 RelativeLayout。

    还有一个问题是您使用的是Xamarin.Forms.Platform.Android.AppCompat.ViewRenderer 还是Xamarin.Forms.Platform.Android.ViewRenderer。大多数使用 AppCompat 作为默认 Xam.Forms 模板使用 FormsAppCompatActivity。因此,假设您使用的是 AppCompat,则自定义渲染器的以下完整源代码(必要时具有完整的类型限定)正在我这边工作:

    using System;
    using Android.Content;
    using TestRelLayout;
    using TestRelLayout.Droid;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.Android;
    
    [assembly: ExportRenderer(typeof(MyCustomViewControl), typeof(MyCustomViewRenderer))]
    namespace TestRelLayout.Droid
    {
        public class MyCustomViewRenderer : Xamarin.Forms.Platform.Android.AppCompat.ViewRenderer<MyCustomViewControl, Android.Widget.RelativeLayout>
        {
            public MyCustomViewRenderer(Context context) : base(context)
            {
            }
    
            private Android.Widget.RelativeLayout rlMainContainer;
    
    
            protected override void OnElementChanged(ElementChangedEventArgs<MyCustomViewControl> e)
            {
                base.OnElementChanged(e);
    
                if (e.OldElement != null || Element == null)
                {
                    return;
                }
    
                rlMainContainer = new Android.Widget.RelativeLayout(Context);
                rlMainContainer.SetMinimumHeight(50);
                rlMainContainer.SetMinimumWidth(100);
                rlMainContainer.LayoutParameters = new Android.Widget.RelativeLayout.LayoutParams(Android.Widget.RelativeLayout.LayoutParams.MatchParent, Android.Widget.RelativeLayout.LayoutParams.MatchParent);
                // set the background color to make it easy to see if renderer is working               
                rlMainContainer.SetBackgroundColor(
                            Android.Graphics.Color.Aquamarine);
    
                if (Control == null)
                    SetNativeControl(rlMainContainer);
    
                // did not bother to set this up in my MainActivity
                //MainActivity.instance.setActiveReader(Control);
            }
        }
    }
    

    【讨论】:

    • 感谢您提供如此全面的答案。关于RelativeLayout 部分,我有一个类似using RelativeLayout = Android.Widget.RelativeLayout; 的使用语句,这应该没问题,但我使用的是Xamarin.Forms.Platform.Android.ViewRenderer。我会尝试另一个,但他们在他们的网站docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/… 或其他答案上没有提及 AppCombat。从现在开始,我还将在我的问题中发布 using 语句。
    【解决方案2】:

    你为什么要渲染原生的 Android 相对布局? Xamarin.Forms 中有内置选项。看看这个documentation

    【讨论】:

    • 这不是答案,最好将其添加为评论。我实际上需要一个 ViewGroup 元素(在我的例子中是相对布局),因为我想将它用作另一个函数中的参数。
    • 好的,如果您在 Forms 中工作,为什么您希望将 RelativeLayout 作为函数中的参数?
    • 因为我正在使用一个期望它的外部库。
    【解决方案3】:

    经过大量文件比较(我的项目和微软示例之一),我发现问题与

    MainPage = new NavigationPage(new MainPage());.

    为了解决这个问题,我刚刚删除了 NavigationPage 包装器。

    MainPage = new MainPage();.

    还不知道为什么会这样,但如果有人知道,请编辑我的答案并附上解释。

    编辑:渲染器也可以与NavigationPage 一起使用,但仅在 OnCreate 方法完成执行之后。

    【讨论】:

    • 奇怪,我在测试中使用了导航页面,并且有效。一定是您发布的代码中未显示的其他事情。
    • @jgoldberger 是的,我刚刚使用了 Microsoft 的 CustomRenderer,看来如果您使用 NavigationPage 包装器,渲染器将工作,但只有在 onCreate 方法完成执行后才能工作。跨度>
    猜你喜欢
    • 1970-01-01
    • 2021-04-11
    • 2018-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多