Customize default legends
You can quickly change the position, the font, the text size or the background color:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamarinSample.Axes.Multiple.View"
xmlns:lvc="clr-namespace:LiveChartsCore.SkiaSharpView.Xamarin.Forms;assembly=LiveChartsCore.SkiaSharpView.XamarinForms"
xmlns:vms="clr-namespace:ViewModelsSamples.Axes.Multiple;assembly=ViewModelsSamples">
<ContentPage.BindingContext>
<vms:ViewModel/>
</ContentPage.BindingContext>
<lvc:CartesianChart
Series="{Binding Series}"
YAxes="{Binding YAxes}"
LegendPosition="Bottom"
LegendBackgroundPaint="{Binding LegendTextPaint}"
LegendTextPaint="{Binding LegendTextPaint}"
LegendTextSize="16">
</lvc:CartesianChart>
</ContentPage>
View model
[ObservableObject]
public partial class ViewModel
{
public ISeries[] Series { get; set; } = { ... };
public Axis[] YAxes { get; set; } = { ... };
public SolidColorPaint LegendTextPaint { get; set; } = // mark
new SolidColorPaint // mark
{ // mark
Color = new SKColor(50, 50, 50), // mark
SKTypeface = SKTypeface.FromFamilyName("Courier New") // mark
}; // mark
public SolidColorPaint LedgendBackgroundPaint { get; set; } = // mark
new SolidColorPaint(new SKColor(240, 240, 240)); // mark
}
Tooltip control from scratch
You can also create your own legend, the recommended way is to use the LiveCharts API (example bellow) but you can
use anything as tooltip as soon as it implements the IChartLegend<T>
interface. At the following example we build
a custom control to render legends in our charts using the LiveCharts API.
CustomLegend.cs
using System.Linq;
using LiveChartsCore;
using LiveChartsCore.Drawing;
using LiveChartsCore.Kernel.Sketches;
using LiveChartsCore.Measure;
using LiveChartsCore.SkiaSharpView.Drawing;
using LiveChartsCore.SkiaSharpView.Drawing.Geometries;
using LiveChartsCore.SkiaSharpView.Painting;
using LiveChartsCore.SkiaSharpView.VisualElements;
using LiveChartsCore.VisualElements;
using SkiaSharp;
namespace ViewModelsSamples.General.TemplatedLegends;
public class CustomLegend : IChartLegend<SkiaSharpDrawingContext>, IImageControl
{
private static readonly int s_zIndex = 10050;
private StackPanel<RoundedRectangleGeometry, SkiaSharpDrawingContext>? _stackPanel;
private readonly SolidColorPaint _backgroundPaint = new(new SKColor(28, 49, 58)) { ZIndex = s_zIndex };
private readonly SolidColorPaint _fontPaint = new(new SKColor(230, 230, 230)) { ZIndex = s_zIndex + 1 };
public LvcSize Size { get; set; }
public void Draw(Chart<SkiaSharpDrawingContext> chart)
{
if (chart.LegendPosition == LegendPosition.Hidden) return;
Measure(chart);
if (_stackPanel is null) return;
var actualChartSize = chart.ControlSize;
if (chart.LegendPosition == LegendPosition.Top)
{
chart.Canvas.StartPoint = new LvcPoint(0, Size.Height);
_stackPanel.X = actualChartSize.Width * 0.5f - Size.Width * 0.5f;
_stackPanel.Y = -Size.Height;
}
if (chart.LegendPosition == LegendPosition.Bottom)
{
_stackPanel.X = actualChartSize.Width * 0.5f - Size.Width * 0.5f;
_stackPanel.Y = actualChartSize.Height;
}
if (chart.LegendPosition == LegendPosition.Left)
{
chart.Canvas.StartPoint = new LvcPoint(Size.Width, 0);
_stackPanel.X = -Size.Width;
_stackPanel.Y = actualChartSize.Height * 0.5f - Size.Height * 0.5f;
}
if (chart.LegendPosition == LegendPosition.Right)
{
_stackPanel.X = actualChartSize.Width;
_stackPanel.Y = actualChartSize.Height * 0.5f - Size.Height * 0.5f;
}
chart.AddVisual(_stackPanel);
}
public void Measure(IChart chart)
{
var skiaChart = (Chart<SkiaSharpDrawingContext>)chart;
BuildLayout(skiaChart);
if (_stackPanel is null) return;
Size = _stackPanel.Measure(skiaChart, null, null);
}
private void BuildLayout(Chart<SkiaSharpDrawingContext> chart)
{
_stackPanel ??= new StackPanel<RoundedRectangleGeometry, SkiaSharpDrawingContext>
{
Padding = new Padding(15),
Orientation = ContainerOrientation.Vertical,
HorizontalAlignment = Align.Start,
VerticalAlignment = Align.Middle,
BackgroundPaint = _backgroundPaint
};
// clear the previous elements.
foreach (var child in _stackPanel.Children.ToArray())
{
_ = _stackPanel.Children.Remove(child);
chart.RemoveVisual(child);
}
foreach (var series in chart.ChartSeries)
{
var sketch = series.GetMiniatresSketch();
var relativePanel = sketch.AsDrawnControl();
var label = new LabelVisual
{
Text = series.Name ?? string.Empty,
Paint = _fontPaint,
TextSize = 15,
Padding = new Padding(8, 0, 0, 0),
VerticalAlignment = Align.Start,
HorizontalAlignment = Align.Start
};
var sp = new StackPanel<RoundedRectangleGeometry, SkiaSharpDrawingContext>
{
Padding = new Padding(0, 4),
VerticalAlignment = Align.Middle,
HorizontalAlignment = Align.Middle,
Children =
{
relativePanel,
label
}
};
_ = _stackPanel?.Children.Add(sp);
}
}
}
View
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamarinSample.General.TemplatedLegends.View"
xmlns:lvc="clr-namespace:LiveChartsCore.SkiaSharpView.Xamarin.Forms;assembly=LiveChartsCore.SkiaSharpView.XamarinForms"
xmlns:vms="clr-namespace:ViewModelsSamples.General.TemplatedLegends;assembly=ViewModelsSamples"
xmlns:core="clr-namespace:LiveChartsCore;assembly=LiveChartsCore">
<ContentPage.BindingContext>
<vms:ViewModel/>
</ContentPage.BindingContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<lvc:CartesianChart Grid.Row="0" Series="{Binding Series}" LegendPosition="Bottom">
<!-- mark -untilCloses CartesianChart.Legend -->
<lvc:CartesianChart.Legend>
<vms:CustomLegend></vms:CustomLegend>
</lvc:CartesianChart.Legend>
</lvc:CartesianChart>
</Grid>
</ContentPage>