Last active
August 8, 2021 10:53
-
-
Save rudyryk/7b9633e847e727d12de7 to your computer and use it in GitHub Desktop.
C# — Measure string size in Xamarin.Forms for iOS and Android platforms
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// TextMeter.cs | |
// Created by Alexey Kinev on 11 Feb 2015. | |
// | |
// Licensed under The MIT License (MIT) | |
// http://opensource.org/licenses/MIT | |
// | |
// Copyright (c) 2015 Alexey Kinev <[email protected]> | |
// | |
// Usage example: | |
// | |
// var label = new Label { | |
// Text = "La-la-la-laaaaaaaaaaaaaaaaa! And even more La-la-la-laaaaa!", | |
// FontSize = 16.0, | |
// }; | |
// label.FontFamily = Device.OnPlatform ( | |
// iOS: "HelveticaNeue" | |
// Android: "Roboto" | |
// ); | |
// var labelHeight = TextMeter.MeasureTextSize( | |
// label.Text, 200, label.FontSize, label.FontFamily).Height; | |
// | |
using System; | |
using Xamarin.Forms; | |
#if __IOS__ | |
using System.Drawing; | |
using Foundation; | |
using UIKit; | |
namespace ZeroFiveBit.Forms.Utils | |
{ | |
public static class TextMeterImplementation | |
{ | |
public static Xamarin.Forms.Size MeasureTextSize(string text, double width, | |
double fontSize, string fontName = null) | |
{ | |
var nsText = new NSString(text); | |
var boundSize = new SizeF((float)width, float.MaxValue); | |
var options = NSStringDrawingOptions.UsesFontLeading | | |
NSStringDrawingOptions.UsesLineFragmentOrigin; | |
if (fontName == null) | |
{ | |
fontName = "HelveticaNeue"; | |
} | |
var attributes = new UIStringAttributes { | |
Font = UIFont.FromName(fontName, (float)fontSize) | |
}; | |
var sizeF = nsText.GetBoundingRect(boundSize, options, attributes, null).Size; | |
return new Xamarin.Forms.Size((double)sizeF.Width, (double)sizeF.Height); | |
} | |
} | |
} | |
#endif | |
#if __ANDROID__ | |
using Android.Widget; | |
using Android.Util; | |
using Android.Views; | |
using Android.Graphics; | |
namespace ZeroFiveBit.Forms.Utils | |
{ | |
public static class TextMeterImplementation | |
{ | |
private static Typeface textTypeface; | |
public static Xamarin.Forms.Size MeasureTextSize(string text, double width, | |
double fontSize, string fontName = null) | |
{ | |
var textView = new TextView(global::Android.App.Application.Context); | |
textView.Typeface = GetTypeface(fontName); | |
textView.SetText(text, TextView.BufferType.Normal); | |
textView.SetTextSize(ComplexUnitType.Px, (float)fontSize); | |
int widthMeasureSpec = Android.Views.View.MeasureSpec.MakeMeasureSpec( | |
(int)width, MeasureSpecMode.AtMost); | |
int heightMeasureSpec = Android.Views.View.MeasureSpec.MakeMeasureSpec( | |
0, MeasureSpecMode.Unspecified); | |
textView.Measure(widthMeasureSpec, heightMeasureSpec); | |
return new Xamarin.Forms.Size((double)textView.MeasuredWidth, | |
(double)textView.MeasuredHeight); | |
} | |
private static Typeface GetTypeface(string fontName) | |
{ | |
if (fontName == null) | |
{ | |
return Typeface.Default; | |
} | |
if (textTypeface == null) | |
{ | |
textTypeface = Typeface.Create(fontName, TypefaceStyle.Normal); | |
} | |
return textTypeface; | |
} | |
} | |
} | |
#endif | |
namespace ZeroFiveBit.Forms.Utils | |
{ | |
public static class TextMeter | |
{ | |
public static Xamarin.Forms.Size MeasureTextSize(string text, double width, | |
double fontSize, string fontName = null) | |
{ | |
return TextMeterImplementation.MeasureTextSize(text, width, fontSize, fontName); | |
} | |
} | |
} |
I see on Android that if I make a label with the text “iiiiiiiiiiiiiiiiiiii” and I compare the width of the label with the measured width of its text, for some font sizes (15, 16, 17, 23, 24, 25, 31, 32, 33) the difference is less than 1, but for others (18 to 22) the difference is about 6.
Text meter is now part of the misc utils package:
https://github.com/TheUniforms/Uniforms-Misc
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How should I use the code? I put it into the portable project of my Xamarin.Forms solution and it does not compile (“The name 'TextMeterImplementation' does not exist in the current context”), both “#if…#endif” blocks are greyed out and the compiler ignores them.
I had to use DependencyService to make it work.