Forum Archive

Change Keyboard Layout/Language

brumm

Hello all, is it possible to change the keyboard language? I like to program a vocabulary trainer and like to switch automatically between a Cyrillic and a Latin keyboard layout, while entering the input text field.

cvp

@brumm if you want to say "as if I had tapped the keyboard globe key" automatically, I don't think it is possible, but, of course, I could be wrong.

And, what is automatically ?

brumm

@cvp yes, you‘ve got me right. I just do not want to press the globe (too lazy 😊).

stephen

@cvp automatically ⇄ automatiquement

cvp

@brumm said:

lazy

That, I can understand 😀

But, how/when would the program change ?

stephen

@brumm i dont belive what ur asking would be posible with apple. but you shouod be able to write an autocorrect script that converts your input to a deired text value? this is assuming your using pythonista's pykeys

cvp

@brumm It would also be possible to use InputView as I did here

cvp

@stephen said:

automatically ⇄ automatiquement

I know but I don't see how, when you are typing in Latin letters, you could automatically switch to other keys, which is the criteria to switch ?

brumm

@cvp said:

criteria

The criteria would be the selection of the text field (language l or c). E.g. first the Latin word and then in the next text field the Cyrillic word. Something with _begin_editing ...

brumm

Btw. thank you and don‘t worry i can live without it. i just wanna know if it‘s possible or not.

stephen

@brumm @cvp

after searching around.. even using objC thesebare your options to programatically change keyboard type on UITextfield..

typedef enum {
    UIKeyboardTypeDefault,                // Default type for the current input method.
    UIKeyboardTypeASCIICapable,           // Displays a keyboard which can enter ASCII characters, non-ASCII keyboards remain active
    UIKeyboardTypeNumbersAndPunctuation,  // Numbers and assorted punctuation.
    UIKeyboardTypeURL,                    // A type optimized for URL entry (shows . / .com prominently).
    UIKeyboardTypeNumberPad,              // A number pad (0-9). Suitable for PIN entry.
    UIKeyboardTypePhonePad,               // A phone pad (1-9, *, 0, #, with letters under the numbers).
    UIKeyboardTypeNamePhonePad,           // A type optimized for entering a person's name or phone number.
    UIKeyboardTypeEmailAddress,           // A type optimized for multiple email address entry (shows space @ . prominently).
    UIKeyboardTypeDecimalPad,             // A number pad including a decimal point
    UIKeyboardTypeTwitter,                // Optimized for entering Twitter messages (shows # and @)
    UIKeyboardTypeWebSearch,              // Optimized for URL and search term entry (shows space and .)

    UIKeyboardTypeAlphabet = UIKeyboardTypeASCIICapable, // Deprecated

} UIKeyboardType;

sorry buddy 😕

brumm

Again thank you.

cvp

@brumm Quick and very very dirty script, far from finished, but only to show how it could be possible. Automatic standard keyboard for 1st TextField, and InputView for 2nd one.
Really automatic, nothing to do, ok for lazy guys 🙄 like us
Sorry for my Cyrillic 😂 (characters taken from Russian keyboard)
Please try it and tell me...


import ui
from objc_util import *

import ui
from objc_util import *

def SetTextFieldPad(tf,pad=None,clearButtonMode=False,undo_redo_pasteBarButtons=False,textfield_did_change=None):
    if not pad:

        pad = [
        {'key':'й'},{'key':'ц'},{'key':'у'},{'key':'к'},{'key':'е'},{'key':'н'},{'key':'г'},{'key':'ш'},{'key':'щ'},{'key':'з'},{'key':'х'},        {'key':'back space','icon':'typb:Delete'},
        {'key':'new row'},
        {'key':'Ф'},{'key':'ы'},{'key':'в'},{'key':'а'},{'key':'п'},{'key':'р'},{'key':'о'},{'key':'л'},{'key':'д'},{'key':'ж'},{'key':'э'},            {'key':'done','icon':'emj:Checkmark_3'},
        {'key':'new row'},
        {'key':'Я'},{'key':'ч'},{'key':'с'},{'key':'м'},{'key':'и'},{'key':'т'},{'key':'ь'},{'key':'б'},{'key':'ю'},{'key':'ъ'},
        {'key':'new row'}]

    tfo = ObjCInstance(tf).textField() # UITextField is subview of ui.TextField

    def key_pressed(sender):

            if sender.title == 'test':
                return
            tfb = sender.TextField
            tfobjc = ObjCInstance(tfb).textField()
            cursor = tfobjc.offsetFromPosition_toPosition_(tfobjc.beginningOfDocument(), tfobjc.selectedTextRange().start())
            if sender.name == 'delete':
                if cursor <= (len(tfb.text)-1):
                    tfb.text = tfb.text[:cursor] + tfb.text[cursor+1:]
            elif sender.name == 'back space':
                if cursor > 0:
                    #if tfb.text != '':
                    tfb.text = tfb.text[:cursor-1] + tfb.text[cursor:]
                    cursor = cursor - 1
            elif sender.name == 'done':
                tfb.end_editing()
                return
            else:
                tfb.text = tfb.text[:cursor] + sender.title + tfb.text[cursor:]
                cursor = cursor + 1

            if textfield_did_change:
                textfield_did_change(tfb)

            # set cursor
            cursor_position = tfobjc.positionFromPosition_offset_(tfobjc.beginningOfDocument(), cursor)
            tfobjc.selectedTextRange = tfobjc.textRangeFromPosition_toPosition_(cursor_position, cursor_position)

    # design your keyboard
    # pad = [{key='functionnality',title='title',icon='icon'},...]
    #       new row => new row
    #       nul => no key
    #       back space => left delete
    #       delete => right delete
    #       done => discard the keyboard
    #   other => append the character

    # count the maximum width of rows
    row_max_length = 0
    row_length = 0
    for pad_elem in pad:
        if pad_elem['key'] == 'new row':
            if row_length > row_max_length:
                row_max_length = row_length
            row_length = 0      
        else:
            row_length = row_length + 1
    if row_length > row_max_length:
        row_max_length = row_length

    v = ui.View()
    db = 50
    dd = 10
    x0 = (ui.get_screen_size()[0]-row_max_length*db-(row_max_length-1)*dd)/2
    x = x0
    y = dd

    for pad_elem in pad:
        if pad_elem['key'] == 'new row':
            y = y + db + dd
            x = x0
        elif pad_elem['key'] == 'nul':          
            x = x + db + dd
        else:           
            b = ui.Button()
            b.name = pad_elem['key']
            b.background_color = 'white'    # or any other color
            b.tint_color = 'black'
            b.corner_radius = 10 
            b.title = ''
            b.font = ('<system>',32)
            if 'icon' in pad_elem:
                b.image = ui.Image.named(pad_elem['icon']).with_rendering_mode(ui.RENDERING_MODE_ORIGINAL)
            elif 'title' not in pad_elem:
                b.title = pad_elem['key']
            if 'title' in pad_elem:
                b.title = pad_elem['title']

            b.frame = (x,y,db,db)
            b.TextField = tf # store tf as key attribute  needed when pressed
            b.action = pad_elem.get('action', key_pressed)
            v.add_subview(b)
            x = x + db + dd
    y = y + db + dd

    v.width = ui.get_screen_size()[0]
    v.height = y

    # view of keyboard
    retain_global(v) # see https://forum.omz-software.com/topic/4653/button-action-not-called-when-view-is-added-to-native-view
    tfo.setInputView_(ObjCInstance(v))

    # color of cursor and selected text
    tfo.tintColor = UIColor.redColor().colorWithAlphaComponent(0.5)

    # clear button
    tfo.clearButtonMode = clearButtonMode

    # comment both lines to keep undo/redo/paste BarButtons above keyboard
    if not undo_redo_pasteBarButtons:
        tfo.inputAssistantItem().setLeadingBarButtonGroups(None)
        tfo.inputAssistantItem().setTrailingBarButtonGroups(None)

class MyView(ui.View):
    def __init__(self):
        self.frame = (0,0,500,500)
        self.background_color = 'white'

        tfl = ui.TextField()
        tfl.frame = (10,10,480,32)
        tfl.delegate = self
        self.add_subview(tfl)

        tfc = ui.TextField()
        tfc.frame = (10,50,480,32)
        tfc.delegate = self
        self.add_subview(tfc)
        SetTextFieldPad(tfc)

v = MyView()
v.present('sheet')

cvp

Update

        tfl = ui.TextField()
        tfl.frame = (10,10,480,32)
        tfl.placeholder = 'latin'
        tfl.delegate = self
        self.add_subview(tfl)

        tfc = ui.TextField()
        tfc.frame = (10,50,480,32)
        tfc.placeholder = 'cyrillic'
        tfc.delegate = self
        self.add_subview(tfc)
        SetTextFieldPad(tfc) 

brumm

Looks great, спасибо.

cvp

@brumm Never mind. Did you try it? Is something like that (I know that it is not exactly that) you want?

brumm

I thought there is an easy solution, but that is also great, because when you fill the db you don‘t need to change it all the time. Now I‘m missing some keys like space, shift, minus, exclamation mark. Where i can find the right syntax?

cvp

@brumm I'm sure that my script, not initially written for that, can be made easier...
I'll do it if you let me some time

brumm

@cvp That is very kind of you, no hurry. I‘m not started coding. First I will design the Views and database structure.

cvp

@brumm ouf 😅

cvp

@brumm Could you try this new (far from perfect) version and tell me if useful Double_keyboard.py

brumm

Wow! Thank you so much. Looks awesome.
@cvp Btw. would it be okay for you, if I upload my VocabularyTrainer with your code to Github? Or can I put a link to your gist in my future repository?

cvp

@brumm My code is yours, do what you want. 😀

cvp

@brumm Right alignment done in new version of Double_keyboard.py

becomes

cvp

@brumm my script defines as 2nd keyboard a Cyrillic one because my standard keyboard is Latin, but, of course, you could easily do the inverse...

brumm

MyVocabTrainer

Far away from being finished. Ugly code and only for fixed iPad 768x1024 resolution.