Kivy, android i klawiatura systemowa

0

Witam.
Pewnie zwracam się do jednej osoby, ale chyba lepiej jak coś jest publiczne. Może ktoś coś poczyta w przyszłości.
Pytanie. W mojej aplikacji jest jedno pole tekstowe (edytor - edycja, wiele linii) oraz dwa przyciski. Może się pojawić dodatkowe pole tekstowe (filtr lub szukaj) Zależy mi na tym, aby klawiatura ekranowa systemu Android nie pojawiała się bądź znikała jak klikam pomiędzy polami lub w przyciski (menu), które oczywiście nie maja wpływają na zmianę tekstu w polu tekstowym (choć niektóre mają z rozwijanego menu). Czytam w dokumentacji o 'keyboard_mode=manage' i zakładam, że ja wtedy otwieram i zamykam klawiaturę. Do czego to podłączyć. Gdzieś było, że do pola tekstowego. Każdego? A przyciski też to powinny mieć? Te ekranowe przyciski, które jedne powinny, a inne nie powinny zamykać klawiatury. Jak to rozwiązać?
A jeszcze jak symulować klawiaturę pod Linuksem?

Pozdrawiam
Radosław Głębicki

1

Po pierwsze, żeby zamiast korzystać z prawdziwej klawiatury przed biurkiem i klikać na przyciski jak na mobilkach, ustawiamy konfigurację

# to musi być u samej góry przed innymi importami

from kivy.config import Config
Config.set('kivy', 'keyboard_mode', 'dock')

Po drugie, żeby samemu decydować kiedy te klawiatury wirtualne mają się pojawiać i znikać faktycznie modyfikujemy property keyboard_mode Text Inputów na manage. Jako że nie chcemy, żeby klawiatura wirtualna nam znikała, ustawiamy jako manage na wszystkich polach tekstowych, od teraz można je otwierać metodą show_keyboard() i zamykać metodą hide_keyboard():

layout = BoxLayout(orientation='vertical')
text_input_1 = TextInput(keyboard_mode='managed')
text_input_2 = TextInput(keyboard_mode='managed')
empty_space = Widget()
button_1 = Button(text="Button 1")
button_2 = Button(text="Button 2")

layout.add_widget(text_input_1)
layout.add_widget(text_input_2)
layout.add_widget(empty_space)
layout.add_widget(button_1)
layout.add_widget(button_2)

Teraz trzeba ogarnąć jak te klawiatury pokazać tak, by nie znikały przy naciskaniu na przyciski inne widgety. Do kontroli klikania używany jest callback dla zdarzenia on_touch_down. Wewnątrz możemy sprawdzić, czy kliknęliśmy faktycznie w widget, czy poza nim sprawdzając self.collide_point(*touch.pos). A zatem:

def on_touch_down_callback(instance, touch):
    if not instance.collide_point(*touch.pos):
        # kliknieto poza - nic nie rób
        return

    # zwolnij poprzednie klawiatury
    text_input_1.hide_keyboard()
    text_input_2.hide_keyboard()
    # natychmiast wyświetl nową dla wybranego pola tekstowego
    instance.show_keyboard()

text_input_1.bind(on_touch_down=on_touch_down_callback)
text_input_2.bind(on_touch_down=on_touch_down_callback)

Jeżeli kliknęliśmy poza polem tekstowym, nic nie robimy. W przeciwnym razie zwalniamy poprzednie klawiatury (inaczej klikanie w klawisze będzie nam wpisywało tekst do wszystkich pól tekstowych w jakie kliknęliśmy), po czym pokazujemy nową klawiaturę.

Jeszcze dla zabawy zamontujmy aby drugi przycisk (ale nie pierwszy) nam te klawiatury gasił:

def release_all_keyboards_callback(*args):
    text_input_1.hide_keyboard()
    text_input_2.hide_keyboard() 
button_2.bind(on_press=release_all_keyboards_callback)

Trochę to takie na kolanie pisane, że z palca wypisuje wszystkie widgety zamiast jak człowiek jakoś poiterować po potomkach layoutu, sprawdzając, który z nich to TextInput i ma akurat wyświetloną klawiaturę, ale niech tam będzie.

Razem do kupy:

from kivy.config import Config
Config.set('kivy', 'keyboard_mode', 'dock')

from kivy.core.window import Window
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.uix.widget import Widget
from kivy.clock import Clock
from kivy.base import runTouchApp


layout = BoxLayout(orientation='vertical')
text_input_1 = TextInput(keyboard_mode='managed')
text_input_2 = TextInput(keyboard_mode='managed')
empty_space = Widget()
button_1 = Button(text="Button 1")
button_2 = Button(text="Button 2")

layout.add_widget(text_input_1)
layout.add_widget(text_input_2)
layout.add_widget(empty_space)
layout.add_widget(button_1)
layout.add_widget(button_2)

def on_touch_down_callback(instance, touch):
    if not instance.collide_point(*touch.pos):
        # clicked outside - do not close anything
        return

    # zwolnij poprzednie klawiatury
    text_input_1.hide_keyboard()
    text_input_2.hide_keyboard()
    # natychmiast wyświetl nową dla wybranego pola tekstowego
    instance.show_keyboard()

text_input_1.bind(on_touch_down=on_touch_down_callback)
text_input_2.bind(on_touch_down=on_touch_down_callback)


def release_all_keyboards_callback(*args):
    text_input_1.hide_keyboard()
    text_input_2.hide_keyboard() 
button_2.bind(on_press=release_all_keyboards_callback)

runTouchApp(layout)

Jakbyśmy chcieli, abyśmy klawiatura była otwarta od początku to można by to np. zrobić w Clock.schedule_once(set_keyboard_for_text_input_1, 0).

0

Wyciągam ten temat bo może źle opisałem mój problem. Zależy mi na klawiaturze systemowej w Androidzie, a nie vkeyboard od Kivy. Może źle się wyraziłem. Jak było. Klikam w pola tekstowe pod Androidem, a klawiatura znika i się pojawia. Zależy mi na tym, aby była stale otwarta, a gdy ja zdecyduję to wtedy się ukrywa. Np otwiera się jakiś "Dialog". Teraz po kompilacji mam dwie klawiatury: systemowa Androida i vkeyboard od kivy. Po przeczytaniu powyższych tekstów zrozumiałem, błędnie najwyraźniej, że stosując te rozwiązania uzyskam symulację w Linuksie pojawiania się klawiatury "Androidowej", a w Androidzie będzie tylko Androidowa.
Jak kontrolować klawiaturę systemu Android?

Pozdrawiam
Radek Głębicki

1 użytkowników online, w tym zalogowanych: 0, gości: 1