Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom renderers are not working #56

Open
shannonpahl opened this issue Sep 17, 2020 · 2 comments
Open

Custom renderers are not working #56

shannonpahl opened this issue Sep 17, 2020 · 2 comments

Comments

@shannonpahl
Copy link

shannonpahl commented Sep 17, 2020

When I create a custom renderer and set the chart property to use the custom renderer, the overridden methods in the custom renderer are not being called. The result just looks like the default renderer is still being used and its not calling into the overridden methods. This is the case for the XAxisRenderer, YAxisRenderer (lazy vars) and the chart renderer (normal var). I can subclass the chartview and override its methods and that works, both when the chartview is created in code or using interface builder. I've attached a sample project with these issues. Is there an easy fix or workaround, or is something else needed to make the assignment work? This works well in Xamarin.Android.

ioscharts_overrides.zip

`

public class SimpleBarChart : BarChartView
{
    public SimpleBarChart() { }

    public SimpleBarChart(IntPtr handle) : base(handle) { }

    public void Configure()
    {
        // Custom XAxisRenderer not working
        XAxisRenderer = new SimpleXAxisRenderer(
            ViewPortHandler,
            XAxis,
            GetTransformerForAxis(AxisDependency.Left));

        // Custom chart renderer not working
        Renderer = new SimpleBarChartRenderer(this, ChartAnimator, ViewPortHandler);

        var points = new BarChartDataEntry[]
        {
            new BarChartDataEntry(0, 1),
            new BarChartDataEntry(1, 2),
            new BarChartDataEntry(2, 4),
        };

        var dataset = new BarChartDataSet(points, "series 1");
        var barData = new BarChartData();
        barData.AddDataSet(dataset);
        Data = barData;
    }
}


public class SimpleXAxisRenderer : ChartXAxisRenderer
{
    public SimpleXAxisRenderer(ChartViewPortHandler viewportHandler, ChartXAxis xAxis, ChartTransformer transformer)
        : base(viewportHandler, xAxis, transformer)
    {
    }

    public override void ComputeAxisValuesWithMin(double min, double max)
    {
        // place breakpoint here: never gets called
        Trace.Log();
        base.ComputeAxisValuesWithMin(min, max);
    }
}


public class SimpleBarChartRenderer : BarChartRenderer
{
    public SimpleBarChartRenderer(IBarChartDataProvider dataProvider, ChartAnimator animator, ChartViewPortHandler viewportHandler)
        : base(dataProvider, animator, viewportHandler)
    {
    }

    public override void DrawDataWithContext(CGContext context)
    {
        // place breakpoint here: never gets called
        Trace.Log();
        base.DrawDataWithContext(context);
    }

    public override void DrawExtrasWithContext(CGContext context)
    {
        // place breakpoint here: never gets called
        Trace.Log();
        base.DrawExtrasWithContext(context);
    }
}

`

@AaronBastian
Copy link

AaronBastian commented Sep 29, 2020

I am having a similar issue:

public class YAxisRenderer : ChartYAxisRenderer
{
   public YAxisRenderer(ChartViewPortHandler viewPortHandler, ChartYAxis yAxis, ChartTransformer transformer) : base(viewPortHandler, yAxis, transformer) { }

   public override void RenderLimitLinesWithContext(CGContext context)
   {
      // breakpoint not getting hit
      base.RenderLimitLinesWithContext(context);
      // tons of custom line rendering here
   }
}

Any help on this would be greatly appreciated.

@shannonpahl
Copy link
Author

Unfortunately, there is no good solution here. The issue is with how interop works between Swift and C#: For Objective-C and Java, this all works as you would expect. We have it working well on Android. The problem is when you override a Swift method that starts off as a Swift method. ie. You can override any UIView method (eg Draw in a ChartView) but you cannot override any of the methods of the Renderers as the base methods start off in Swift. The Renderer property in the Chart is a Swift object so you have to derive from the Swift class to be able to set the property. If the property was defined as an interface type (eg ValueFormatters) then you can just implement the interface, set the property and have all the code in C#. This works fine. But for Renderers, you need to derive from the Renderer, add a C# method to do all the drawing you need and then call that method from your Draw method that you override in the Chart. You also need to use the enable property of that feature (in your case limit lines) so the base implementation does not also draw limit limes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants