2016-05-07 8 views
2

アイテムごとに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. 

それは次のようなものになります。

enter image description here

+0

TListItemDrawable.Renderのシグネチャが10.1 Berlinで変更されましたが、機能には影響していないようです。 Dalija Prasnikarの変更(下記)が実装されているので、うまくいきます。 – nolaspeaker

答えて

5

MouseDownメソッドにエラーがあります。ユーザーは、それが押された1見るために彼らのMouseDownメソッドを呼び出し、そのすべての可視のサブコントロールを反復処理ListItemをクリックすると

function TListItemSwitch.MouseDown(const Button: TMouseButton; 
    const Shift: TShiftState; const MousePos: TPointF): Boolean; 
begin 
    Result := inherited; 
    if Result then begin 
    DoSwitch; 
    end; 
end; 

:それは次のようになります。 MouseDownメソッドがtrueを返す場合は、特定のサブコントロールが押されたことを意味します。あなたの場合、ロジックはTListItemSimpleControlに実装されており、継承します。

MouseDownのすべてのイベントに対して、制御範囲内でマウスが押されていなくても、DoSwitchロジックを実行していました。

関連する問題