问题
I have this (now working) code based on bits I picked up various places:
procedure TFormMain.imgMapsGesture(Sender: TObject;
const EventInfo: TGestureEventInfo; var Handled: Boolean);
var
LObj: IControl;
LImage: TImage;
W: Single;
H: Single;
begin
LImage := nil;
LObj := Self.ObjectAtPoint(ClientToScreen(EventInfo.Location));
if (LObj is TImage) and (LObj.Visible) then
begin
LImage := TImage(LObj.GetObject);
if (LImage <> imgMaps) then
LImage := nil
;
end
;
if LImage = nil then
Exit
;
if LImage.Bitmap = nil then
Exit
;
case EventInfo.GestureID of
igiZoom:
begin
if (EventInfo.Distance < 1) then
Exit
;
if
(not(TInteractiveGestureFlag.gfBegin in EventInfo.Flags))
and
(not(TInteractiveGestureFlag.gfEnd in EventInfo.Flags))
then
begin
W := LImage.Width + 2 * ((EventInfo.Distance - FLastDistanceZoom) / 3);
H := LImage.Height + 2 * ((EventInfo.Distance - FLastDistanceZoom) / 3);
if
(W < layoutMapsContent.Width)
or
(H < layoutMapsContent.Height)
then
begin
W := layoutMapsContent.Width;
H := layoutMapsContent.Height;
end
;
LImage.Width := W;
LImage.Height := H;
FLastDistanceZoom := EventInfo.Distance;
end
;
end
;
igiPan:
begin
if
(not(TInteractiveGestureFlag.gfEnd in EventInfo.Flags))
then
begin
if (not(TInteractiveGestureFlag.gfBegin in EventInfo.Flags)) then
begin
LImage.Position.X := LImage.Position.X + (EventInfo.Location.X - FMapsLastPositionPan.X);
LImage.Position.Y := LImage.Position.Y + (EventInfo.Location.Y - FMapsLastPositionPan.Y);
end
;
FMapsLastPositionPan.X := EventInfo.Location.X;
FMapsLastPositionPan.Y := EventInfo.Location.Y;
end
;
end
;
I got zoom working fairly well (not in simulator though, but on iOS iPhone), however panning is not working at all. When panning in simulator I can see eventdisance is always 0. I have enabled pan + zoom geatures on the TImage.
回答1:
I doubt the code you picked up in various places actually works:
The documentation on TGestureInfo clearly states that
[...] Distance is only set for the zoom and two finger tap gestures (TInteractiveGesture = igZoom or igTwoFingerTap). [...]
That means that you will have to keep track of the position the finger was registered in the previous call of onGesture
. You can then do something regarding the difference of EventInfo.Location
then and EventInfo.Location
now. Of course, this is only going to work if gfBegin
is not in GestureEvent.Flags
because you won't have a valid value for a previous position but you already know that.
Additionally, you might have a look at EventInfo.InertiaVector
for "stuff continues moving for a bit when you lift your finger". But that's entirely optional.
Also, if you're handling a gesture (no matter if interactive or standard gesture), you should set Handled
to True
. This way, you don't risk another component trying to handle the gesture. But to be honest, I'm not exactly sure if this is also the case with FireMonkey. With Vcl, it is. Compare the documentation for FMX.Types.TInteractiveGestures with Vcl.Controls.TInteractiveGestureOption. Better safe than sorry.
回答2:
Hi I have been developing a custom fmx listbox with a scroll bar. I found that the pan interactive gesture event is handled differently between windows and ios. In ios TInteractiveGestureFlag.gfInertia flag isn't set for an inertia event the absence of the gfBegin and gfEnd flags indicate an inertia pan event is taking place.
fvscroll is a standard scroll bar component.
scmfx,scmfy are private class variables TopItem sets the topitem of my custom listbox ItemHeight is the height of a listbox item
procedure TFCListBox.FlickScroll(const Ev: TGestureEventInfo);
var
N:TDateTime;
dy,dx,dz,rad:single;
begin
if TInteractiveGestureFlag.gfBegin in ev.flags then
begin
PanStartTime := N;
PanStartEv := Ev;
scrollstart := fvscroll.value;
rad := DegToRad(RotationAngle);
scmfx := sin(rad);
scmfy := cos(rad);
end;
if (TInteractiveGestureFlag.gfInertia in ev.Flags) or (ev.Flags = []) then
begin
dy := (Ev.Location.Y - PanStartEv.Location.y) *scmfy;
dx := (Ev.Location.X - PanStartEv.Location.X) *scmfx;
dz := dx - dy;
fvscroll.Value := scrollstart + dz;
end;
if TInteractiveGestureFlag.gfEnd in ev.Flags then
begin
TopItem := Round(fvScroll.Value/ItemHeight);}
end;
end;
I hope this is helpful
来源:https://stackoverflow.com/questions/17907730/delphi-ios-and-pan-gesture-distance-always-zero