Ich schreibe ein benutzerdefiniertes Schalterobjekt, das in Firemonkes TListView
Steuerelement pro Element verwendet werden soll. Alles funktioniert wie erwartet, abgesehen von einem seltsamen Fehler. Wenn der Benutzer auf eines der Elemente, aber nicht auf das bestimmte Schalterobjekt klickt, schaltet es den Schalter trotzdem um. Ich gehe davon aus, dass das Ereignis MouseDown
ausgelöst wird, wenn der Benutzer auf das Listenelement klickt und nicht unbedingt mein bestimmtes "Steuerelement" darauf gezeichnet wird.Klicken Sie auf Ereignisse, die von der Listenansicht abgefangen werden. Element
Wie schränke ich das Klickereignis so ein, dass es nur dann gilt, wenn der Benutzer auf den aktuellen Schalter klickt?
JD.ListViewObjects.pas
unit JD.ListViewObjects;
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;
type
TLISwitchThumbStyle = (tsRect, tsRoundRect, tsElipse);
TListItemSwitch = class(TListItemSimpleControl)
private
FIsChecked: Boolean;
FOnSwitch: TNotifyEvent;
FThumbStyle: TLISwitchThumbStyle;
FThumbWidth: Single;
FThumbHeight: Single;
FThumbRound: Single;
procedure SetIsChecked(const AValue: Boolean);
procedure SetThumbStyle(const Value: TLISwitchThumbStyle);
procedure SetThumbWidth(const Value: Single);
procedure SetThumbHeight(const Value: Single);
procedure SetThumbRound(const Value: Single);
protected
function MouseDown(const Button: TMouseButton; const Shift: TShiftState; const MousePos: TPointF): Boolean;
override;
procedure DoSwitch; virtual;
procedure Render(const Canvas: TCanvas; const DrawItemIndex: Integer; const DrawStates: TListItemDrawStates;
const SubPassNo: Integer = 0); override;
public
constructor Create(const AOwner: TListItem); override;
destructor Destroy; override;
public
property IsChecked: Boolean read FIsChecked write SetIsChecked;
property ThumbWidth: Single read FThumbWidth write SetThumbWidth;
property ThumbHeight: Single read FThumbHeight write SetThumbHeight;
property ThumbStyle: TLISwitchThumbStyle read FThumbStyle write SetThumbStyle;
property ThumbRound: Single read FThumbRound write SetThumbRound;
property OnSwitch: TNotifyEvent read FOnSwitch write FOnSwitch;
end;
implementation
{ TListItemSwitch }
constructor TListItemSwitch.Create(const AOwner: TListItem);
begin
inherited;
Width:= 50;
Height:= 20;
FIsChecked:= False;
FThumbWidth:= 15;
FThumbHeight:= 15;
FThumbRound:= 3;
end;
destructor TListItemSwitch.Destroy;
begin
inherited;
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.DoSwitch;
begin
FIsChecked:= not FIsChecked;
if Assigned(OnSwitch) then
OnSwitch(Self);
Invalidate;
end;
procedure TListItemSwitch.SetIsChecked(const AValue: Boolean);
begin
FIsChecked:= AValue;
Invalidate;
end;
procedure TListItemSwitch.SetThumbWidth(const Value: Single);
begin
FThumbWidth := Value;
Invalidate;
end;
procedure TListItemSwitch.SetThumbHeight(const Value: Single);
begin
FThumbHeight := Value;
Invalidate;
end;
procedure TListItemSwitch.SetThumbRound(const Value: Single);
begin
FThumbRound := Value;
Invalidate;
end;
procedure TListItemSwitch.SetThumbStyle(const Value: TLISwitchThumbStyle);
begin
FThumbStyle := Value;
Invalidate;
end;
procedure TListItemSwitch.Render(const Canvas: TCanvas;
const DrawItemIndex: Integer; const DrawStates: TListItemDrawStates;
const SubPassNo: Integer);
var
R, R2: TRectF;
D: Single;
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, FThumbRound, FThumbRound,
[TCorner.TopLeft, TCorner.TopRight, TCorner.BottomLeft, TCorner.BottomRight],
1.0, TCornerType.Round);
R2.Top:= R.Top + (R.Height/2) - (FThumbHeight/2);
R2.Height:= FThumbHeight;
D:= R2.Top - R.Top;
if IsChecked then begin
R2.Left:= R.Right - FThumbWidth - D;
end else begin
R2.Left:= R.Left + D;
end;
R2.Width:= FThumbWidth;
Canvas.Fill.Color:= TAlphaColorRec.Black;
Canvas.FillRect(R2, FThumbRound, FThumbRound,
[TCorner.TopLeft, TCorner.TopRight, TCorner.BottomLeft, TCorner.BottomRight],
1.0, TCornerType.Round);
finally
Canvas.EndScene;
end;
end;
end.
uListViewSwitchTest.pas
unit uListViewSwitchTest;
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,
JD.ListViewObjects;
type
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}
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
var
X: Integer;
function A: TListViewItem;
begin
Result:= ListView1.Items.Add;
end;
begin
ListView1.Align:= TAlignLayout.Client;
for X := 1 to 50 do
A;
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;
end;
end;
end.
Es ist etwas sollte wie folgt aussehen:
Die Signatur von TListItemDrawable.Render hat sich in 10.1 Berlin geändert, scheint aber die Funktionalität nicht zu beeinträchtigen. Mit der Änderung von Dalija Prasnikar (unten) funktioniert es gut. – nolaspeaker