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

Android 12及以上双屏同时显示系统软键盘实现方案问询

双屏同时显示系统软键盘问题(Android 12+)

需求与现状

  • 需求:Android 12及以上设备的主、副显示屏同时显示系统默认软键盘
  • 当前问题:软键盘仅能在单个显示屏显示,切换输入框焦点时,原显示屏软键盘自动关闭,仅当前焦点所在屏显示键盘
  • 期望行为:主、副屏同时显示系统软键盘

核心疑问

若系统默认方案不可行,车机类多屏设备(如中控屏与乘客屏)如何实现双屏同时显示键盘?


系统默认API的限制

Android系统的InputMethodManager默认采用单焦点绑定软键盘的设计:同一时刻仅能有一个输入焦点关联软键盘实例,切换焦点时系统会自动销毁原屏的软键盘会话,这是系统层面的固有逻辑,无法通过常规showSoftInput方法绕过。


解决方案

方案1:多输入法会话尝试(系统API方向)

Android 12+提供了InputMethodManager.createInputMethodSession()方法,可为不同Display创建独立的输入法会话,但该方案依赖输入法应用支持多会话同时激活——大部分系统默认输入法(如Gboard)不支持此特性,需定制第三方输入法或修改系统输入法源码。

修改后的POC代码示例:

class MainActivity : AppCompatActivity() {
    private lateinit var displayManager: DisplayManager
    private lateinit var inputMethodManager: InputMethodManager
    private var primarySession: InputMethodSession? = null
    private var secondarySession: InputMethodSession? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
        inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager

        setupMultipleDisplays()
    }

    private fun setupMultipleDisplays() {
        val displays = displayManager.displays
        if (displays.size >= 2) {
            try {
                val secondaryDisplay = displays[1]
                val secondaryPresentation = SecondaryDisplayPresentation(this, secondaryDisplay)
                secondaryPresentation.show()

                // 为双屏创建独立输入法会话
                primarySession = inputMethodManager.createInputMethodSession(object : InputMethodCallback() {})
                secondarySession = inputMethodManager.createInputMethodSession(object : InputMethodCallback() {})

                setupDisplayInputs(displays)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    private fun setupDisplayInputs(displays: Array<Display>) {
        val primaryEditText: EditText? = findViewById(R.id.primaryEditText)
        primaryEditText?.setOnFocusChangeListener { view, hasFocus ->
            if (hasFocus) {
                showSoftInputForSession(view, primarySession)
                // 强制触发副屏键盘显示
                findViewById<EditText>(R.id.secondaryEditText)?.let {
                    showSoftInputForSession(it, secondarySession)
                }
            }
        }

        val secondaryEditText: EditText? = findViewById(R.id.secondaryEditText)
        secondaryEditText?.setOnFocusChangeListener { view, hasFocus ->
            if (hasFocus) {
                showSoftInputForSession(view, secondarySession)
                // 强制触发主屏键盘显示
                findViewById<EditText>(R.id.primaryEditText)?.let {
                    showSoftInputForSession(it, primarySession)
                }
            }
        }
    }

    private fun showSoftInputForSession(view: View, session: InputMethodSession?) {
        view.requestFocus()
        session?.showSoftInput(InputMethodManager.SHOW_IMPLICIT, null)
    }

    inner class SecondaryDisplayPresentation(context: Context, display: Display) : Presentation(context, display) {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.custom_keyboard)
        }
    }
}

方案2:车机场景自定义键盘实现(可行方案)

车机多屏设备的主流解决方案是自定义软键盘,完全绕过系统输入法的单会话限制:

  1. 为主、副屏分别实现独立的自定义键盘View(可复用同一布局)
  2. 将键盘View与对应显示屏的输入框绑定,手动处理输入事件
  3. 不受系统焦点影响,可自由控制双屏键盘的显示/隐藏

核心实现代码片段:

// 绑定主屏输入框与自定义键盘
val primaryEditText: EditText = findViewById(R.id.primaryEditText)
val primaryKeyboard: View = findViewById(R.id.primary_keyboard)
bindCustomKeyboard(primaryEditText, primaryKeyboard)

// 绑定副屏输入框与自定义键盘
val secondaryPresentation = SecondaryDisplayPresentation(this, displays[1])
val secondaryEditText: EditText = secondaryPresentation.findViewById(R.id.secondaryEditText)
val secondaryKeyboard: View = secondaryPresentation.findViewById(R.id.secondary_keyboard)
bindCustomKeyboard(secondaryEditText, secondaryKeyboard)

// 自定义键盘绑定逻辑
private fun bindCustomKeyboard(editText: EditText, keyboardView: View) {
    keyboardView.visibility = View.VISIBLE
    // 示例:绑定字母按键
    keyboardView.findViewById<Button>(R.id.key_a).setOnClickListener {
        editText.append("a")
    }
    keyboardView.findViewById<Button>(R.id.key_backspace).setOnClickListener {
        val text = editText.text
        if (text.isNotEmpty()) editText.setText(text.subSequence(0, text.length - 1))
    }
    // 其他按键同理扩展
}

内容的提问来源于stack exchange,提问作者Star

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 21:05:01