You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 14:04:52