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
相关产品推荐
相关产品推荐

