Jump to content
Sign in to follow this  
Nico Preto

Detect shake gesture on IOS

Recommended Posts

Have you looked into iOSApi.CoreMotion? It does sound like a good place to start.

Share this post


Link to post

I've created a gist here, but also including it in this post:

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls, FMX.Controls.Presentation,
  System.TypInfo,
  Macapi.ObjectiveC, Macapi.Helpers,
  iOSapi.UIKit, iOSapi.Foundation;

type
  IShakeView = interface(UIView)
    ['{21B0BCE6-8D07-40BA-943C-DC4B1A99D3CA}']
    function canBecomeFirstResponder: Boolean; cdecl;
    procedure motionBegan(motion: UIEventSubtype; withEvent: UIEvent); cdecl;
    procedure motionEnded(motion: UIEventSubtype; withEvent: UIEvent); cdecl;
  end;

  TShakeView = class(TOCLocal)
  private
    FOnShake: TNotifyEvent;
    procedure DoShake;
    function GetView: UIView;
    procedure InitView;
  protected
    function GetObjectiveCClass: PTypeInfo; override;
  public
    { IShakeView }
    function canBecomeFirstResponder: Boolean; cdecl;
    procedure motionBegan(motion: UIEventSubtype; withEvent: UIEvent); cdecl;
    procedure motionEnded(motion: UIEventSubtype; withEvent: UIEvent); cdecl;
  public
    constructor Create;
    procedure BecomeFirstResponder;
    property View: UIView read GetView;
    property OnShake: TNotifyEvent read FOnShake write FOnShake;
  end;

  TForm1 = class(TForm)
    Label1: TLabel;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    FShakeView: TShakeView;
    procedure ShakeViewShakeHandler(Sender: TObject);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

uses
  FMX.Platform.iOS;

{ TShakeView }

constructor TShakeView.Create;
begin
  inherited;
  InitView;
end;

procedure TShakeView.InitView;
var
  LView: Pointer;
begin
  // Using a zero-sized rect because this view won't actually be seen
  LView := GetView.initWithFrame(CGRectFromRect(TRectF.Empty));
  if GetObjectID <> LView then
    UpdateObjectID(LView);
end;

procedure TShakeView.BecomeFirstResponder;
begin
  GetView.becomeFirstResponder;
end;

function TShakeView.canBecomeFirstResponder: Boolean;
begin
  Result := True;
end;

procedure TShakeView.DoShake;
begin
  if Assigned(FOnShake) then
    FOnShake(Self);
end;

function TShakeView.GetObjectiveCClass: PTypeInfo;
begin
  Result := TypeInfo(IShakeView);
end;

function TShakeView.GetView: UIView;
begin
  Result := UIView(Super);
end;

procedure TShakeView.motionBegan(motion: UIEventSubtype; withEvent: UIEvent);
begin
  //
end;

procedure TShakeView.motionEnded(motion: UIEventSubtype; withEvent: UIEvent);
begin
  if withEvent.subtype = UIEventSubtypeMotionShake then
    DoShake;
end;

{ TForm1 }

constructor TForm1.Create(AOwner: TComponent);
begin
  inherited;
  FShakeView := TShakeView.Create;
  FShakeView.OnShake := ShakeViewShakeHandler;
  WindowHandleToPlatform(Handle).View.addSubview(FShakeView.View);
  Button1Click(Button1);
end;

destructor TForm1.Destroy;
begin
  FShakeView.Free;
  inherited;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  FShakeView.BecomeFirstResponder;
  Label1.Text := 'Waiting for shake';
end;

procedure TForm1.ShakeViewShakeHandler(Sender: TObject);
begin
  Label1.Text := 'Shaked me!';
end;

end.

 

  • Like 3

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×