rraallvv
rraallvv

Reputation: 2933

How to draw only the background of a Xamarin.Forms button?

I have this custom renderer where I want to resize the text to fit the button's bounding rect only if the text bounding box is greater than the button's.

What I'm trying to do is to draw the text "by hand" on top of the button's background without allowing the button itself to draw its text.

Is this possible without using a different type of view to fake a button?

Can I intercept somehow the FontSize property setter from the renderer, so I can store its value in some ivar while passing zero to the button so it won't draw the text?

public class AutoTextSizeButtonRenderer : ButtonRenderer
{
    private float fontSize = 0;

    private static float EPSILON = 0.1f;

    public AutoTextSizeButtonRenderer(Context context) : base(context)
    {
        SetWillNotDraw(false);
    }

    protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);
        Button button = Element as Button;
        if (Math.Abs(button.FontSize - 1) > EPSILON && Math.Abs(button.FontSize - fontSize) > EPSILON) {
            fontSize = (float)button.FontSize;
            button.FontSize = 1;
        }
        //Draw(new Canvas());
    }

    public override void Draw(Canvas canvas)
    {
        base.Draw(canvas);

        Button button = Element as Button;
        string text = button.Text;

        if (text != null)
        {
            TextPaint paint = new TextPaint();
            //paint.SetTypeface(Typeface.DefaultBold);
            paint.AntiAlias = true;
            Rect bounds = new Rect();
            Paint.FontMetrics metrics = null;

            DisplayMetrics displayMetrics = new DisplayMetrics();
            Display.GetMetrics(displayMetrics);
            float scaledDensity = displayMetrics.ScaledDensity;

            float textSize = fontSize;
            while(textSize >= 0)
            {
                paint.TextSize = scaledDensity * textSize;
                paint.GetTextBounds(text, 0, text.Length, bounds);
                metrics = paint.GetFontMetrics();
                if (bounds.Width() < MeasuredWidth && (metrics.Bottom - metrics.Top) < MeasuredHeight) {
                    break;
                }
                textSize--;
            }

            paint.Color = button.TextColor.ToAndroid();
            canvas.DrawText(
                text,
                0.5f * MeasuredWidth - bounds.Left - 0.5f * bounds.Width(),
                0.5f * MeasuredHeight - metrics.Ascent - 0.5f * (metrics.Bottom - metrics.Top),
                paint);
        }
    }
}

Upvotes: 0

Views: 192

Answers (1)

York Shen
York Shen

Reputation: 9084

how I did to detect changes in the value of FontSize in OnElementPropertyChanged

When you change your Xamarin.Forms.Button FontSize property, you could detect this change in the OnElementPropertyChanged method like this :

protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    base.OnElementPropertyChanged(sender, e);

    if (e.PropertyName == Xamarin.Forms.Button.FontSizeProperty.PropertyName)
        System.Diagnostics.Debug.WriteLine("FontSizeProperty has changed!");
}

Update :

Get the Button FontSize value :

protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    base.OnElementPropertyChanged(sender, e);

    if (e.PropertyName == Xamarin.Forms.Button.FontSizeProperty.PropertyName)
        System.Diagnostics.Debug.WriteLine("FontSizeProperty has changed!");
        System.Diagnostics.Debug.WriteLine("Element.FontSize == " + Element.FontSize);
}

Upvotes: 1

Related Questions