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

Kivy在Android上的keyboard_suggestions异常行为问题求助

Kivy中TextInput开启keyboard_suggestions后的焦点切换Bug及优化方案

问题现象

给两个TextInput控件设置keyboard_suggestions: True和input_type: "text"后,出现以下异常:

  • 在第一个TextInput输入“Test”(未使用联想建议)
  • 直接点击第二个输入框并按下“1”,第一个输入框的内容会被自动粘贴到第二个输入框中

复现代码

from kivy.lang import Builder
from kivy.app import App


KV = """
BoxLayout:
 orientation: "vertical"
 TextInput:
  input_type:'text'
  keyboard_suggestions:True
 TextInput:
  input_type:'text'
  keyboard_suggestions:True
"""

class Test(App):
 def build(self):
  return Builder.load_string(KV)


Test().run()

问题原因推测

切换TextInput焦点时,keyboard_suggestions相关的状态未被正确重置。如果先手动收起键盘(点击右下角按钮或输入框外)再聚焦第二个输入框,功能就完全正常。

现有临时方案的问题

目前用的解决方法是在on_focus事件中,当控件获取焦点时先取消再重新聚焦,虽然能修复Bug,但键盘会闪烁两次,用户体验不佳。

更优解决方案

方案1:失去焦点时主动重置键盘建议状态

自定义TextInput类,在控件失去焦点时清空键盘建议缓存并销毁旧键盘,避免状态残留:

from kivy.lang import Builder
from kivy.app import App
from kivy.uix.textinput import TextInput

class FixedTextInput(TextInput):
    def on_focus(self, instance, value):
        super().on_focus(instance, value)
        if not value:
            # 失去焦点时重置键盘建议状态并销毁旧键盘
            self._keyboard_suggestions = None
            if self._keyboard:
                self._keyboard.dismiss()
                self._keyboard = None

KV = """
BoxLayout:
 orientation: "vertical"
 FixedTextInput:
  input_type:'text'
  keyboard_suggestions:True
 FixedTextInput:
  input_type:'text'
  keyboard_suggestions:True
"""

class Test(App):
 def build(self):
  return Builder.load_string(KV)


Test().run()

方案2:获取焦点前强制重建键盘

在控件获取焦点前销毁旧键盘,强制系统创建全新的键盘实例,彻底隔离前后输入框的状态:

class FixedTextInput(TextInput):
    def on_focus(self, instance, value):
        if value:
            # 获取焦点前销毁旧键盘,强制生成新键盘
            if self._keyboard:
                self._keyboard.dismiss()
                self._keyboard = None
        super().on_focus(instance, value)

方案3:容器层拦截焦点切换,先收键盘

给外层BoxLayout添加触摸事件检测,当点击另一个TextInput时,先收起当前激活的键盘,再切换焦点:

from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput

class MyBoxLayout(BoxLayout):
    def on_touch_down(self, touch):
        if touch.is_touch:
            # 找到当前有焦点的TextInput
            focused_input = None
            for child in self.children:
                if isinstance(child, TextInput) and child.focus:
                    focused_input = child
                    break
            # 点击的是另一个TextInput,先收键盘再切换焦点
            if focused_input and isinstance(touch.target, TextInput) and touch.target != focused_input:
                focused_input.focus = False
                if focused_input._keyboard:
                    focused_input._keyboard.dismiss()
        return super().on_touch_down(touch)

# KV中替换原BoxLayout为MyBoxLayout
KV = """
MyBoxLayout:
 orientation: "vertical"
 TextInput:
  input_type:'text'
  keyboard_suggestions:True
 TextInput:
  input_type:'text'
  keyboard_suggestions:True
"""

总结

方案1和方案2的体验最优,不会出现键盘闪烁的问题,建议优先尝试。如果是特定平台(如Android)的系统键盘适配Bug,也可以考虑升级Kivy到最新版本,查看官方是否已修复该问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 18:30:04