ionic-team / cordova-plugin-ionic-keyboard

Keyboard Plugin for Cordova
Other
191 stars 177 forks source link

Correct Android Screen Size (resizeOnFullScreen true - not full screen) #166

Open itbeyond opened 2 years ago

itbeyond commented 2 years ago

If you set the preference for resizeOnFullScreen and you do not have your app running (or you allow user settings) in either fullscreen mode (via StatusBar) or Immersive fullscreen mode (via cordova-plugin-fullscreen) the height is calculated wrong and some content between 8 and 40 pixels dependant on device will be off the bottom of the screen. This update looks for isFullScreen as per #156, which was close but we still need to subtract the r.top from the return value hence this PR which has been tested on many devices with and without statusbar and immersive mode.

Based on and fixes #156, #117, #132, #134

itbeyond commented 2 years ago

If anyone wants to use this PR you can use the fork I created from Master 2.2.0 which includes this PR. https://github.com/itbeyond/cordova-plugin-ionic-keyboard

pierresh commented 2 years ago

Hello,

Thanks a lot for your PR, nevertheless I needed to change it a bit to make it render perfectly (otherwise I still have the black bar).

Before

return isFullScreen() ? r.bottom - r.top : r.height();

After

return isFullScreen() ? r.bottom - r.top + 108 : r.height();

I have the option resizeOnFullScreen set to true in config.xml, and the status bar is overlay.

pierresh commented 1 year ago

For some Huawei devices, I need to change 108 to 50 to look nice... Do you have any idea on which criteria this value might depend between devices?

pierresh commented 1 year ago

Actually, I have a solution to this problem

Create a file named FixScreen.java and put it beside the file called MainActivity.java

Basically it should be in '/platforms/android/app/src/main/java/com/company/app/'

(com/company/app because I assume the app's id is com.company.app, please replace with your app's one, as well as everywhere in files below)

package com.company.app;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;

import java.lang.reflect.Method;

public class FixScreen {
    public static void assistActivity([View](http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+view) content) {
        new FixScreen(content);
    }
    private [View](http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+view) mChildOfContent;
    private int usableHeightPrevious;
    private ViewGroup.LayoutParams frameLayoutParams;
    private FixScreen([View](http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+view) content) {
        mChildOfContent = content;
        mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            public void onGlobalLayout() {
                possiblyResizeChildOfContent();
            }
        });
        frameLayoutParams = mChildOfContent.getLayoutParams();
    }
    private void possiblyResizeChildOfContent() {
        int usableHeightNow = computeUsableHeight();
        Log.d("usableHeightNow", "possiblyResizeChildOfContent() returned: " + usableHeightNow);
        if (usableHeightNow != usableHeightPrevious) {
            frameLayoutParams.height = usableHeightNow;
            mChildOfContent.requestLayout();
            usableHeightPrevious = usableHeightNow;
        }
    }

    private int computeUsableHeight() {
        Rect r = new Rect();
        mChildOfContent.getWindowVisibleDisplayFrame(r);
        return (r.bottom);
    }
    public static boolean checkDeviceHasNavigationBar([Context](http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+context) context) {
        boolean hasNavigationBar = false;
        Resources rs = context.getResources();
        int id = rs.getIdentifier("config_showNavigationBar", "bool", "android");
        if (id > 0) {
            hasNavigationBar = rs.getBoolean(id);
        }
        try {
            Class systemPropertiesClass = Class.forName("android.os.SystemProperties");
            [Method](http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+method) m = systemPropertiesClass.getMethod("get", [String](http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string).class);
            [String](http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string) navBarOverride = ([String](http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string)) m.invoke(systemPropertiesClass, "qemu.hw.mainkeys");
            if ("1".equals(navBarOverride)) {
                hasNavigationBar = false;
            } else if ("0".equals(navBarOverride)) {
                hasNavigationBar = true;
            }
        } catch ([Exception](http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+exception) e) {
        }
        return hasNavigationBar;
    }
}

Then in MainActivity.java, 3 changes: add import com.company.app.FixScreen; add fixScreenOverlap(); add the function private void fixScreenOverlap(){ ... }

package com.company.app;

import android.os.Bundle;

import org.apache.cordova.*;

import com.company.app.FixScreen;

public class MainActivity extends CordovaActivity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        // enable Cordova apps to be started in the background
        Bundle extras = getIntent().getExtras();
        if (extras != null && extras.getBoolean("cdvStartInBackground", false)) {
            moveTaskToBack(true);
        }

        // Set by <content src="index.html" /> in config.xml
        loadUrl(launchUrl);
        fixScreenOverlap();
    }

    private void fixScreenOverlap(){
        if (FixScreen.checkDeviceHasNavigationBar(this)) {
            FixScreen.assistActivity(findViewById(android.R.id.content));
        }
    }
}