Android libGDX 项目按键时弹出软键盘,如何阻止?
如果游戏窗口只需接收键盘按键,完全不需要通过输入法输入文本,可以在 MainActivity 中添加 FLAG_ALT_FOCUSABLE_IM。窗口保持可聚焦时,这个标志会阻止它成为输入法的目标,同时保留接收按键焦点的能力。Android API 文档说明了这一行为。
现有材料不足以确定是哪一次系统或输入法调用触发了弹出,因此不能直接认定这是 ScrCpy 或 libGDX 1.14.0 的已知缺陷。以下修改适用于明确不需要 IME 的游戏窗口,还需要在出现问题的设备上验证。
为什么没有文本框,也可能涉及输入法?
libGDX 的渲染 View 也可能提供文本输入接口。1.14.0 的 GLSurfaceView20 实现了 onCreateInputConnection(),会设置 EditorInfo.inputType 并返回 BaseInputConnection。因此,仅凭示例中没有 EditText,无法排除输入法参与的可能。libGDX 1.14.0 源码
这只能说明该 View 具备输入法连接能力,不能单独证明按下字母、数字或空格后一定会显示软键盘。触发条件还可能与 Android 版本、当前输入法、键盘识别方式及输入事件来源有关,而现有描述没有提供这些信息。
在 Activity 中禁止当前窗口与 IME 交互
可以将 MainActivity.kt 改为:
import android.os.Bundle
import android.view.WindowManager
import com.badlogic.gdx.backends.android.AndroidApplication
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration
class MainActivity : AndroidApplication() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
window.addFlags(
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
)
val config = AndroidApplicationConfiguration().apply {
useImmersiveMode = true
}
initialize(HelloWorldGame(), config)
}
}
不要同时添加 FLAG_NOT_FOCUSABLE:它会使窗口无法获得按键输入焦点,也会改变 FLAG_ALT_FOCUSABLE_IM 的作用条件。这里需要保持窗口可聚焦,同时阻止当前窗口与输入法交互。窗口标志说明
这项修改不需要调整 SpriteBatch、BitmapFont 或 Gradle 中的 native 库复制任务。
为什么之前的处理没有解决?
stateAlwaysHidden 不会永久禁用软键盘
SOFT_INPUT_STATE_ALWAYS_HIDDEN 指定窗口获得焦点时应隐藏软键盘,但不会关闭窗口使用输入法的能力。窗口获得焦点后,软键盘仍可能因后续输入法交互再次显示。状态标志说明
按键捕获和输入法可见性属于不同的控制环节
Gdx.input.setCatchKey(...) 用于控制指定按键是否被捕获;InputProcessor 用于处理交给游戏的输入事件。它们都没有提供禁止窗口连接 IME 的设置。
在 Activity 的 onKeyDown() 或 onKeyUp() 中返回 true,也不能保证影响已经由输入法处理的事件。为所有按键统一返回 true 还可能吞掉游戏需要的输入。建议撤掉排查时添加的这些拦截,再验证窗口标志的效果。
如何确认修改有效?
在原先能够复现的环境中重新启动 Activity,依次按下 [、]、字母、数字和空格,检查软键盘是否仍然出现,同时确认游戏仍能收到按键。
可以临时在 HelloWorldGame.create() 中添加以下日志,观察交给 libGDX 的事件:
Gdx.input.inputProcessor = object : InputAdapter() {
override fun keyDown(keycode: Int): Boolean {
Gdx.app.log("Keyboard", "keyDown=$keycode")
return true
}
override fun keyTyped(character: Char): Boolean {
Gdx.app.log("Keyboard", "keyTyped=$character")
return true
}
}
需要导入 com.badlogic.gdx.Gdx 和 com.badlogic.gdx.InputAdapter。如果已有输入处理器,应将日志加入现有处理流程,避免直接替换。这里的返回值表示事件在 libGDX 输入处理链中已被处理,不代表关闭了系统输入法。
若仍然复现,下一步应记录 Android 版本、输入法名称,以及输入来自实体键盘、ScrCpy 还是 emulator。对照测试时每次只改变一个条件,并留意弹出的内容是否确实属于当前 Activity 的 IME;这个窗口标志不负责禁止其他窗口显示输入法。
后续需要输入昵称或聊天怎么办?
FLAG_ALT_FOCUSABLE_IM 会阻止当前窗口与输入法交互,因此会影响中文候选词、组合输入等依赖 IME 的文本输入能力。如果同一窗口后续需要文本输入,应先在 Android UI 线程清除该标志,再按实际输入组件的流程请求焦点、显示输入法:
runOnUiThread {
window.clearFlags(
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
)
}
清除标志只恢复窗口使用输入法的条件,不会自动显示键盘。若 ScrCpy 的输入方式依赖文本注入而非直接发送按键,也应单独验证禁用 IME 后的输入表现。
备注:内容仅供参考。
