0

Xamarin Forms Android Autosize Label TextCompat pre android 8 doesn't autosize text

I unfortunately do not have a high enough rep to comment on anyones post.

I was trying some things out and came across the post linked which got me very close to the solution after experimenting with other posts. I am also trying to autosize text within an app, but inside of an MVVM Master Detail project. If I enter values directly in the Droid renderer it works as expected, but that defeats the purpose when I have fonts of all sizes needed.

  • I have already made sure my return type is correct.
  • The code behind is initialized prior to the get value.
  • The fields are public.
  • There are no other issues by plugging in numeric values instead of bindable properties.

I am not receiving any values from the view. I would assume the view has not been created yet but the code behind has initialized. I am pretty sure I have done everything mostly right but I mostly deal with stock Xamarin so expanding functionality is still pretty new to me. All help is appreciated.

Custom Control (edit: changed default value from default(int) to an integer value to get rid of exception)

/// <summary>Auto scale label font size class.</summary>
public class AutoSizeLabel : Label
{
    /// <summary>Minimum font size property.</summary>
    public static readonly BindableProperty MinimumFontSizeProperty = BindableProperty.Create(
        propertyName: nameof(MinimumFontSize),
        returnType: typeof(int),
        declaringType: typeof(AutoSizeLabel),
        defaultValue: 17);

    /// <summary>Maximum font size property.</summary>
    public static readonly BindableProperty MaximumFontSizeProperty = BindableProperty.Create(
        propertyName: nameof(MaximumFontSize),
        returnType: typeof(int),
        declaringType: typeof(AutoSizeLabel),
        defaultValue: 24);

    /// <summary>Gets or sets minimum font size.</summary>
    public int MinimumFontSize
    {
        get
        {
            return (int)this.GetValue(MinimumFontSizeProperty);
        }

        set
        {
            this.SetValue(MinimumFontSizeProperty, value);
        }
    }

    /// <summary>Gets or sets maximum font size.</summary>
    public int MaximumFontSize
    {
        get
        {
            return (int)this.GetValue(MaximumFontSizeProperty);
        }

        set
        {
            this.SetValue(MaximumFontSizeProperty, value);
        }
    }
}

Droid Renderer

public class AutoSizeLabelRenderer : LabelRenderer
{

    protected override bool ManageNativeControlLifetime => false;

    protected override void Dispose(bool disposing)
    {
        Control.RemoveFromParent();
        base.Dispose(disposing);
    }

    private AutoSizeLabel bindingValue = new AutoSizeLabel();

    private AppCompatTextView appCompatTextView;

    public AutoSizeLabelRenderer(Context context) : base(context)
    {
    }

    protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
    {
        base.OnElementChanged(e);

        if (e.NewElement == null || !(e.NewElement is AutoSizeLabel autoLabel) || Control == null) { return; }

        //v8 and above supported natively, no need for the extra stuff below.
        if (DeviceInfo.Version.Major >= 8)
        {
            Control?.SetAutoSizeTextTypeUniformWithConfiguration(bindingValue.MinimumFontSize, bindingValue.MaximumFontSize, 2, (int)ComplexUnitType.Sp);
            return;
        }
        appCompatTextView = new AppCompatTextView(Context);
        appCompatTextView.SetTextColor(Element.TextColor.ToAndroid());
        appCompatTextView.SetMaxLines(1);
        appCompatTextView.SetBindingContext(autoLabel.BindingContext);SetNativeControl(appCompatTextView);

        TextViewCompat.SetAutoSizeTextTypeUniformWithConfiguration(Control, bindingValue.MinimumFontSize, bindingValue.MaximumFontSize, 2, (int)ComplexUnitType.Sp);
    }
}

XAML Call

                <renderer:AutoSizeLabel MinimumFontSize="17"
                                    MaximumFontSize="24"
                                    Style="{StaticResource SomeStyle}"
                                    Text="{Binding SomeText}">
                <Label.GestureRecognizers>
                    <TapGestureRecognizer Command="{Binding SomeCommand}"></TapGestureRecognizer>
                </Label.GestureRecognizers>
            </renderer:AutoSizeLabel>
  • What is the error now? Could you provide more details with screenshot about what you want to get and what you have done now? What is the version of your device? Does the `AutoSize` property work? – Wendy Zang - MSFT Feb 12 '21 at 08:00
  • @WendyZang-MSFT Nexus One android 9.0. An example would be a single label in a view. I am translating the app into 6 different languages where there are a number of languages that translate to lengthier strings than English. The autosize works perfectly if you set the min and max value from within the custom renderer as an actual number. A majority of what I have been trying is placing breakpoints everywhere to track down why the returned value is 0. ```Java.Lang.IllegalArgumentException Message=Minimum auto-size text size (0.0px) is less or equal to (0px)``` – tft_jkaiser Feb 12 '21 at 15:02

1 Answers1

0

This line is unnecessary.

private AutoSizeLabel bindingValue = new AutoSizeLabel();

Instead reference autoLabel. Alternatively I changed the check to

if (e.NewElement == null || Control == null) { return; }

and cast in the following line using

var autoSizeLabel = e.NewElement as AutoSizeLabel;