Hi All,
My requirement is to calculate the width of a text that is inside a Label. This calculated width is set as the width of the Label. In other words the labels width is equal to the width of the text inside it. Is there any method to achieve this in XForms like we have methods in Xamarin.Android and Xamarin.iOS ? Or is there any workaround ?
Note : I dont want the text length that returns the number of characters in the string, instead the extent width of the string.
Thanks in Advance !!
Hey Guys i sorted out a solution long back !!! My bad that i did not post the answer.
You can achieve the requirement by using the concept of Dependency Services. You declare an interface in the PCL project where you expose a method to calculate the text length. You can implement this interface in the Forms android,iOS and Windows projects.
You pass the text to the individual platform specific implementation, where you create a equivalent view ( TextView for Android, UILabel for iOS etc) and set the text as the text of the view and then measure it using native codes. Please refer the code snippets incase my description is unclear.
PCL INTERFACE DECLARATION
public interface CalculateTextWidth { double calculateWidth (string text); }
ANDROID IMPLEMENTATION
`public class CalculateTextWidth_Android : CalculateTextWidth
{
public CalculateTextWidth_Android () {}
public double calculateWidth (string text) { Rect bounds = new Rect(); TextView textView = new TextView(Forms.Context); textView.Paint.GetTextBounds(text, 0, text.Length, bounds); var length = bounds.Width(); return length / Resources.System.DisplayMetrics.ScaledDensity; } }`
iOS IMPLEMENTATION
`public class CalculateTextWidth_iOS : CalculateTextWidth
{
UILabel uiLabel ;
CGSize length;
public CalculateTextWidth_iOS ()
{
}
public double calculateWidth (string text) { uiLabel = new UILabel (); uiLabel.Text = text; length = uiLabel.Text.StringSize (uiLabel.Font); return length.Width; } }`
WINDOWS PHONE IMPLEMENTATION
`public class CalculateTextWidth_WinPhone : CalculateTextWidth
{
public CalculateTextWidth_WinPhone() {}
public double calculateWidth(string text) { var textBlock = new TextBlock() { FontSize = 12 }; textBlock.Text = text; var parentBorder = new Border { Child = textBlock }; textBlock.MaxHeight = 50; textBlock.MaxWidth = double.PositiveInfinity; parentBorder.Measure(new System.Windows.Size(textBlock.MaxWidth, textBlock.MaxHeight)); parentBorder.Child = null; return parentBorder.DesiredSize.Width; } }`
WinRT IMPLEMENTATIONpublic double calculateWidth(string text) { var textBlock = new TextBlock() { FontSize = 12 }; textBlock.Text = text; var parentBorder = new Border { Child = textBlock }; textBlock.MaxHeight = 50; textBlock.MaxWidth = double.PositiveInfinity; parentBorder.Measure(new System.Windows.Size(textBlock.MaxWidth, textBlock.MaxHeight)); parentBorder.Child = null; return parentBorder.DesiredSize.Width; }
Please leave a comment in case of any queries
Regards,
Vimal Prabhu
Answers
I also need to do this in Xamarin.Forms. I have an absolute layout that I store labels in. I need them to go at specific locations which requires me to get the width/height at runtime based on the text/Font. How can this be achieved? Something similar to the graphics.MeasureString would be optimal.
@JeffreyVoigt you can override the Measure function of the parent layout (create a custom layout similar to AbsoluteLayout) and call measure for the individual labels in that phase. However, that might be overkill depending on what exactly you're trying to achieve.
I have a similar requirement. I have a number of fixed-size Views on a row, but in the space remaining what to put a timer (as a Label) in HH:MM:SS format. If the screen width cannot fit the whole of that in, I want it to fallback to just HH:MM , or even just HH if it cannot fit HH:MM in.
Given a FontFamily, FontSize and FontAttributes, I'd be after a method that calculates the horizontal text extent for the text that would go in a particular View (most important being a Label, but it would be good if it worked for Button too).
I do have workarounds for my particular scenario, but a method that gets the horizontal text extent, that works across platforms, would be the ideal.
An alternative (which I know Xamarin have been asked for previously) is to have an API that specifies that the FontSize should be set automatically such that the specified Text fits within the Width available using the largest font that results in the text fitting.
Hey Guys i sorted out a solution long back !!! My bad that i did not post the answer.
You can achieve the requirement by using the concept of Dependency Services. You declare an interface in the PCL project where you expose a method to calculate the text length. You can implement this interface in the Forms android,iOS and Windows projects.
You pass the text to the individual platform specific implementation, where you create a equivalent view ( TextView for Android, UILabel for iOS etc) and set the text as the text of the view and then measure it using native codes. Please refer the code snippets incase my description is unclear.
PCL INTERFACE DECLARATION
public interface CalculateTextWidth { double calculateWidth (string text); }
ANDROID IMPLEMENTATION
`public class CalculateTextWidth_Android : CalculateTextWidth
{
public CalculateTextWidth_Android () {}
iOS IMPLEMENTATION
`public class CalculateTextWidth_iOS : CalculateTextWidth
{
UILabel uiLabel ;
CGSize length;
public CalculateTextWidth_iOS ()
{
}
WINDOWS PHONE IMPLEMENTATION
`public class CalculateTextWidth_WinPhone : CalculateTextWidth
{
public CalculateTextWidth_WinPhone() {}
WinRT IMPLEMENTATION
public double calculateWidth(string text) { var textBlock = new TextBlock() { FontSize = 12 }; textBlock.Text = text; var parentBorder = new Border { Child = textBlock }; textBlock.MaxHeight = 50; textBlock.MaxWidth = double.PositiveInfinity; parentBorder.Measure(new System.Windows.Size(textBlock.MaxWidth, textBlock.MaxHeight)); parentBorder.Child = null; return parentBorder.DesiredSize.Width; }
Please leave a comment in case of any queries
Regards,
Vimal Prabhu
@Vimal.4745 - Many thanks. When I have time, I'll tweak it so that this uses a FontSize that is passed in, rather than a hard-coded size, but this is a great starting point.
Thanks Vimal but I am facing some problems in implementing that function. Some how the function is not returning correct values for height. It is always returning height for one line unless there is carriage return in the text. I have implemented it like this
Can you please help
Thanks Vimal. I have implemented your code in windows RT but I am facing some problems in getting the desired results for height. I have implemented this code
I am not getting correct height. I am always getting height for one line unless there is carriage return in the text
Problem resolved just insert
textBlocktb.TextWrapping = TextWrapping.Wrap;
I want to know how to measure textview height .Please answer to me.
I like @Vimal.4745's answer, but there are several things I am having trouble figuring out how to do. First, I need to calculate the size in the Xamarin.Forms project, but I need a TextView in your method. This makes since, and I understand why, but I would like to know if there is a way to use the Renderer to convert my Label to a TextView to be used in the measurer (so that I do not need to manually set all the properties by hand)? My Label(s) use Style(s) which are located in my Xamarin.Forms project, and the Style(s) obviously target Label(s) (not TextView(s)) I think my basic question is how do I use your code from my Xamarin.Forms project? Thanks.