Skip to content

Instantly share code, notes, and snippets.

@rudyryk
Last active August 8, 2021 10:53
Show Gist options
  • Save rudyryk/7b9633e847e727d12de7 to your computer and use it in GitHub Desktop.
Save rudyryk/7b9633e847e727d12de7 to your computer and use it in GitHub Desktop.
C# — Measure string size in Xamarin.Forms for iOS and Android platforms
//
// 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);
}
}
}
@rudyryk
Copy link
Author

rudyryk commented Jan 19, 2016

@JamesKelley this is maximum text width in pixels to fit in. It is common to have limited width and variable height, i.e. in news feed with text posts etc. For example, you may pass screen width minus left and right padding, that actually depends on your layout.

@Aspro1
Copy link

Aspro1 commented Feb 16, 2016

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.

@Aspro1
Copy link

Aspro1 commented Feb 16, 2016

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.

@rudyryk
Copy link
Author

rudyryk commented Sep 29, 2016

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