2016-05-06 13 views
1

どこから始めたらいいのかわからないので、これを試みていません。すべてのTListViewアイテムにTSwitchを追加してください

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

ご協力いただきありがとうございます。

おかげで、

+0

私はこれを実行しようとしましたが、私は設計時にそれを行う簡単な方法を見ることができません。たぶん実行時オプションがあります。 –

答えて

4

あなたが最初に念頭に置いてTListView制御の全体のデザインを維持する必要があります。これは、多数のアイテムが含まれている場合に非常に軽量になることを意図しています。何百万ものアイテムを持っているかもしれませんが、あなたは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. 

Screenshot

注:これは、デルファイ10シアトルで書かれています。

私はどちらかにあると考えているあなたの唯一の他のオプション:

  1. 各項目のTSwitchをインスタンス化し、上記と同様の方法を使用してそれをレンダリング(非常にずさんな、私はお勧めしません)
  2. 図アウトする方法スタイルを使用して標準TSwitchの描画を実装するには、上記と同じ方法を使用します(パフォーマンスと視覚的適応のための最適なオプションです)
  3. 代わりにTListBoxへのリゾートそれは大量に非常に重いでしょうアイテムのBER)

私はa separate question/answerTListViewとFireMonkeyの中TListBoxの違いについての深いもう少し行ってきました。

+0

プラスの面では、これは標準的なワンレス描画よりもはるかに効率的で、アニメーションはなく、クリックに対して信頼性があります( 'TSwitch'にいくつかの奇妙な不具合があるため)。しかし、ラインを選択するだけでスイッチが切り替わるという別の不具合があります。 –

+0

ありがとう、ジェリー、まさに私が探しているもの。 –

+0

@ 6String_Coderここには、私がすでに上に追加した複雑さのない、優れた実装があります:http://stackoverflow.com/questions/37083809/click-events-being-caught-by-list-view-parent-item Long私はリストビューのコンポーネントを作成しています。このコンポーネントを使用すると、デザイン時のコンポーネントエディタでリストビューのアイテムを「デザインする」ことができます。 –

関連する問題