9

In Unity I can't control the touchscreen keyboard. TouchScreenKeyboard class has only one parameters for Android.

if(TouchScreenKeyboard.visible)
{ float keyboardHeight = TouchScreenKeyboard.area.height;
  // will resize the view here! But this return zero!
}

Is there any other way to know the height of the keyboard on Android ?

Çağatay Kaya
  • 417
  • 1
  • 6
  • 19

3 Answers3

8

This should do the trick (found here):

    public int GetKeyboardSize()
    {
        using(AndroidJavaClass UnityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        {
            AndroidJavaObject View = UnityClass.GetStatic<AndroidJavaObject>("currentActivity").Get<AndroidJavaObject>("mUnityPlayer").Call<AndroidJavaObject>("getView");

            using(AndroidJavaObject Rct = new AndroidJavaObject("android.graphics.Rect"))
            {
                View.Call("getWindowVisibleDisplayFrame", Rct);

                return Screen.height - Rct.Call<int>("height");
            }
        }
    }
Jerry Switalski
  • 2,690
  • 1
  • 18
  • 36
3

It was long ago, but just in case anybody is struggling with it again, I managed to find a solution for a panel with an InputField using this MonoBehaviour class. I attached it to the InputField and linked the panel which should be resized.

public class InputFieldForScreenKeyboardPanelAdjuster : MonoBehaviour {

    // Assign panel here in order to adjust its height when TouchScreenKeyboard is shown
    public GameObject panel;

    private InputField inputField;
    private RectTransform panelRectTrans;
    private Vector2 panelOffsetMinOriginal;
    private float panelHeightOriginal;
    private float currentKeyboardHeightRatio;

    public void Start() {
        inputField = transform.GetComponent<InputField>();
        panelRectTrans = panel.GetComponent<RectTransform>();
        panelOffsetMinOriginal = panelRectTrans.offsetMin;
        panelHeightOriginal = panelRectTrans.rect.height;
    }

    public void LateUpdate () {
        if (inputField.isFocused) {
            float newKeyboardHeightRatio = GetKeyboardHeightRatio();
            if (currentKeyboardHeightRatio != newKeyboardHeightRatio) {
                Debug.Log("InputFieldForScreenKeyboardPanelAdjuster: Adjust to keyboard height ratio: " + newKeyboardHeightRatio);
                currentKeyboardHeightRatio = newKeyboardHeightRatio;
                panelRectTrans.offsetMin = new Vector2(panelOffsetMinOriginal.x, panelHeightOriginal * currentKeyboardHeightRatio);
            }
        } else if (currentKeyboardHeightRatio != 0f) {
            if (panelRectTrans.offsetMin != panelOffsetMinOriginal) {
                SmartCoroutine.DelayedExecute(this, () => {
                    Debug.Log("InputFieldForScreenKeyboardPanelAdjuster: Revert to original");
                    panelRectTrans.offsetMin = panelOffsetMinOriginal;
                }, 0.5f);
            }
            currentKeyboardHeightRatio = 0f;
        }
    }

    private float GetKeyboardHeightRatio() {
        if (Application.isEditor) {
            return 0.4f; // fake TouchScreenKeyboard height ratio for debug in editor        
        }

#if UNITY_ANDROID        
        using (AndroidJavaClass UnityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) {
            AndroidJavaObject View = UnityClass.GetStatic<AndroidJavaObject>("currentActivity").Get<AndroidJavaObject>("mUnityPlayer").Call<AndroidJavaObject>("getView");
            using (AndroidJavaObject rect = new AndroidJavaObject("android.graphics.Rect")) {
                View.Call("getWindowVisibleDisplayFrame", rect);
                return (float)(Screen.height - rect.Call<int>("height")) / Screen.height;
            }
        }
#else
        return (float)TouchScreenKeyboard.area.height / Screen.height;
#endif
    }

}
Vitaliy Polchuk
  • 1,878
  • 19
  • 12
  • worked great, thank you. Just replace that "SmartCoroutine.DelayedExecute" as it obviously some of your internal library – Martin Asenov Sep 30 '17 at 22:49
  • For the SmartCoroutine, which @Vitaliy is using to delay the Reset can be incorporated by moving the contents into another method, and then invoking it after the required delay } else if (ratio != 0f) { if (panelRectTrans.offsetMin != panelOffsetMinOriginal) Invoke("DelayedReset", 0.5f); ratio = 0f; } void DelayedReset() { Debug.Log("InputFieldForScreenKeyboardPanelAdjuster: Revert to original"); panelRectTrans.offsetMin = panelOffsetMinOriginal; } – olonge Oct 19 '19 at 14:05
  • Need a fix for iPhone 11 as this solution fails to move the inputfield container up the entire amount. The keyboard covers about half of inputfield. – Valerie Nov 03 '19 at 23:37
  • I fixed this for iPhone 11 by using Screen.safeArea.height instead. E.g. return (float)TouchScreenKeyboard.area.height / Screen.safeArea.height; – Valerie Nov 04 '19 at 16:22
  • A little old now, but found this so helpful I wanted to share our update that incorporates both olonge and Valerie's suggestions as well some cleanup and support for limiting resets if additional uses are found on the same target container (i.e. panel). Also support for using anchorPosition3D which I found works better if the parent container is positioned in the center of the view. https://github.com/playvue/UnityHelpers/blob/master/Scripts/InputFieldForScreenKeyboard.cs – kfblake Mar 27 '21 at 20:37
0

I got this to work relative to the canvas size, here is the code... All you need is to call it with the canvas RectTransform reference.

    public static int GetRelativeKeyboardHeight(RectTransform rectTransform, bool includeInput)
    {
        int keyboardHeight = GetKeyboardHeight(includeInput);
        float screenToRectRatio = Screen.height / rectTransform.rect.height;
        float keyboardHeightRelativeToRect = keyboardHeight / screenToRectRatio;

        return (int) keyboardHeightRelativeToRect;
    }

    private static int GetKeyboardHeight(bool includeInput)
    {
#if UNITY_EDITOR
        return 0;
#elif UNITY_ANDROID
        using (AndroidJavaClass unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        {
            AndroidJavaObject unityPlayer = unityClass.GetStatic<AndroidJavaObject>("currentActivity").Get<AndroidJavaObject>("mUnityPlayer");
            AndroidJavaObject view = unityPlayer.Call<AndroidJavaObject>("getView");
            AndroidJavaObject dialog = unityPlayer.Get<AndroidJavaObject>("mSoftInputDialog");
            if (view == null || dialog == null)
                return 0;
            var decorHeight = 0;
            if (includeInput)
            {
                AndroidJavaObject decorView = dialog.Call<AndroidJavaObject>("getWindow").Call<AndroidJavaObject>("getDecorView");
                if (decorView != null)
                    decorHeight = decorView.Call<int>("getHeight");
            }
            using (AndroidJavaObject rect = new AndroidJavaObject("android.graphics.Rect"))
            {
                view.Call("getWindowVisibleDisplayFrame", rect);
                return Screen.height - rect.Call<int>("height") + decorHeight;
            }
        }
#elif UNITY_IOS
        return (int)TouchScreenKeyboard.area.height;
#endif
    }
Junior
  • 91
  • 3