3

どこから始めればよいかわからないため、これを試みていません。

FMX TSwitch を FMX TListViewitem に追加することはできますか?

どんな助け/提案も大歓迎です。

ありがとう、

4

1 に答える 1

6

TListView最初に、コントロールの設計全体を念頭に置く必要があります。多数のアイテムが含まれている場合に備えて、非常に軽量になるように設計されています。100 万個のアイテムがあるかもしれませんが、100 万個のスイッチ コントロールをインスタンス化する必要はありません。したがって、許可などのコンテナーとして各項目にコントロールを埋め込むことは意図されていませんTListBox

そうは言っても、 のデザインと一貫性を保つために、個々のリスト項目ごとに最小限の描画を実行することを前提としていますTListView。これには、継承元の仮想オブジェクトを作成しTListItemObjectて、各アイテムに関連付ける必要があります。これらのオブジェクトは、アクセサリやビットマップなど、任意のアイテムの既存の組み込み要素を許可するものです。

これは、開始するために一緒に投げた非常に大まかなデモです。必要な外観にするには、図面を変更する必要があります。

新しい 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.

スクリーンショット

注: これは Delphi 10 シアトルで作成されました。

私が信じている他の唯一のオプションは、次のいずれかです。

  1. TSwitchアイテムごとにa をインスタンス化し、上記と同じ方法を使用してレンダリングします (非常にずさんです。お勧めしません)。
  2. TSwitch上記と同じ方法を使用して、スタイルを使用して標準の描画を実装する方法を見つけます (これはおそらく、パフォーマンスと視覚的な適応のための最良のオプションです)。
  3. リストをどのように使用するかによっては、代わりに aTListBoxに頼ります (多数のアイテムでは非常に重くなります)。

Firemonkeyの aTListViewと aの違いについては、別の質問/回答でもう少し詳しく説明しました。TListBox

于 2016-05-06T23:55:00.853 に答える