如何避免Android LibGDX项目中弹出软键盘?
LibGDX Android端按键触发软键盘弹出问题解决
背景
时隔多年重新尝试LibGDX开发,开发期间使用ScrCpy工具镜像设备画面。
问题描述
已实现的键盘按键处理功能运行正常,但按下部分按键(如[、]、数字、英文字母、空格键等)时,系统软键盘会自动弹出,效果如下:
最小复现代码
MainActivity.kt
class MainActivity : AndroidApplication() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val config = AndroidApplicationConfiguration().also { configuration: AndroidApplicationConfiguration -> configuration.useImmersiveMode = true } initialize(HelloWorldGame(), config) } }
HelloWorldGame.kt
class HelloWorldGame : ApplicationAdapter() { private lateinit var batch: SpriteBatch private lateinit var font: BitmapFont override fun create() { batch = SpriteBatch() font = BitmapFont().apply { color = Color.WHITE data.setScale(3f) } } override fun render() { ScreenUtils.clear(Color.valueOf("#6750A4")) batch.begin() font.draw(batch, "Hello LibGDX World!", 100f, 500f) batch.end() } override fun dispose() { batch.dispose() font.dispose() } }
Gradle配置
根目录build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { id("com.android.application") version "9.1.0" apply false }
模块build.gradle
import org.gradle.kotlin.dsl.withType import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile plugins { id("com.android.application") } android { namespace = "com.lb.myapplication" compileSdk = 37 defaultConfig { applicationId = "com.lb.myapplication" minSdk = 24 targetSdk = 36 versionCode = 1 versionName = "1.0" } buildTypes { release { isMinifyEnabled = false proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) } } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } tasks.withType<KotlinJvmCompile>().configureEach { compilerOptions { jvmTarget.set(JvmTarget.JVM_17) } } sourceSets { getByName("main") { jniLibs.srcDirs("libs") } } } val natives by configurations.creating dependencies { implementation("androidx.core:core-ktx:1.18.0") implementation("com.badlogicgames.gdx:gdx:1.14.0") implementation("com.badlogicgames.gdx:gdx-backend-android:1.14.0") val gdxVersion = "1.14.0" natives("com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-arm64-v8a") natives("com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a") natives("com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86") natives("com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86_64") } tasks.register("copyAndroidNatives") { inputs.files(natives) outputs.dir(file("libs")) doLast { natives.files.forEach { jar -> val outputDir = when { jar.name.contains("arm64-v8a") -> file("libs/arm64-v8a") jar.name.contains("armeabi-v7a") -> file("libs/armeabi-v7a") jar.name.contains("x86_64") -> file("libs/x86_64") jar.name.contains("x86") -> file("libs/x86") else -> null } outputDir?.let { copy { from(zipTree(jar)) into(it) include("*.so") } } } } } project.afterEvaluate { tasks.matching { it.name.contains("merge") && it.name.contains("JniLibFolders") }.configureEach { dependsOn("copyAndroidNatives") } }
已尝试无效方案
排除ScrCpy影响后,新建项目在Android模拟器中测试问题依然存在(仅Google Play Games模拟器无此现象,推测该模拟器无软键盘),普通Android应用及部分游戏无此问题。尝试过以下方法均无效:
- 在Manifest的Activity标签中设置
android:windowSoftInputMode="stateAlwaysHidden" - 在MainActivity中重写
onKeyDown、onKeyLongPress、onKeyUp方法并返回true - 在Activity代码中调用
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN) - 在LibGDX类中使用
Gdx.input.setCatchKey(Input.Keys...., true)和设置Gdx.input.inputProcessor
原因分析
LibGDX的Android后端默认会创建一个隐藏的EditText组件来处理文本输入,当按下字符类按键时,该组件会触发系统软键盘弹出。即使开启了沉浸式模式,系统仍会响应这类文本输入请求,导致软键盘自动弹出。
解决方法
核心方案:禁用LibGDX默认文本输入组件
修改MainActivity中的AndroidApplicationConfiguration配置,直接禁用默认的文本输入支持,从根源上阻止软键盘触发:
class MainActivity : AndroidApplication() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val config = AndroidApplicationConfiguration().also { it.useImmersiveMode = true it.useEditText = false // 禁用默认文本输入EditText } initialize(HelloWorldGame(), config) } }
备选方案:拦截特定按键事件
如果需要保留部分文本输入功能,可在MainActivity中重写dispatchKeyEvent方法,拦截会触发软键盘的按键事件:
override fun dispatchKeyEvent(event: KeyEvent): Boolean { val keyCode = event.keyCode // 拦截字符类、空格、括号等按键 if ((keyCode in KeyEvent.KEYCODE_0..KeyEvent.KEYCODE_9) || (keyCode in KeyEvent.KEYCODE_A..KeyEvent.KEYCODE_Z) || keyCode == KeyEvent.KEYCODE_SPACE || keyCode == KeyEvent.KEYCODE_LEFT_BRACKET || keyCode == KeyEvent.KEYCODE_RIGHT_BRACKET) { return true // 消费事件,不传递给系统 } return super.dispatchKeyEvent(event) }
验证
修改配置后,按下字符类按键时系统不会再弹出软键盘,同时LibGDX的按键处理功能可正常运行。
内容的提问来源于stack exchange,提问作者android developer
相关产品推荐
相关产品推荐

