1
votes

I'm using SkiaSharp in Xamarin Forms. My goal is to ensure that the font displayed in Xamarin controls, e.g. a Label, matches the font used in SkiaSharp drawing.

In addition, I want to use the default font so that the app looks right on its respective platform and adheres to user preferences.

In my simple app, I have some Xamarin labels and I have a custom control drawn by SkiaSharp. The two have different fonts, though they are very close. SkiaSharp has the same look but is about 10% smaller. And Xamarin has wider antialiasing.

See clip of screenshot (top: SkiaSharp, bottom: Xamarin):

top:SkiaSharp, bottom:Xamarin

I'm not sure how to solve this. There are at least a couple approaches:

  1. How can I determine the font being used for a Xamarin Label ? If I can determine this, I should be able to set it for SkiaSharp drawing.
  2. Or, how do I set the Xamarin font to that being used by SkiaSharp. I can get the font family from SkiaSharp during runtime but I don't know how to set it in Xamarin during runtime.

I guess a third alternative is to do all fonts via SkiaSharp. But then I won't be able to use any Xamarin controls that display text.

1
Hi, about modify font on runtime, you could have a look at this discussion, it may be helpful.Junior Jiang
I'm hoping there's a Xamarin solution. That link has a solution for Android and a separate solution for iOS. No solution for UWP (though I'm sure there is one). Further, they are not written using Xamarin Forms, and may use completely different APIs.Peri Hartman

1 Answers

0
votes

Generally, the SkiaSharp use the default system text font to draw text.

If you could set the TextSize to fit the default FontSize, you will see they will show the same.

Have a look at this screenshot:

enter image description here

The one above is Label and the one below is SKCanvasView in Xaml:

<Label Text="Hello SkiaSharp!" x:Name="mylabel" VerticalOptions="Start" FontSize="Large" HorizontalOptions="CenterAndExpand" />
<forms:SKCanvasView PaintSurface="OnCanvasViewPaintSurface" />

The OnCanvasViewPaintSurface method is:

void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
    SKImageInfo info = args.Info;
    SKSurface surface = args.Surface;
    SKCanvas canvas = surface.Canvas;

    canvas.Clear();

    string str = "Hello SkiaSharp!";

    // Create an SKPaint object to display the text
    SKPaint textPaint = new SKPaint
    {
        Color = SKColors.Chocolate
    };

    // Adjust TextSize property so text is 90% of screen width
    float textWidth = textPaint.MeasureText(str);
    //textPaint.TextSize = 0.9f * info.Width * textPaint.TextSize / textWidth;
    textPaint.TextSize = (float)((float)mylabel.FontSize*(2.6));

    //textPaint.Typeface = SKTypeface.FromFamilyName("monospace");

    // Find the text bounds
    SKRect textBounds = new SKRect();
    textPaint.MeasureText(str, ref textBounds);

    // Calculate offsets to center the text on the screen
    float xText = info.Width / 2 - textBounds.MidX;
    float yText = info.Height / 2 - textBounds.MidY;

    // And draw the text
    canvas.DrawText(str, xText, yText, textPaint);

    // Create a new SKRect object for the frame around the text
    SKRect frameRect = textBounds;
    frameRect.Offset(xText, yText);
    frameRect.Inflate(10, 10);

    // Create an SKPaint object to display the frame
    SKPaint framePaint = new SKPaint
    {
        Style = SKPaintStyle.Stroke,
        StrokeWidth = 5,
        Color = SKColors.Blue
    };

    // Draw one frame
    canvas.DrawRoundRect(frameRect, 20, 20, framePaint);

    // Inflate the frameRect and draw another
    frameRect.Inflate(10, 10);
    framePaint.Color = SKColors.DarkBlue;
    canvas.DrawRoundRect(frameRect, 30, 30, framePaint);
}