Closed JoshuaNovak919 closed 8 years ago
Hi Joshua. I still need to figure it out how to propagate request layout down to each children. Stay tuned. Thanks
By the way, you dont need to specify HeightRequest for everything. For example grid row * and Auto works. Layouts FillAndExpand works. Padding, spacing properties works. Only some elements like Label, Button, BoxView needs HeightRequest...
Label HeightRequest = to their font size :)
@alexrainman Yeah I tried that, but depending on the font, it isn't exactly the right size. I got that working by manually setting it up. It seems that Orientation="Horizontal"
on StackLayouts doesn't work and Positioning in an AbsoluteLayout
doesn't work either.
Its possible to calculate the height using font size and the amount of text to place. I will do my testing based on your comments. Thanks
J, you are right, Horizontal StackLayout doesn't works and no idea why :) you can use a two column Grid instead.
I tested AbsoluteLayout and it works like a charm :)
And RelativeLayout works too.
@alexrainman AbsoluteLayout
works depending on what position you use. If you use AutoSize
for height or width then it won't work. I'm using PositionProportional
and I had to define height and width for all the elements to get it to work.
That's the problem, AutoSize doesn't works. As i said, you must request height 'til i find the way of requesting layout to all children. This the first version of the Control and it took me while to understand the obscure non-documented Xamarin.Forms RenderFactory API. I will share with you a way to calculate label height in a cross-platform way :)
@alexrainman I figured out a way to calculate the height by just adding a few pixels to the font size, but the issue is calculating the width, it is quite difficult.
This is what i use to calculate the width:
var width = Navigation.NavigationStack.First().Width - x;
x = sum of padding from left and right sides. If you have columns, then just do the math :)
Then to calculate height use this:
public interface ITextMeter
{
double MeasureTextSize(string text, double width, double fontSize, string fontName = null);
}
[assembly: Xamarin.Forms.Dependency(typeof(TextMeterImplementation))]
namespace YourNamespace.iOS
{
public class TextMeterImplementation : ITextMeter
{
//public static Xamarin.Forms.Size MeasureTextSize(string text, double width, double fontSize, string fontName = null)
public double 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);
return (double)sizeF.Height;
}
}
}
[assembly: Xamarin.Forms.Dependency(typeof(TextMeterImplementation))]
namespace YourNamespace.Droid
{
public class TextMeterImplementation : ITextMeter
{
private Typeface textTypeface;
public double MeasureTextSize(string text, double width, double fontSize, string fontName = null) {
var paint = new TextPaint(PaintFlags.AntiAlias | PaintFlags.SubpixelText);
paint.TextSize = (float)fontSize;
paint.SetTypeface(GetTypeface(fontName));
int lineCount = 0;
int index = 0;
int length = text.Length;
while(index < length - 1) {
index += paint.BreakText(text, index, length, true, (float)width, null);
lineCount++;
}
var bounds = new Rect();
paint.GetTextBounds(text, 0, length, bounds);
return (double)lineCount * bounds.Height() + 3;
}
private Typeface GetTypeface(string fontName)
{
if (fontName == null)
{
return Typeface.Default;
}
if (textTypeface == null)
{
textTypeface = Typeface.Create(fontName, TypefaceStyle.Normal);
}
return textTypeface;
}
}
}
I found a fix for this. Expect version 2 soon :)
Hi, I tested your fix and I left a comment.
Can you help me ?
https://gist.github.com/alexrainman/82b00160ab32bef9e69dee6d460f44fa#comments
Thank you
Can you use CVLabel custom control provided by the plugin and let me know if height is correct? Thats what i advice, use CVLabel and for the rest of controls provide HeightRequest with OnPlatform using the default ones.
I've just use your TextMeterImplementation with Xamarin Label. It works on iOS but not on Android.
Now It works on Android for me. I fixed my issue with this :
public float GetDensity()
{
return global::Android.App.Application.Context.Resources.DisplayMetrics.Density;
}
public double 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.Dip, (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);
var density = global::Android.App.Application.Context.Resources.DisplayMetrics.Density;
return ((double)textView.MeasuredHeight / density) + 5;
}
Example :
var density = textMeter.getDensity() -> 1 for iOS and global::Android.App.Application.Context.Resources.DisplayMetrics.Density for Android
Height = (int)textMeter.MeasureTextSize(alert.CurrentText, (App.ScreenWidth / nbColumns) - 30 * density, 15.0, "Roboto-Regular");
EDIT: 09/01/2016
I didn't work when I changed textsize in android settings (display section) because I used Dip instead of Sp (recommended for text size)
but this work for me now :
public float GetDensity()
{
return global::Android.App.Application.Context.Resources.DisplayMetrics.Density;
}
public double 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.Sp, (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);
var density = global::Android.App.Application.Context.Resources.DisplayMetrics.Density;
return ((double)textView.MeasuredHeight / density) + 5;
}
It doesn't works for me :(
This is what i use internally in TextMeter Android:
private Typeface textTypeface;
public double 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 = AViews.View.MeasureSpec.MakeMeasureSpec(
(int)width, AViews.MeasureSpecMode.AtMost);
int heightMeasureSpec = AViews.View.MeasureSpec.MakeMeasureSpec(
0, AViews.MeasureSpecMode.Unspecified);
textView.Measure(widthMeasureSpec, heightMeasureSpec);
return (double)textView.MeasuredHeight;
}
private Typeface GetTypeface(string fontName)
{
if (fontName == null)
{
return Typeface.Default;
}
if (textTypeface == null)
{
textTypeface = Typeface.Create(fontName, TypefaceStyle.Normal);
}
return textTypeface;
}
CVLabel.cs
public class CVLabel : Label
{
public CVLabel()
{
SetBinding(Label.HeightRequestProperty, new Binding("WidthRequest", BindingMode.Default, new LabelHeightConverter(), this, null, this));
}
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
WidthRequest = width;
this.LayoutTo(new Rectangle(this.X, this.Y, width, height));
this.InvalidateMeasure();
}
}
And it works with your text or any other.
Hi, I'm using your implementation because I want to see how much big are my labels (I need to know the measure of my text in pixels). I see that when I set a fontSize of 20 I have i.e. 268 as measured size. What's the measurement unit? Thank you
If my work is helping you, please help me back: https://xamarinhq.wufoo.com/forms/nominate-a-xamarin-mvp/
This is what i have done that is community visible:
Why is the Label/Button
HeightRequest
required? It makes it very difficult to use the CarouselViews when you are required to manually set or calculate all the heights.