Chromebook 的输入兼容性

笔记本电脑用户使用的输入设备通常与手机用户不同。

在 Chromebook 上运行时,Android 应用会发现所处的环境并不适合其原本的设计方式,因为它们显示在配备鼠标、触控板和键盘的笔记本电脑上的窗口内。虽然 Android 确实支持这类设备,但很少在应用中正确实现。为了使这些应用能正常运行,Chromebook 默认情况下采用一种适用于所有应用的兼容模式。

兼容模式

在兼容模式下,应用接收事件的方式与 Android API 提供事件的方式有所不同。对于不想实现 Chromebook 专属功能,但希望以触摸操作为中心的应用可以正常运行的开发者来说,此模式很有用。

兼容模式会引入以下行为:

  • 触控板滚动可以模拟用两根“手指”触摸屏幕滚动。
  • 鼠标滚轮滚动也可以起到相同的效果。
  • 所有测量和事件的行为方式就像应用窗口是全屏显示的一样。诸如 getRawXgetRawY 之类的方法可能不会返回显示空间坐标,而是返回窗口空间坐标。

根据应用的目标 API 级别,兼容模式会或多或少地提供这些兼容性处理。

使用 android.hardware.type.pc

如果要优化应用以使其在 Chromebook 上运行良好并能充分利用输入设备,请在应用清单中声明以下内容:

<uses-feature
        android:name="android.hardware.type.pc"
        android:required="false" />
    

这样可以告知 Android 您的目标设备是通常配备键盘、鼠标和触控板的 PC 设备。它会停用兼容模式,并允许您开发鼠标和触控板的自定义行为。

注意 DecorCaptionView

在自由格式窗口模式下,应用标题栏是视图层次结构的一部分并且由您控制。您通常不需要注意这一点,但在某些情况下,您必须格外小心:

  • 不要乱用 Window.getDecorView()。如果要添加顶级视图,请将其添加到已设为 Activity.setContentView() 的视图中。
  • Activity.setContentView() 不会在应用的 (0, 0) 处。这是标题栏所在的位置。
  • 尽可能避免使用 MotionEvent.getRawX()MotionEvent.getRawY()。如果确实使用了这些方法,请将其与 View.getLocationOnScreen() 结合使用,以将坐标转换为视图空间坐标。

输入设备支持

通过 android.hardware.type.pc 标记将 PC 设备设为目标设备后,您的应用会收到以下事件:

鼠标和触控板支持

鼠标和触控板都可以生成 MotionEvents,就像触摸事件一样。您可以检查 MotionEvent.getSource() 来区分 SOURCE_MOUSESOURCE_TOUCHSCREEN

  • 鼠标/触控板移动。 生成 ACTION_HOVER_MOVE 事件。这些事件在 View.onGenericMotionEvent() 中进行处理。
  • 鼠标/触控板按钮。ACTION_BUTTON_PRESSACTION_BUTTON_RELEASE 事件发送到 View.onGenericMotionEvent()。您也可以使用 getButtonState() 检查所有鼠标/触控板事件中的按下按钮状态。
  • 触控板滚动。 用两根手指在触控板上滚动的报告方式与触摸屏拖动事件类似,可实现平滑和动态滚动。如果要让触摸屏拖动和触控板滚动表现出不同的行为,请使用 getSource()
  • 鼠标滚轮滚动。 鼠标滚轮滚动会作为 ACTION_SCROLL 事件报告给 View.onGenericMotionEvent()
  • 鼠标/触控板点击并拖动。 点击并拖动事件与触摸屏拖动事件非常类似。您可以使用 getButtonState() 区分点击并拖动事件与触控板滚动事件。点击并拖动事件始终都会附带一个按钮,而触控板滚动事件则不会。

右键点击支持

处理右键点击事件(也称为“上下文点击”事件)非常简单,只需将 View.OnContextClickListener 设为您的视图即可。

Kotlin

    yourView.setOnContextClickListener {
        //display context click options
        true
    }
    

Java

    yourView.setOnContextClickListener(new View.OnContextClickListener() {
    @Override
      public boolean onContextClick(View view) {
        //display context click options
        return true;
      }
    });
    

此方法是在 API 级别 23 中添加的,因此,如果您希望在可能运行旧版 Android 系统的其他设备上获得相同的功能,则可以使用如上所示的通用动作事件

键盘

键盘输入在桌面设备和笔记本电脑设备上非常重要。它也是无障碍功能不可或缺的要素。

要激活适当的输入焦点,您应遵循默认 Android API 中所述的常规资源添加准则:

  • 如果您要自行处理键盘输入,可以通过 KeyEvent.callback 使用默认函数。无需处理 TextEdit 元素内的键盘输入。
  • 如果您要自行修改文本,应使用 onKeyDownonKeyLongPressonKeyUp 事件,但不能使用 onKeyPreIME 事件,除非您要全面实现 IME(不建议这样做)。

触控笔

触控笔报告事件的方式与触摸屏通过 View.onTouchEvent() 报告事件的方式类似。不过,触控笔事件会携带更多信息,应予以考虑:

  • MotionEvent.getToolType()。工具类型可让您区分 TOOL_TYPE_FINGERTOOL_TYPE_STYLUS 事件。此外,还可让您通过 TOOL_TYPE_ERASER 识别笔的橡皮擦一端(如果用户有的话)的使用。
  • MotionEvent.getPressure()。表示施加到触控笔(如果支持)的物理压力。
  • MotionEvent.AXIS_TILT/AXIS_ORIENTATION。可与 MotionEvent.getAxisValue() 一起使用,以读取触控笔(如果支持)的物理倾斜度和方向。

历史点

Android 会对输入事件进行批处理,让其每帧传送一次。不过,触控笔可以按高得多的频率(200Hz 很常见)报告输入事件。创建绘图应用时,请务必使用从历史 API 获取的点:

  • MotionEvent.getHistoricalX()
  • MotionEvent.getHistoricalY()
  • MotionEvent.getHistoricalPressure()
  • MotionEvent.getHistoricalAxisValue()

防止手掌误触

Chrome 操作系统会尝试识别用户是否将手掌放到了屏幕上,以免误向应用报告输入事件。不过,系统并不总是能够做到这一点,有时可能会在识别出手掌误触之前报告了触摸事件。在这种情况下,系统将通过报告 ACTION_CANCEL 事件来取消触摸。

此事件会告知应用所有触摸都无效,应用应撤消由触摸引起的所有交互。例如,对于绘图应用,应用会临时绘制新线条,只有在一系列触摸事件彻底完成后,才会将这些线条提交到画布。如果取消了触摸,则可以轻松移除这些临时线条。

记事 intent

Chrome 操作系统会显示经过注册能够处理包含 org.chromium.arc.intent.action.CREATE_NOTE 操作和 Intent.CATEGORY_DEFAULT(即 android.intent.category.DEFAULT)类别的 intent 的应用列表,如以下代码段所示:

  <intent-filter>
        <action android:name="org.chromium.arc.intent.action.CREATE_NOTE" />
        <category android:name="android.intent.category.DEFAULT" />
      </intent-filter>
    

用户将能够选择一个应用,该应用稍后会在收到对记事应用的请求时启动。

当用户请求创建新记事时,该应用会使用仅包含上述操作和类别的 intent 来启动。该应用应在适当的模式下创建一条空白记事,在这种模式下,用户可使用触控笔进行书写。

当用户请求标注图片(例如屏幕截图或下载的图片)上下文时,该应用会使用具有上述操作和类别的 intent(包括 ClipData,它包含一个或多个带有 content:// URI 的项目)来启动。该应用应在适当的模式下创建一条记事(将附加的第一张图片用作背景图片),在这种模式下,用户可使用触控笔进行绘制。

无触控笔测试

  1. 切换到开发模式并使设备可写入
  2. 按 Ctrl+Alt+F2 键(向前箭头)以打开 shell。
  3. 运行命令 sudo vi /etc/chrome_dev.conf
  4. --ash-enable-palette 添加到文件末尾的新行。
  5. 按 Ctrl+Alt+F1 键(向后箭头)以返回界面。
  6. 退出并重新登录。

现在,您会看到触控笔入口点:- 在任务栏中,您可以点按触控笔按钮,然后选择“新建记事”。这样应该会在您的应用中打开一条空白绘图记事。- 如果您截取屏幕截图(在任务栏中,点按触控笔按钮,然后选择“截取屏幕”)或下载图片,应该会在通知中看到“标注图片”选项。这样应该会打开您的应用,并且图片已做好标注的准备。

游戏手柄

Chromebook 最多支持 4 个游戏手柄,并遵循标准的 Android API 来报告它们。遗憾的是,并非专为 Android 设计的游戏手柄却能显示正确的按钮映射是一种很普遍的现象。