アイテムごとにFiremonkeyのTListView
コントロールで使用するカスタムスイッチオブジェクトを作成しています。 1つの変なグリッチを除いて、すべてが期待通りに機能します。ユーザが項目の1つをクリックして特定のスイッチオブジェクト上でクリックしていない場合は、スイッチをトグルします。私は、ユーザーがリスト項目をクリックしたときにMouseDown
イベントがトリガーされていると想定しています。リストビューで捕捉されているクリックイベント親アイテム
ユーザーが実際のスイッチをクリックしたときにのみクリックイベントが適用されるように制限するにはどうすればよいですか。
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.
それは次のようなものになります。
TListItemDrawable.Renderのシグネチャが10.1 Berlinで変更されましたが、機能には影響していないようです。 Dalija Prasnikarの変更(下記)が実装されているので、うまくいきます。 – nolaspeaker