随着技术进步以及跨平台应用的普及,您的 Android 应用已经不再局限于在直板触屏设备运行了。更丰富的交互方式使得用户能够以更复杂的输入方式使用您的应用。所以作为开发者,是时候考虑为各种各样的设备提供强大的输入支持了。本文为您准备了关于更广泛、强大的输入支持的分享,欢迎您阅读。
如果您更喜欢通过视频了解此内容,请在此处查看:
Bilibili 视频链接
https://www.bilibili.com/video/BV1WS4y1o716/
输入 (input)
https://developer.android.google.cn/guide/input
要知道并非所有的用户都使用手机触摸屏与您的应用交互,一部分用户可能使用的是键盘和触控笔等,甚至一部分用户有无障碍需求。那么每位开发者都有必要花些时间去思考,如何使应用为尽可能多的用户带来愉快的使用体验?
无障碍
https://developer.android.google.cn/guide/topics/ui/accessibility
增强输入 (Enhanced input)
对于每种类型的输入设备,我们可以将应用的功能分为标准用例和增强用例两大类:
在提供基础功能外,要考虑添加独特且能为用户提供支持的功能,这才是开发者让自己应用真正脱颖而出的方法。例如,如下所示的 eDJing 这款应用,它添加了对键盘打碟和触控板搓碟以及 MIDI DJ 控制器的支持,用户手中的手机或 Chromebook 就能够立即摇身一变成为 DJ 工作站。
△ eDJing 应用使用场景
Cubasis 是一款一流的数字音频工作站应用,它发布了基于 Chrome OS 操作系统优化的新版本,凭借大屏幕的优势以及 MIDI 控制器连接 Chromebook 的便利性,不仅增强了功能,还提升了应用实用性。
△ Cubasis 应用使用场景
绘图类应用则更加注重: 蓝牙和 USB 绘图板能够持续正常的工作,以及在 Chrome OS 操作系统中将低延迟触控笔 API 应用到绘图和绘画应用中。
△ 绘图类应用使用场景
简而言之,用户希望能在您的应用中获得独特、愉悦、直观的体验,而这种体验由您来打造!
键盘输入支持
键盘被内置在 Chromebook 中,或是成为用户在使用可拆卸设备、平板电脑、可折叠设备和电视过程中日常体验的一部分。好消息是大多数基本键盘输入通常可以直接使用,除非您正致力于构建自己的屏幕键盘或从头开始编写自己的文本输入视图。
发送键支持 (KEYCODE_ENTER)
开发者需要在标准的 EditText 视图中为 Enter 键创建一个新行。如果您的应用中有聊天功能、反馈表单、简报注册或任何需要发送文本的功能,那么默认的换行行为肯定不是您所期望的,不用担心的是您所预期的发送功能很容易实现。
开发者需要在标准的 EditText 视图中为 Enter 键创建一个新行,此处显示了按下 Enter 键的代码,完整代码如下所示:
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
when (keyCode) {
KEYCODE_ENTER -> { // 撤销 onKeyUp 并监听 KEYCODE_ENTER
sendMessage()
return true // 如果应用已处理按键事件则确保返回 true
}
}
// 如果没有处理事件,则交回系统处理
return super.onKeyUp(keyCode, event) // 如果没有则将事件传递给 super
}
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
when (keyCode) {
KEYCODE_SPACE, KEYCODE_MEDIA_PLAY_PAUSE -> {
playOrpauseMedia();
return true
}
KEYCODE_MEDIA_NEXT -> {nextTrack(); return true }
KEYCODE_MEDIA_PREV -> {prevTrack(); return true }
}
// 如果没有处理事件,则交回系统处理
return super.onKeyUp(keyCode, event)
}
游戏键支持 (KEYCODE_W|A|S|D)
对于游戏应用,您可能希望包括对箭头键和 W、A、S、D 四个按键的支持,这同样很简单。您只需在 Android 文档中找到正确的键代码,并监听这些按键即可。完整代码如下所示:
when (keyCode) {
KEYCODE_W, DPAD_UP -> { goUp(); return true }
KEYCODE_A, DPAD_LEFT -> { goLeft(); return true }
KEYCODE_S, DPAD_DOWN -> { goDown(); return true }
KEYCODE_D, DPAD_RIGHT -> { goRight(); return true }
}
键代码
https://developer.android.google.cn/reference/android/view/KeyEvent
需要注意的是在提供键盘支持时通常要监听 onKeyUp,这样您就不必担心在按住某个键时,将会发送重复的 onKeyDown 事件。另外如果您想确保实现毫秒级的时间响应,您可以监听 onKeyDown 并自行处理重复的按键事件。完整代码如下所示:
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
when (keyCode) {
KEYCODE_F -> {
shootFireball()
return true
}
}
return super.onKeyUp(keyCode, event)
}
更多相关信息请访问: ChromeOS.dev
快捷键支持 (Ctrl+)
除了基本键盘按键,还需要考虑的是配置基于 Ctrl 的快捷键,复制、粘贴、撤消、重做等,很常见的快捷键适用于许多应用。出色的键盘支持将会帮助您的应用实现更多的功能,一些应用甚至更进一步将高级功能放在用户触手可及的地方,比如用户在使用 eDJing 应用时,只需按住 Ctrl 键就可以用触控板搓碟。
如下展示了用于撤消的 Ctrl+Z 快捷键的代码,这部分代码类似于前面的 onKeyUp 和 onKeyDown 代码,但使用了 dispatchKeyShortcutEvent 来指示元键组合。请注意此时按下 Alt、Ctrl 或 Shift 键即可触发此操作。完整代码如下所示:
override fun dispatchKeyShortcutEvent(event: KeyEvent): Boolean {
return when (event.getKeyCode()) {
KEYCODE_Z -> {
undoAction() // [Ctrl]+z, [Shift]+z, 或 [Alt]+z 触发
true
}
else -> {
super.dispatchKeyShortcutEvent(event)
}
}
}
如果您只希望响应特定的元键组合,可以使用 Meta_Alt_On,也可以使用类似 isShiftPressed() 或 isCtrlPressed() 的方法。完整代码如下所示:
when {
event.isCtrlPressed && event.isShiftPressed -> {
redoAction(); true // [Ctrl]+[Shift]+z 触发
}
event.isCtrlPressed -> {
undoAction(); true //[Ctrl]+z 触发
}
else -> { // 交给系统处理
super.dispatchKeyShortcutEvent(event)
}
}
根据此处代码,只有在同时按下 Ctrl+Z 时才会执行撤消操作,同样只有在同时按下 Ctrl+Shift+Z 时才会执行重做操作,并不会用到 Alt。
鼠标/触控板输入支持
△ 鼠标
右键点击支持
registerForContextMenu(myView)
// 首先为上下文菜单注册一个或多个视图,这将自动处理长按和右键点击两种操作。
...
override fun onCreateContextMenu(menu, view, menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo)
menuInflater.inflater(R.menu.myContextMenu, menu)
// 然后撤销 overrideonCreateContextMenu 并扩展正确的菜单布局,同一菜单可用于多个视图。
}
override fun onCreateContextMenu(item: MenuItem): Boolean {
return when(item.itemId){
R.id.myMenuItemId -> { menuItemAction(); true }
else -> { return super.onContextItemSelected(item) }
// 最后,设置 onContextItemSelected 指示选中特定菜单项时需要执行的操作。
}
}
myView.setOnContextClickListener {
performContextAction()
true
}
myView.setOnHoverListener { view, motionEvent -> //为视图设置 onHoverListener
when (motionEvent.action) {
ACTION_HOVER_ENTER -> {
view.pointerIcon = PointerIcon.getSystemIcon(
appIicationContext, PointerIcon.TYPE_HAND
)
view.setBackgroundColor(Color.BLUE)
true
} // 监听 HOVER_ENTER 事件并执行相应的操作。根据代码显示指针图标将变为手形且背景颜色将变为蓝色。
ACTION_HOVER_EXIT -> { resetUI(); }
else -> { false }
// 不要忘记设置当 HOVER_EXIT 发生时重置图标和背景颜色。
}
}
△ Minecraft: 教育版
view.requestPointerCapture()
...
view.releasePointerCapture()
...
{ _, motionEvent ->
计算自从上次 motionEvent 事件后的坐标增量
mouseChangeX = motionEvent.x
mouseChangey = motionEvent.y
计算自从上次 motionEvent 事件后的位移
val totalDistance = hypot(mouseChangeX, mouseChangeY)
doSomethingCool(totalDistance)
}
手势支持
https://developer.android.google.cn/training/gestures
触笔输入支持
如果您已经在应用中添加对指针的出色支持,那么对于大多数用例来说触控笔通常能够按预期正常工作。关于触控笔的一些增强功能非常值得关注,比如部分设备支持触控笔倾斜和按压,这有助于您在绘画或绘图应用添加一些出色的控件和功能。此外还有低延迟触控笔 API 可让您在绘画或绘图应用中获得最低延迟的显示响应,并提供可配置的描边预测,为您打造用笔在纸上绘图的体验。如需了解实际效果,请在受支持的 Chromebook 或 Android 设备上查看类似于 Concepts 的应用。
△ Concepts 应用对触控笔支持
http://github.com/chromeos/low-latency-stylus
在 Android 模拟器中使用触控笔
手柄输入支持
△ 游戏手柄
游戏手柄方向键与键盘箭头键的键代码是相同的,只需监听 KEYCODE_DPAD 事件即可同时处理这两者。游戏手柄按钮也有自己的键代码,您可以监听这些按钮就像这里为 X 按钮进行的设置一样。完整代码如下所示:
when (keyCode) {
BUTTON_X -> {
engageNitro(); return true
}
DPAD_UP, KEYCODE_W -> {
goForward(); return true
}
DPAD_LEFT, KEYCODE_A -> {
turnLeft(); return true
}
...
}
MIDI 输入支持
当涉及到专门的硬件时,需要针对设备和用例提供支持。MIDI 支持对于音乐和创意工具来说尤其重要,它允许广泛的、富有表现力的输入信号,从对压力敏感的钢琴键盘到具有滑块、旋钮、键盘等许多不同输入触发器的设备,都能提供支持。
如果您希望使用或了解更多 MIDI 相关的信息,Android Media Samples 库中提供了一些便捷的开源示例,可以帮助您开始使用 MIDI。请查看 MidiSynth 项目,特别是该项目中的 Synth Engine 模块。注意,从 Android 29 开始您还可以使用 NDK MIDI API。
回顾
大屏幕的 Android 设备已经出现而且愈发普及,在 Android 上提供出色的输入支持一直很重要,而对于可折叠设备、平板电脑和 Chrome 操作系统来说尤为重要。请思考您应用的输入处理以及如何增加互动、解锁新功能并提升应用体验。期待各位开发者投入精力构建精彩的 Android 应用,并为其添加了出色的输入处理!
推荐阅读