简体   繁体   English

将TSwitch添加到每个TListView项

[英]Add TSwitch to every TListView item

I haven't attempted this because I wouldn't know where to begin. 我没有尝试过,因为我不知道从哪里开始。

Is it possible to add a FMX TSwitch into a FMX TListViewitem? 是否可以将FMX TSwitch添加到FMX TListViewitem中?

Any help/suggestions would be much appreciated. 任何帮助/建议将不胜感激。

Thanks, 谢谢,

You first have to keep in mind the whole design of the TListView control. 首先,您必须牢记TListView控件的整个设计。 It's meant to be very lightweight for when it contains a large number of items. 当它包含大量项目时,它应该非常轻巧。 You may have a million items, you surely don't want a million switch controls instantiated. 您可能有一百万个项目,您当然不希望实例化一百万个开关控件。 Therefore, it's not meant for you to embed controls in each item as a container, such as the TListBox allows. 因此,这并不意味着您将控件作为容器嵌入每个项目中,例如TListBox允许的那样。

That being said, it's assumed that you perform minimal drawing on each individual list item to be consistent with the design of the TListView . 就是说,假设您对每个单独的列表项执行的绘制最少,以与TListView的设计保持一致。 This requires creating virtual objects inherited from TListItemObject to be associated with each item. 这要求创建从TListItemObject继承的虚拟对象,以与每个项目关联。 These objects are what allow the existing built-in elements of any item, such as the accessory or bitmap. 这些对象允许任何项目的现有内置元素,例如附件或位图。

Here's a very rough demo I threw together to get you started, you'd need to change the drawing how you need it to look. 这是我汇总的一个非常粗糙的演示,以帮助您入门,您需要更改图纸的外观。

Start a new FMX application, drop a TListView , and use this unit in place of your main form's unit: 启动一个新的FMX应用程序,删除一个TListView ,并使用此单元代替您主窗体的单元:

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  FMX.ListView.Types, FMX.ListView.Appearances, FMX.ListView.Adapters.Base,
  FMX.ListView, FMX.Controls.Presentation, FMX.StdCtrls;

type

  TListItemSwitch = class(TListItemSimpleControl)
  private
    FIsChecked: Boolean;
    FOnSwitch: TNotifyEvent;
    procedure SetIsChecked(const AValue: Boolean);
  protected
    function MouseDown(const Button: TMouseButton; const Shift: TShiftState; const MousePos: TPointF): Boolean;
      override;
    procedure DoSwitch; virtual;
  public
    constructor Create(const AOwner: TListItem); override;
    destructor Destroy; override;

    procedure Render(const Canvas: TCanvas; const DrawItemIndex: Integer; const DrawStates: TListItemDrawStates;
      const SubPassNo: Integer = 0); override;

  public
    property IsChecked: Boolean read FIsChecked write SetIsChecked;
    property OnSwitch: TNotifyEvent read FOnSwitch write FOnSwitch;
  end;

  TForm1 = class(TForm)
    ListView1: TListView;
    procedure ListView1UpdateObjects(const Sender: TObject;
      const AItem: TListViewItem);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

{ TListItemSwitch }

constructor TListItemSwitch.Create(const AOwner: TListItem);
begin
  inherited;

end;

destructor TListItemSwitch.Destroy;
begin

  inherited;
end;

procedure TListItemSwitch.DoSwitch;
begin
  FIsChecked:= not FIsChecked;
  if Assigned(OnSwitch) then
    OnSwitch(Self);
end;

function TListItemSwitch.MouseDown(const Button: TMouseButton;
  const Shift: TShiftState; const MousePos: TPointF): Boolean;
begin
  if (Button = TMouseButton.mbLeft) and Enabled then begin
    DoSwitch;
  end;
  inherited;
end;

procedure TListItemSwitch.Render(const Canvas: TCanvas;
  const DrawItemIndex: Integer; const DrawStates: TListItemDrawStates;
  const SubPassNo: Integer);
var
  R, R2: TRectF;
begin
  inherited;

  R:= Self.LocalRect;
  R2:= R;

  Canvas.BeginScene;
  try

    Canvas.Stroke.Kind:= TBrushKind.None;
    Canvas.Fill.Kind:= TBrushKind.Solid;
    Canvas.Fill.Color:= TAlphaColorRec.Skyblue;
    Canvas.FillRect(R, 8, 8,
      [TCorner.TopLeft, TCorner.TopRight, TCorner.BottomLeft, TCorner.BottomRight],
      1.0, TCornerType.Round);

    if IsChecked then begin
      R2.Left:= R.Right - 20;
      R2.Width:= 20;
    end else begin
      R2.Left:= R.Left;
      R2.Width:= 20;
    end;

    Canvas.Fill.Color:= TAlphaColorRec.Black;
    Canvas.FillRect(R2, 8, 8,
      [TCorner.TopLeft, TCorner.TopRight, TCorner.BottomLeft, TCorner.BottomRight],
      1.0, TCornerType.Round);

  finally
    Canvas.EndScene;
  end;

end;

procedure TListItemSwitch.SetIsChecked(const AValue: Boolean);
begin
  FIsChecked:= AValue;
end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
var
  I: TListViewItem;
begin
  I:= ListView1.Items.Add;
  I:= ListView1.Items.Add;
  I:= ListView1.Items.Add;
  I:= ListView1.Items.Add;
  I:= ListView1.Items.Add;
  I:= ListView1.Items.Add;
  I:= ListView1.Items.Add;
  I:= ListView1.Items.Add;
  I:= ListView1.Items.Add;

end;

procedure TForm1.ListView1UpdateObjects(const Sender: TObject;
  const AItem: TListViewItem);
var
  S: TListItemSwitch;
begin
  S:= AItem.Objects.FindObject('Switch') as TListItemSwitch;
  if S = nil then begin
    S:= TListItemSwitch.Create(AItem);
    S.Name:= 'Switch';
    S.Align:= TListItemAlign.Trailing;
    S.VertAlign:= TListItemAlign.Center;
    S.Width:= 50;
    S.Height:= 20;
    S.IsChecked:= False;
  end;

end;

end.

屏幕截图

NOTE: This was written in Delphi 10 Seattle. 注意:这是用Delphi 10 Seattle写的。

Your only other options I believe are to either: 我相信您唯一的其他选择是:

  1. Instantiate a TSwitch for each item and render it using the same method as above (Very sloppy, I do not recommend) 为每个项目实例化一个TSwitch并使用与上述相同的方法进行渲染(非常草率,我不推荐)
  2. Figure out how to implement the drawing of the standard TSwitch using styles, again using the same method as above (which is probably the best option for performance and visual adaption) 再次使用与上述相同的方法,弄清楚如何使用样式来实现标准TSwitch的绘图(这可能是性能和视觉适应的最佳选择)
  3. Resort to a TListBox instead, depending on how you intend to use the list (which would be very heavy on a large number of items) 取而代之的是使用TListBox ,这取决于您打算如何使用列表(在很多项目上这会非常繁琐)

I went a little more in-depth about the differences between a TListView and a TListBox in Firemonkey in a separate question / answer . 我去深入多一点有关之间的差异TListViewTListBox在Firemonkey 一个单独的问题/答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM