Delphi Android:无法捕获鼠标滚轮事件

问题描述

我想在我的 Android 应用程序中始终在任何情况下捕获和处理鼠标滚轮事件,而该应用程序正在运行且可见。

我像这样使用了主表单的事件:

procedure TheaderfooterwithNavigation.FormMouseWheel(Sender: TObject;
  Shift: TShiftState; WheelDelta: Integer; var Handled: Boolean);
begin
  label2.text := inttostr(wheeldelta);
end;

它在 Windows 版本的应用程序中运行良好(Delphi 认同时为 Android 和 Windows 构建),但在 Android 版本中它似乎没有任何作用。

然后我将该过程添加到每个具有相同鼠标滚轮事件的组件中,结果完全相同。

OTG 鼠标滚轮在 android 设备上运行良好,滚动文本窗口等,只有我的 Delphi 应用程序似乎根本没有响应鼠标滚轮。

捕获鼠标滚轮事件需要什么?

解决方法

此解决方案的两个部分:

第 1 部分 - 它需要创建覆盖 View 的 Android onGenericMotionEvent 类的后代,并将事件传递给“委托”。我已将此代码添加到我的 Kastri 库中,但为了完整起见,我将在此处重复它们:

https://github.com/DelphiWorlds/Kastri/blob/master/Java/Base/GenericView/DWGenericView.java

package com.delphiworlds.kastri;

import android.content.Context;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.View;

public class DWGenericView extends View {

  private DWGenericViewDelegate mDelegate;

  public DWGenericView(Context context,DWGenericViewDelegate delegate) {
    super(context);
    mDelegate = delegate;
  }

  @Override
  public boolean onGenericMotionEvent(MotionEvent event) {
    if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
      switch (event.getAction()) {
        case MotionEvent.ACTION_SCROLL:
          mDelegate.onMouseWheel(event);
          return true;
      }
    }
    return super.onGenericMotionEvent(event);
  }

}

https://github.com/DelphiWorlds/Kastri/blob/master/Java/Base/GenericView/DWGenericViewDelegate.java

package com.delphiworlds.kastri;

import android.view.MotionEvent;

public interface DWGenericViewDelegate {

  public void onMouseWheel(MotionEvent event);

}

您需要将此 Java 代码编译成 jar 文件(例如使用 Android Studio),然后将其添加到 Delphi 项目管理器中 Android 平台下的库节点。

编辑:如果您在编译 jar 时遇到问题,我还构建了一个仅包含上述代码的:

https://github.com/DelphiWorlds/Kastri/blob/master/Lib/dw-genericview.jar

第 2 部分 - Java 代码的导入:

https://github.com/DelphiWorlds/Kastri/blob/master/API/DW.Androidapi.JNI.DWGenericView.pas

unit DW.Androidapi.JNI.DWGenericView;

interface

uses
  // Android
  Androidapi.JNIBridge,Androidapi.JNI.JavaTypes,Androidapi.JNI.GraphicsContentViewText;

type
  JGenericView = interface;
  JGenericViewDelegate = interface;

  JGenericViewDelegateClass = interface(IJavaClass)
    ['{AF4620B1-9D15-4B8D-82F1-A8A2C1F411DB}']
  end;

  [JavaSignature('com/delphiworlds/kastri/DWGenericViewDelegate')]
  JGenericViewDelegate = interface(IJavaInstance)
    ['{43A4AF5E-4BDB-48E9-9E1F-1F939E4384E4}']
    procedure onMouseWheel(event: JMotionEvent); cdecl;
  end;

  JGenericViewClass = interface(JViewClass)
    ['{9002B46F-C616-4428-8FCA-F86ED28BD55B}']
    {class} function init(context: JContext; delegate: JGenericViewDelegate): JGenericView; cdecl;
  end;

  [JavaSignature('com/delphiworlds/kastri/DWGenericView')]
  JGenericView = interface(JView)
    ['{77A9B1B8-9412-4074-9BBF-FF81F6364174}']
  end;
  TJGenericView = class(TJavaGenericImport<JGenericViewClass,JGenericView>) end;

implementation

end.

测试项目代码:

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.Memo.Types,FMX.Controls.Presentation,FMX.ScrollBox,FMX.Memo,Androidapi.JNI.GraphicsContentViewText,DW.Androidapi.JNI.DWGenericView;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
  private
    FGenericView: JGenericView;
    FGenericViewDelegate: JGenericViewDelegate;
  protected
    procedure DelegateMouseWheel(event: JMotionEvent);
  public
    constructor Create(AOwner: TComponent); override;
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

uses
  Androidapi.JNIBridge,Androidapi.Helpers,FMX.Platform.Android;

type
  TGenericViewDelegate = class(TJavaLocal,JGenericViewDelegate)
  private
    FForm: TForm1;
  public
    { JGenericViewDelegate }
    procedure onMouseWheel(event: JMotionEvent); cdecl;
  public
    constructor Create(AForm: TForm1);
  end;

{ TGenericViewDelegate }

constructor TGenericViewDelegate.Create(AForm: TForm1);
begin
  inherited Create;
  FForm := AForm;
end;

procedure TGenericViewDelegate.onMouseWheel(event: JMotionEvent);
begin
  FForm.DelegateMouseWheel(event);
end;

{ TForm1 }

constructor TForm1.Create(AOwner: TComponent);
begin
  inherited;
  FGenericViewDelegate := TGenericViewDelegate.Create(Self);
  FGenericView := TJGenericView.JavaClass.init(TAndroidHelper.Context,FGenericViewDelegate);
  WindowHandleToPlatform(Handle).FormLayout.addView(FGenericView);
end;

procedure TForm1.DelegateMouseWheel(event: JMotionEvent);
begin
  Memo1.Lines.Add('onMouseWheel: ' + JStringToString(event.toString));
end;

end.

代码创建 View 后代的实例,传递“委托”引用(将事件传递给表单代码),并将其添加到表单的本机布局中。

这将使您尽可能拥有一个 event 实例可用。使用相关方法计算delta等

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...