Florian
Florian

Reputation: 485

Custom Renderer for ContentView (iOS)

I have a delared the following

public class ViewBase : ContentView
{
    //...
}

When I use that in XAML

<local:ViewBase xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    xmlns:local="clr-namespace:MyForms;"
    x:Class="MyForms.Finder" 
    BackgroundColor="Color.Yellow">

    <!-- ... -->

</local:ViewBase>

When I use a CustomRenderer for that and even (as below) do nothing in it, the BackgroundColor from above is not set. When I don't define the following lines the background is yellow as expected.

[assembly: ExportRenderer(typeof(ViewBase), typeof(ViewRendererBase))]
namespace MyiOS
{    
    public class ViewRendererBase : ViewRenderer
    {
    }
}

BackgroundColor is a Property of ViewRenderer. I had a look into the code, it seems as Control is no set (I don't call SetNativeControl) it can't set Control.BackgroundColor to a value. But why does this happen? My guess is that something is wrong with the inheritance of ViewRenderer, as the default behaviour uses something different on ContentView!?

Upvotes: 3

Views: 3587

Answers (1)

jgoldberger - MSFT
jgoldberger - MSFT

Reputation: 6098

Not sure whether this is a bug in our docs [1] or a bug in the iOS ViewRenderer code [2] for the SetBackgroundColor method. So there are a couple of ways to workaround this. One is to have your custom renderer inherit from VisualElementRenderer<T> instead, e.g.:

public class ViewBaseRenderer : VisualElementRenderer<ContentView>
{
    //...
}

When checking on the default renderer type in iOS code with:

var contentRenderer = Platform.CreateRenderer(new ContentView())
var rendererType = contentRenderer.GetType();

rendererType is a VisualElementRenderer<T>, so this would seem to be the default renderer that is used by Forms, so it would seem to be a bug in the docs.

Another "workaround" would be to use the ViewRenderer but override the SetBackgroundColor method:

public class ViewBaseRenderer : ViewRenderer
{
    protected override void SetBackgroundColor(Color color)
    {
        base.SetBackgroundColor(color);

        if (NativeView == null)
            return;

        if (color != Color.Default)
            NativeView.BackgroundColor = color.ToUIColor();
    }

I have brought this up with the Xamarin Forms team to determine whether it is a bug in the docs or a bug in the Forms iOS Platform code for the ViewRenderer. If you look at the forms source code I linked [2] you will see that if Control is null, which it is in this case, the background color is never set. By overriding and adding the code to set the background color for NativeView then you can workaround this possible bug.

So apparently it seems the docs are in error. If you use ViewRenderer you have to set the Control yourself. Other renderers that inherit from ViewRenderer, like LabelRender, set the Control already, but ViewRenderer does not, so you would have to call SetNativeControl() in the OnElementChanged override to create and set a native control. See this forum post [3]. Personally, I think that one should inherit from the renderer that is used by default, which in this case is a VisualElementRenderer<T>

[1] https://developer.xamarin.com/guides/xamarin-forms/custom-renderer/renderers/#Layouts

[2] https://github.com/xamarin/Xamarin.Forms/blob/74cb5c4a97dcb123eb471f6b1dffa1267d0305aa/Xamarin.Forms.Platform.iOS/ViewRenderer.cs#L99

[3] https://forums.xamarin.com/discussion/comment/180839#Comment_180839

Upvotes: 5

Related Questions