Çağatay Kaya
Çağatay Kaya

Reputation: 437

How to resize view when touchscreen keyboard is visible on Android with Unity?

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 ?

Upvotes: 9

Views: 12940

Answers (3)

Junior
Junior

Reputation: 91

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
    }

Upvotes: 0

Vitaliy Polchuk
Vitaliy Polchuk

Reputation: 1898

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
    }

}

Upvotes: 3

Jerry Switalski
Jerry Switalski

Reputation: 2720

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");
            }
        }
    }

Upvotes: 8

Related Questions