2016-05-06 11 views
1

Ich habe dies nicht versucht, weil ich nicht wissen würde, wo ich anfangen soll.Hinzufügen TSwitch zu jedem TListView Element

Kann ich einen FMX TSwitch in ein FMX TListViewitem einfügen?

Jede Hilfe/Vorschläge würde sehr geschätzt werden.

Danke,

+0

Ich habe versucht, dies zu tun, und sehe keine einfache Möglichkeit, es zur Entwurfszeit zu tun. Vielleicht gibt es eine Laufzeitoption. –

Antwort

4

Sie zuerst das gesamte Design der TListView Kontrolle im Auge behalten müssen. Es soll sehr leicht sein, wenn es eine große Anzahl von Gegenständen enthält. Sie können eine Million Elemente haben, Sie wollen sicherlich nicht eine Million Switch-Steuerelemente instanziiert. Daher ist es nicht für Sie vorgesehen, Steuerelemente in jedes Element als einen Container einzubetten, wie es beispielsweise der TListBox ermöglicht.

Es wird davon ausgegangen, dass Sie minimale Zeichnung auf jedem einzelnen Listenelement durchführen, um mit dem Design der TListView konsistent zu sein. Dazu müssen virtuelle Objekte erstellt werden, die von TListItemObject geerbt wurden, um mit jedem Element verknüpft zu werden. Diese Objekte ermöglichen die vorhandenen integrierten Elemente eines beliebigen Elements, z. B. des Zubehörs oder der Bitmap.

Hier ist eine sehr grobe Demo Ich warf zusammen, um Sie zu beginnen, müssten Sie die Zeichnung ändern, wie Sie es brauchen, um zu sehen.

eine neue FMX-Anwendung starten, ein TListView fallen, und verwenden Sie dieses Gerät anstelle Ihrer Hauptgerätes Form:

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

Hinweis: Dies wurde in Delphi 10 Seattle geschrieben.

Ihre einzige andere Optionen Ich glaube, sind entweder:

  1. eine TSwitch für jedes Element instanziiert und machen es nach dem gleichen Verfahren wie oben (sehr schlampig, ich nicht empfehlen)
  2. herauszufinden, wie Um die Zeichnung des Standards TSwitch mit Stilen zu implementieren, wieder mit der gleichen Methode wie oben (das ist wahrscheinlich die beste Option für Leistung und visuelle Anpassung)
  3. Verwenden Sie stattdessen eine TListBox, je nachdem, wie Sie die Liste verwenden wollen (was auf einer großen Anzahl sehr schwer wäre ber der Elemente)

ging ich ein wenig mehr in die Tiefe über die Unterschiede zwischen einem TListView und einem TListBox in Firemonkey in a separate question/answer.

+0

Auf der positiven Seite, das ist viel effizienter als die Standard-One-less-Zeichnung, keine Animationen und zuverlässig auf den Klick (weil der "TSwitch" einige seltsame Störungen hat). Es gibt jedoch einen weiteren Fehler, bei dem durch einfaches Auswählen einer Leitung der Schalter umgeschaltet wird. –

+0

Vielen Dank @Jerry, genau das, was ich suche. –

+0

@ 6String_Coder Hier ist eine gute Implementierung davon ohne die Komplexität, die ich bereits oben hinzugefügt habe: http://stackoverflow.com/questions/37083809/click-events-being-caught-by-list-view-parent-item Long Kurz gesagt, ich erstelle eine Listenansicht-Controller-Komponente, mit der Sie die Elemente der Listenansicht in einem Design-Time-Komponenteneditor "entwerfen" können. –