Search code examples
delphibuttontextfiremonkeydelphi-xe4

How to adjust button size to fit the text in Delphi FireMonkey?


I want button size (width and height) to be as small as possible, but I want it to fit the text. Any code example? Delphi XE4 FireMonkey Mobile Application.


Solution

  • FireMonkey renders text via methods using TTextLayout class.
    We can access this methods via a class helper and then change the buttons size based on the information provided by the layout.

    uses FMX.TextLayout;
    
    type
      TextHelper = class helper for TText
         function getLayout : TTextLayout;
      end;
    
    function TextHelper.getLayout;
    begin
      result := Self.fLayout;
    end;
    
    procedure ButtonAutoSize(Button : TButton);
    var
      bCaption : TText;
      m : TBounds;
    begin
      bCaption := TText(Button.FindStyleResource('text',false));
      bCaption.HorzTextAlign := TTextAlign.taLeading;
      bCaption.VertTextAlign := TTextAlign.taLeading;
      m := bCaption.Margins;
      Button.Width  := bCaption.getLayout.Width  + m.Left + m.Right;
      Button.Height := bCaption.getLayout.Height + m.Top  + m.Bottom;
    end;
    
    procedure TForm1.Button1Click(Sender: TObject);
    begin
       ButtonAutoSize(Sender as TButton);
    end;
    

    Update

    Here is a more future proof solution that doesn't require exposing private class fields.

    uses FMX.Objects;
    
    procedure ButtonAutoSizeEx(Button: TButton);
    var
      Bitmap: TBitmap;
      Margins: TBounds;
      Width, Height: Single;
    begin
      Bitmap := TBitmap.Create;
      Bitmap.Canvas.Font.Assign(Button.TextSettings.Font);
      Width := Bitmap.Canvas.TextWidth(Button.Text);
      Height := Bitmap.Canvas.TextHeight(Button.Text);
      Margins := (Button.FindStyleResource('text', false) as TText).Margins;
      Button.TextSettings.HorzAlign := TTextAlign.Leading;
      Button.Width := Width + Margins.Left + Margins.Right;
      Button.Height := Height + Margins.Top + Margins.Bottom;
    end;
    

    This example omits any word wrapping or character trimming.