Different keyboard flavours in iOS


#1

Hello,

I was wondering what would be the best way in JUCE to assign a specific type to the iOS keyboard.

For instance, when a TextEditor pertaining a numeric value gains the focus, the keyboard should be setup for numeric input.

I believe I should set the 'keyboardType' property of the UITextField, but where? Could I do this through Component::getPeer()?

Is this something that you plan to add, Jules?

Thanks


#2

It'd probably be best added as a new virtual method on the TextInputTarget class, but I've no time to look at it right now..


#3

Hello Jules,

Here is my solution, if you believe it is acceptable, as I hope, could you add it to Juce? I have tested it in iOS, but I've never touched Android, so I can only hope it is suitable for that OS.

1. Declare a VirtualKeyboardType enum inside TextInputTarget to provide a list of types as a reasonable intersection between those defined in iOS and those defined in Android.

2. Declare a VirtualKeyboardType member variable and set/get methods inside TextInputTarget.

class JUCE_API  TextInputTarget
{
public:
    //==============================================================================

enum VirtualKeyboardType
    {
    // iOS: UIKeyboardTypeDefault, Android: text
    virtKbdTypeDefault,

    // iOS: UIKeyboardTypeNumbersAndPunctuation, Android: number|numberSigned|numberDecimal
    virtKbdTypeNumbers,

    // iOS: UIKeyboardTypeURL, Android: textUri
    virtKbdTypeURL,

    // iOS: UIKeyboardTypePhonePad, Android: phone
    virtKbdTypePhonePad,

    // iOS: UIKeyboardTypeEmailAddress, Android: textEmailAddress
    virtKbdTypeEmailAddress
    };

    /** */
    TextInputTarget()
        : virtualKeyboardType(virtKbdTypeDefault) 
        {}

    /** Destructor. */
    virtual ~TextInputTarget() {}

    /** Returns true if this input target is currently accepting input.
        For example, a text editor might return false if it's in read-only mode.
    */
    virtual bool isTextInputActive() const = 0;

    /** Returns the extents of the selected text region, or an empty range if
        nothing is selected,
    */
    virtual Range<int> getHighlightedRegion() const = 0;

    /** Sets the currently-selected text region. */
    virtual void setHighlightedRegion (const Range<int>& newRange) = 0;

    /** Sets a number of temporarily underlined sections.
        This is needed by MS Windows input method UI.
    */
    virtual void setTemporaryUnderlining (const Array <Range<int> >& underlinedRegions) = 0;

    /** Returns a specified sub-section of the text. */
    virtual String getTextInRange (const Range<int>& range) const = 0;

    /** Inserts some text, overwriting the selected text region, if there is one. */
    virtual void insertTextAtCaret (const String& textToInsert) = 0;

    /** Returns the position of the caret, relative to the component's origin. */
    virtual Rectangle<int> getCaretRectangle() = 0;

    /** Sets the current virtual keyboard type. */
    virtual void setVirtualKeyboardType (VirtualKeyboardType type) { virtualKeyboardType = type; }

    /** Gets the current virtual keyboard type. */
    virtual VirtualKeyboardType getVirtualKeyboardType () { return virtualKeyboardType; }

private:
    VirtualKeyboardType    virtualKeyboardType;
};

3. Modify methods derived from ComponentPeer::textInputRequired() as needed, so that they can set the desired type of keyboard in the specific OS.

void UIViewComponentPeer::textInputRequired (const Point<int>&)
{
if (TextInputTarget* const target = findCurrentTextInputTarget())
    {
    switch(target->getVirtualKeyboardType())
        {
        case TextInputTarget::virtKbdTypeDefault:
            view->hiddenTextView.keyboardType = UIKeyboardTypeDefault;
            break;

        case TextInputTarget::virtKbdTypeNumbers:
            view->hiddenTextView.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
            break;

        case TextInputTarget::virtKbdTypeURL:
            view->hiddenTextView.keyboardType = UIKeyboardTypeURL;
            break;

        case TextInputTarget::virtKbdTypePhonePad:
            view->hiddenTextView.keyboardType = UIKeyboardTypePhonePad;
            break;

        case TextInputTarget::virtKbdTypeEmailAddress:
            view->hiddenTextView.keyboardType = UIKeyboardTypeEmailAddress;
            break;
        }
    }
}

OK, that's all, thank you for your attention!


#4

Thanks! I'll have a go at rolling something like this in there asap!


#5

Thank you, Jules!