【问题标题】:How to adjust button size to fit the text in Delphi FireMonkey?如何调整按钮大小以适合 Delphi FireMonkey 中的文本?
【发布时间】:2013-08-28 03:01:27
【问题描述】:

我希望按钮大小(宽度和高度)尽可能小,但我希望它适合文本。任何代码示例? Delphi XE4 FireMonkey 移动应用程序。

【问题讨论】:

    标签: delphi button text firemonkey delphi-xe4


    【解决方案1】:

    FireMonkey 通过使用 TTextLayout 类的方法呈现文本。
    我们可以通过类助手访问这些方法,然后根据布局提供的信息更改按钮大小。

    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;
    

    更新

    这是一个更面向未来的解决方案,不需要公开私有类字段。

    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;
    

    此示例省略了任何自动换行或字符修剪。

    【讨论】:

    • 它在 XE6 上的行为很奇怪。如果我对具有不同文本长度的同一个按钮进行连续调用,则宽度会在需要时增加,但永远不会减小。
    • @RegisSt-Gelais,请记住这是为 XE4 编写的。从那时起,Firemonkey 经历了很多变化,因此结果可能会有所不同。如果这对您很重要,您应该为 XE6 发布一个新的 SO 问题。
    • 感谢您的评论,也感谢您提供的原始解决方案。问题仍然有效。我不想创建副本。也许通过恢复它并说它在 XE6 上不起作用,有人会发布一个新的解决方案。问候。
    • @RegisSt-Gelais,你说得对,我已经用解决问题的替代解决方案更新了我的答案,希望有更多的未来证明。如果这能解决您的问题,请告诉我。
    • 添加一项效果很好。有时 FindStyleResource 返回 nil 导致应用程序崩溃。我添加了类似 Text := Button.FindStyleResource('text', false) 作为 TText;如果 Text 是 TText 然后开始 ....
    【解决方案2】:

    基于@Peter 的回答,但不需要创建位图:

    //...
    
    type
        TButtonHelper = class helper for TButton
            procedure FitToText(AOnlyWidth: Boolean = False);
        end;
    
    implementation
    
    //...
    
    // Adapt button size to text.
    // This code does not account for word wrapping or character trimming.
    procedure TButtonHelper.FitToText(AOnlyWidth: Boolean = False);
    var
        Margins: TBounds;
        TextWidth, TextHeight: Single;
        Obj: TFmxObject;
    const
        CLONE_NO = False;
    begin
        Obj := FindStyleResource('text', CLONE_NO);
        if Obj is TText then    //from Stackoverflow comments: Some time FindStyleResource returns nil making the app crash
        begin
            Margins := (Obj as TText).Margins;
            TextWidth := Canvas.TextWidth(Text);
            if not AOnlyWidth then
              TextHeight := Canvas.TextHeight(Text);
            TextSettings.HorzAlign := TTextAlign.taLeading;    //works in XE4
            //later FMX-Versions ?: TextSettings.HorzAlign := TTextAlign.Leading;
            Width := TextWidth + Margins.Left + Margins.Right;
            if not AOnlyWidth then
              Height := TextHeight + Margins.Top + Margins.Bottom;
        end;
    end;
    

    【讨论】:

    • @Peter 随时使用此代码更新您的答案。那我就删掉我的答案,因为你欠原来的想法。
    • 在 Android 上运行良好,但在 Windows 上它的大小只有应有的一半......? (D10 西雅图)
    • @JerryDodge 我在 Windows 上使用 XE4 和 XE8 对此进行了测试,没有任何问题。 Peter (ButtonAutoSizeEx) 的解决方案对你有用吗?
    猜你喜欢
    • 2020-04-25
    • 2016-11-24
    • 2019-01-11
    • 2016-05-27
    • 2015-09-16
    • 1970-01-01
    • 1970-01-01
    • 2017-01-07
    • 2011-02-06
    相关资源
    最近更新 更多