Xamarin Forms - 使用 LabelSizeFontToFit 效果更改按钮上的文本使文本越来越小

问题描述

我在水平堆栈布局中有几个按钮,为了适应不同的语言和纵向,我需要文字大小来适应可用空间。因此,我使用了 LabelSizefontToFit 效果(来自 Xamarin.Toolkit.Effects NuGet 包),如下面的 XAML 代码所示。

<StackLayout x:Name="TitleBarLayout" Orientation="Horizontal" HorizontalOptions="Fill" VerticalOptions="Fill" Spacing="0" Padding="0" Margin="0" BackgroundColor="LightGoldenrodYellow" >
    <Button x:Name="AddSelected" FontSize="Default" HorizontalOptions="End" TextColor="White" VerticalOptions="Center" BackgroundColor="Blue" Margin="0" Padding="0" Clicked="AddSelected_Clicked" >
        <Button.Effects>
            <effects:LabelSizefontToFit />
        </Button.Effects>
    </Button>
    <Button x:Name="DeleteSelected" FontSize="Default" HorizontalOptions="End" TextColor="White" VerticalOptions="Center" BackgroundColor="Red" Margin="0" Padding="0" Clicked="DeleteSelected_Clicked" >
        <Button.Effects>
            <effects:LabelSizefontToFit />
        </Button.Effects>
    </Button>
</StackLayout>

这最初可以正常工作。但是,我需要根据是选择一个还是多个项目,在两个不同的字符串之间切换这些按钮上的文本。不幸的是,每次我更改 C# 代码中的文本时,文本都会变小。当我选择和取消选择不同的东西时,它最终变得难以辨认。这是没有意义的,因为一旦字体小到足以容纳两个字符串,它就不应该变得更小。

我尝试了各种布局参数的组合都无济于事。

有谁知道它为什么会这样,以及如何让它正确运行?

PS 我尝试了其他几种缩小字体以适应的方法,但它们更加混乱且难以使用。我不想使用 Forms9Patch,因为它使我的包大小增加了 35%。

解决方法

对于 Xamarin.Toolkit.Effects,不会放大字体大小,只会缩小字体大小。为了解决这个问题,我建议您可以创建自定义 Button,custombtn 扩展 Xamarin.Forms.Button 并添加以下两个方法:>

   public class custombtn:Button
{
    /// <summary>
    /// Autosizes the button's font size with regards to it's container size.
    /// </summary>
    private void AutoFontSize()
    {
        //determine the text height for the min font size
        double lowerFontSize = 15;
        double lowerTextHeight = TextHeightForFontSize(lowerFontSize);

        //determine the text height for the max font size
        double upperFontSize = 30;
        double upperTextHeight = TextHeightForFontSize(upperFontSize);

        //start a loop which'll find the optimal font size
        while (upperFontSize - lowerFontSize > 1)
        {
            //determine current average font size and calculate corresponding text height
            double fontSize = (lowerFontSize + upperFontSize) / 2;
            double textHeight = TextHeightForFontSize(upperFontSize);

            //if the calculated height is out of bounds,update max values,else update min values
            if (textHeight > Height)
            {
                upperFontSize = fontSize; upperTextHeight = textHeight;
            }
            else
            {
                lowerFontSize = fontSize; lowerTextHeight = textHeight;
            }
        }

        //finally set the correct font size
        FontSize = lowerFontSize;
    }

    /// <summary>
    /// Determines the text height for the label with a given font size.
    /// </summary>
    private double TextHeightForFontSize(double fontSize)
    {
        FontSize = fontSize;
        return OnMeasure(Width,Double.PositiveInfinity).Request.Height;
    }

    /// <summary>
    /// Callback when the size of the element is set during a layout cycle.
    /// </summary>
    protected override void OnSizeAllocated(double width,double height)
    {
        //call base implementation
        base.OnSizeAllocated(width,height);

        //update font size
        AutoFontSize();
    }

    new public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty,value); AutoFontSize(); }
    }

}

可以添加 MinFontSize 和 MaxFontSize 属性,以便可以在 XAML 中指定最小/最大字体大小值。