3

私はさまざまな場所で拾ったビットに基づいて、この(現在動作している)コードを持っています:

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
;

ズームはかなりうまく機能しましたが(シミュレーターではなく、iOS iPhoneで)、パンニングはまったく機能していません。シミュレータでパンすると、eventdisance が常に 0 であることがわかります。TImage でパン + ズーム ジェスチャを有効にしました。

4

2 に答える 2

1

さまざまな場所で取り上げたコードが実際に機能するとは思えません。

TGestureInfoのドキュメントには、次のように明確に記載されています。

[...] 距離は、ズームおよび 2 本指タップ ジェスチャ(TInteractiveGesture = igZoom または igTwoFingerTap) に対してのみ設定されます。[...]

つまり、前回の の呼び出しで指が登録された位置を追跡する必要がありonGestureます。EventInfo.Locationその後、当時とEventInfo.Location現在の違いに関して何かを行うことができます。もちろん、これが機能するのgfBeginは が入っていない場合だけです。GestureEvent.Flagsなぜなら、前の位置に有効な値がないからです。しかし、それはすでにわかっています。

さらに、EventInfo.InertiaVector「指を離すと、何かが少しの間動き続ける」ことを確認することもできます。しかし、それは完全にオプションです。

また、ジェスチャを処理している場合 (インタラクティブまたは標準ジェスチャに関係なく)、 に設定Handledする必要がありますTrue。このようにして、別のコンポーネントがジェスチャを処理しようとする危険を冒すことはありません。しかし、正直なところ、これが FireMonkey にも当てはまるかどうかは正確にはわかりません。Vclでは、そうです。FMX.Types.TInteractiveGesturesのドキュメントとVcl.Controls.TInteractiveGestureOptionを比較してください。転ばぬ先の杖。

于 2013-07-28T20:50:06.597 に答える
0

こんにちは、スクロールバー付きのカスタム fmx リストボックスを開発しています。パン インタラクティブ ジェスチャ イベントは、windows と ios の間で異なる方法で処理されることがわかりました。iOS では、慣性イベントに対して TInteractiveGestureFlag.gfInertia フラグが設定されていません。gfBegin フラグと gfEnd フラグがない場合、慣性パン イベントが発生していることを示します。

fvscroll は、標準のスクロール バー コンポーネントです。

scmfx、scmfy はプライベート クラス変数です TopItem はカスタム リストボックスのトップ項目を設定します ItemHeight はリストボックス項目の高さです

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;

これが役立つことを願っています

于 2013-08-28T11:49:13.610 に答える