Delphi iOS and pan gesture - distance always zero
Asked Answered
T

2

3

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.

Tangram answered 28/7, 2013 at 11:30 Comment(0)
W
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.

Waves answered 28/7, 2013 at 20:50 Comment(2)
Thanks for your comments which will help me in correct direction. I will work with it today and reurn. Just for reference: Yes. Only zoom works. Pan never did (neither the original or what I changed it into)Tangram
I updated code an acceepted answer. I still have a problem with panning "jumping" to last finger let go off screen when performing zoom + pan at same time. See: #17920770Tangram
P
0

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

Pycnometer answered 28/8, 2013 at 11:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.