You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在FMX.TCalendar中基于日期设置单元格灰色背景?

FMX.TCalendar日期单元格高亮实现方案

FMX.TCalendar本身没有直接暴露Draw方法,但完全可以通过继承自定义控件的方式实现你要的两个功能,具体方案如下:

核心思路

FMX的TCalendar内部通过TCalendarDayButton控件渲染每个日期单元格,我们可以继承TCalendar,重写其日期更新逻辑,对每个日期按钮的背景色进行自定义设置。

具体实现步骤

1. 自定义日历控件

创建继承自TCalendar的自定义控件,添加禁用日期列表,并实现日期按钮的样式更新逻辑:

type
  TCustomCalendar = class(TCalendar)
  private
    FDisabledDates: TList<TDate>;
    procedure UpdateDayButton(ADayButton: TCalendarDayButton; ADate: TDate);
  protected
    procedure UpdateDays; override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    // 你需要的禁用指定日期的函数
    procedure DisableCalendarDate(ADate: TDate);
    // 可选:恢复指定日期的正常显示
    procedure EnableCalendarDate(ADate: TDate);
  end;

2. 实现控件基础逻辑

初始化和销毁禁用日期列表:

constructor TCustomCalendar.Create(AOwner: TComponent);
begin
  inherited;
  FDisabledDates := TList<TDate>.Create;
end;

destructor TCustomCalendar.Destroy;
begin
  FDisabledDates.Free;
  inherited;
end;

3. 重写日期更新方法

在日历更新月份日期时,遍历所有日期按钮,根据条件设置背景色:

procedure TCustomCalendar.UpdateDays;
var
  I: Integer;
  DayButton: TCalendarDayButton;
begin
  inherited;
  // 遍历所有日期按钮
  for I := 0 to Pred(ControlCount) do
  begin
    if Controls[I] is TCalendarDayButton then
    begin
      DayButton := TCalendarDayButton(Controls[I]);
      UpdateDayButton(DayButton, DayButton.Date);
    end;
  end;
end;

procedure TCustomCalendar.UpdateDayButton(ADayButton: TCalendarDayButton; ADate: TDate);
begin
  // 去除时间部分,仅比较日期
  ADate := Trunc(ADate);
  // 判断:早于今日 或 在禁用列表中
  if (ADate < Trunc(Date)) or (FDisabledDates.IndexOf(ADate) <> -1) then
  begin
    // 设置灰色背景,白色文字
    ADayButton.Fill.Color := TAlphaColors.Gray;
    ADayButton.TextSettings.FontColor := TAlphaColors.White;
    // 取消默认样式(避免样式覆盖自定义颜色)
    ADayButton.StyleLookup := '';
  end
  else
  begin
    // 恢复默认样式和颜色
    ADayButton.StyleLookup := 'calendardaybuttonstyle';
    ADayButton.Fill.Color := TAlphaColors.Null;
    ADayButton.TextSettings.FontColor := TAlphaColors.Black;
  end;
end;

4. 实现禁用指定日期的函数

添加方法来手动禁用/恢复指定日期:

procedure TCustomCalendar.DisableCalendarDate(ADate: TDate);
begin
  ADate := Trunc(ADate);
  if FDisabledDates.IndexOf(ADate) = -1 then
  begin
    FDisabledDates.Add(ADate);
    UpdateDays; // 立即刷新日历显示
  end;
end;

procedure TCustomCalendar.EnableCalendarDate(ADate: TDate);
begin
  ADate := Trunc(ADate);
  FDisabledDates.Remove(ADate);
  UpdateDays;
end;

注意事项

  • 不同平台(Windows/Android/iOS)的FMX控件样式可能存在差异,如果自定义颜色不生效,可以尝试重写TCalendarDayButton的Paint方法来强制绘制背景。
  • 当切换月份、年份时,UpdateDays会自动触发,确保所有日期的样式都能正确更新。
  • 日期比较时使用Trunc去除时间部分,避免因时间戳差异导致判断错误。

内容的提问来源于stack exchange,提问作者Glen Morse

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 14:00:34