• (原)FMX 设置ListBox的字体及自动计算ListItem高度


    在用FMX的ListBox和ComboBox等涉及TListBox的时候,都要人工设置ItemHeight。

    如果ItemHeight是固定不变的,并且是定制使用ListItem的Style的话,可以直接在Style中设置ItemHeight。

    如果要动态改变ItemHeight,或者是ItemHeight的大小未知,自动设置ItemHeight, 就要根据Item的文本大小来调整,因此要测量ListItem的文本高度TextHeight(一般不用考虑宽度),如果Scale不是1,还得乘以Scale。所以就涉及到测量文本的高度问题。

    原来在VCL下,直接是TCanvas.MeasureText(),就可以得到实际的文本高度TextHight。但是在FMX下,最好不用TCanvas来测量,虽然TCanvas提供了MeasureText()和TextHeight()方法,其中TextHeight()调用MeasureText(),MeasureText()调用了TTextLayout的属性TextRect。

    但是要注意,我们改变ListItem的Font的时候,ListItem.Canvas的Font是不变的,还是默认大小。一般情况下,默认Font的大小(在win10下,如果不改系统默认字体大小,这个值是12)太小了,我们都会设置的大一些。所以要用TCanvas的MeasureText()或TextHeight()方法测量的TextHeight大小,测量前我们得先改变ListItem.Canvas的Font大小,但是TCanvas.Font属性是只读的,不能改变整个Font,只能是单独改变TFont的各个属性,比如Font.Family,Font.Size,Font.Color等,比较麻烦。看看TCanvas的代码:

    .........

    property Stroke: TStrokeBrush read FStroke;
    property Fill: TBrush read FFill write SetFill;
    property Font: TFont read FFont;
    property Matrix: TMatrix read FMatrix;
    property Width: Integer read FWidth;
    property Height: Integer read FHeight;
    property Bitmap: TBitmap read FBitmap;
    property Scale: Single read FScale;

    .........

    Fill和Stroke倒是可读写的,Font是只读的。

    再看看MeasureText()和TextHeight():

    procedure TCanvas.MeasureText(var ARect: TRectF; const AText: string;
      const WordWrap: Boolean; const Flags: TFillTextFlags; const ATextAlign,
      AVTextAlign: TTextAlign);
    var
      Layout: TTextLayout;
    begin
      if AText.IsEmpty then
      begin
        ARect.Right := ARect.Left;
        ARect.Bottom := ARect.Top;
        Exit;
      end;
    
      Layout := TTextLayoutManager.TextLayoutByCanvas(Self.ClassType).Create(Self);
      try
        Layout.BeginUpdate;
        Layout.TopLeft := ARect.TopLeft;
        Layout.MaxSize := PointF(ARect.Width, ARect.Height);
        Layout.Text := AText;
        Layout.WordWrap := WordWrap;
        Layout.HorizontalAlign := ATextAlign;
        Layout.VerticalAlign := AVTextAlign;
        Layout.Font := Self.Font;
        Layout.Color := Self.Fill.Color;
        Layout.RightToLeft := TFillTextFlag.RightToLeft in Flags;
        Layout.EndUpdate;
        ARect := Layout.TextRect;
      finally
        FreeAndNil(Layout);
      end;
    end;
    
    function TCanvas.TextHeight(const AText: string): Single;
    var
      R: TRectF;
    begin
      R := RectF(0, 0, 10000, 10000);
      MeasureText(R, AText, False, [], TTextAlign.Leading, TTextAlign.Leading);
      Result := R.Bottom;
    end;
    

     是通过TTextLayout来实现。

    所以干脆不用这个名不副实的MeasureText(),自己用TTextLayout来实现好了。

    写个通用的设置字体和自动计算Item高度的方法:

    //ListBoxItem 的文本高度自动计算,以ListItem[0]为准,如果是每个ListItem不一样,建议用Style方式实现

    procedure SetListBoxItemFontAndHeight(AControl: TFmxObject; AFontName: string; AFontSize: Single;
        AFontColor: TAlphaColor; AutoItemHeight: Boolean);
    var
      i: Integer;
      AStyledSettings: TStyledSettings;
      aListBox: TListBox;
      LTextLayout: TTextLayout;
    begin
      AStyledSettings := AllStyledSettings;
      if not AFontName.IsEmpty then
        AStyledSettings := AStyledSettings - [TStyledSetting.Family];
      if AFontSize > 8 then
        AStyledSettings := AStyledSettings - [TStyledSetting.Size];
      if AFontColor <> TAlphaColors.Black then
        AStyledSettings := AStyledSettings - [TStyledSetting.FontColor];
    
      aListBox := nil;
    
      if AControl is TListBox then
        aListBox := TListBox(AControl)
      else if AControl is TComboBox then
      begin
        TComboBox(AControl).DropDownKind := TDropDownKind.Custom;
        aListBox := TListBox(TComboBox(AControl).ListBox);
      end
      else
        Exit;
    
      if (aListBox = nil) or (aListBox.Count = 0) then
        Exit;
    
      for i := 0 to aListBox.Count-1 do
      begin
        aListBox.ListItems[i].StyledSettings := AStyledSettings;
        if not AFontName.IsEmpty then
          aListBox.ListItems[i].TextSettings.Font.Family := AFontName;
        if AFontSize > 8 then
          aListBox.ListItems[i].TextSettings.Font.Size := AFontSize;
        if AFontColor <> TAlphaColors.Black then
          aListBox.ListItems[i].TextSettings.FontColor := AFontColor;
      end;
    
      if not AutoItemHeight then
        Exit;
    
     //计算ItemHeight LTextLayout := TTextLayoutManager.DefaultTextLayout.Create(); try LTextLayout.BeginUpdate; try LTextLayout.Font := aListBox.ListItems[0].Font; LTextLayout.Text := aListBox.Items[0]; finally LTextLayout.EndUpdate; end; aListBox.ItemHeight := LTextLayout.Height; //TextHeight finally LTextLayout.Free; end; end;

      

  • 相关阅读:
    一,初次接触html+css需要注意的小问题
    Pycharm如何在控制台输出窗口中使用Python解释器
    Silver Cow Party POJ
    Constructing Roads POJ
    小希的迷宫 HDU
    Wireless Network POJ
    Scanner读取记事本文件内容为空的解决办法
    mysql limit的使用方法
    Can you find it? HDU-2141 (二分查找模版题)
    【2028-07-18】精力是有限的,但智慧是无限的
  • 原文地址:https://www.cnblogs.com/jankerxp/p/14502888.html
Copyright © 2020-2023  润新知