Open dlee opened 5 years ago
Same problem for me. When using resizeOnFullScreen=true the view is pushed up when keyboard is show, but my bottom tab bar is hidden beneath the Android OS navigation bar (back, home and overview buttons). If using resizeOnFullScreen=false, the tab bar is correctly place above the navigation bar, but the view is not pushed up when keyboard is showing.
Ionic info:
Ionic:
ionic (Ionic CLI) : 4.10.3 (/usr/local/lib/node_modules/ionic)
Ionic Framework : ionic-angular 3.9.2
@ionic/app-scripts : 3.2.4
Cordova:
cordova (Cordova CLI) : 9.0.0 (cordova-lib@9.0.1)
Cordova Platforms : android 6.4.0, browser 5.0.4, ios 5.0.1
Cordova Plugins : cordova-plugin-ionic-keyboard 2.2.0, cordova-plugin-ionic-webview 3.1.2, (and 16 other plugins)
System:
Android SDK Tools : 26.1.1 (/Users/user/Library/Android/sdk)
ios-sim : 8.0.2
NodeJS : v10.15.3 (/usr/local/bin/node)
npm : 6.11.3
OS : macOS
Xcode : Xcode 11.1 Build version 11A1027
Same here. It would be great if this could be fixed.
Is there a way to modify "resizeOnFullScreen" while running the app? I need this feature only in one place and there's no bottom tab bar.
Having the same issue. Anyone has a workaround? I am also looking for a way to change "resizeOnFullScreen" in app.
same issue i face
Any workaround for this, i'm facing the same issue here
Also getting this issue now, and setting this to true fixes the keyboard overlapping input fields for me on Android. Would be great if there was a workaround for this.
I made the following changes to CDVIonicKeyboard.java as a fix, it seems to work on my end (Oppo Reno Z with software navbar and Samsung Galaxy S7 with hardware navbar) but I don't know if it works for all cases/devices.
I used the solution here to obtain the navigation bar's height: https://stackoverflow.com/a/50775459/12117100
You might want to change the ViewCompat.setOnApplyWindowInsetsListener to rootView.setOnApplyWindowInsetsListener if your API level supports it.
Please test it out and see if it works (added lines are below the "Fix" comments):
public class CDVIonicKeyboard extends CordovaPlugin {
private OnGlobalLayoutListener list;
// ...
// Fix
private int navbarOffset = 0;
cordova.getThreadPool().execute(new Runnable() {
public void run() {
// ...
FrameLayout content = (FrameLayout) cordova.getActivity().findViewById(android.R.id.content);
rootView = content.getRootView();
// Fix
ViewCompat.setOnApplyWindowInsetsListener(rootView, (v, insets) -> {
navbarOffset = insets.getSystemWindowInsetBottom();
return insets.consumeSystemWindowInsets();
});
// ...
private void possiblyResizeChildOfContent() {
int usableHeightNow = computeUsableHeight();
if (usableHeightNow != usableHeightPrevious) {
// Fix: modified the next line
int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight() - navbarOffset;
int heightDifference = usableHeightSansKeyboard - usableHeightNow;
// ...
}
}
I know next to nothing about Android development so if there are any mistakes do help to correct them, thanks!
I made the following changes to CDVIonicKeyboard.java as a fix, it seems to work on my end (Oppo Reno Z with software navbar and Samsung Galaxy S7 with hardware navbar) but I don't know if it works for all cases/devices.
I used the solution here to obtain the navigation bar's height: https://stackoverflow.com/a/50775459/12117100
You might want to change the ViewCompat.setOnApplyWindowInsetsListener to View.setOnApplyWindowInsetsListener if your API level supports it.
Please test it out and see if it works (added lines are below the "Fix" comments):
public class CDVIonicKeyboard extends CordovaPlugin { private OnGlobalLayoutListener list; // ... // Fix private int navbarOffset = 0; cordova.getThreadPool().execute(new Runnable() { public void run() { // ... FrameLayout content = (FrameLayout) cordova.getActivity().findViewById(android.R.id.content); rootView = content.getRootView(); // Fix ViewCompat.setOnApplyWindowInsetsListener(rootView, (v, insets) -> { navbarOffset = insets.getSystemWindowInsetBottom(); return insets.consumeSystemWindowInsets(); }); // ... private void possiblyResizeChildOfContent() { int usableHeightNow = computeUsableHeight(); if (usableHeightNow != usableHeightPrevious) { // Fix: modified the next line int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight() - navbarOffset; int heightDifference = usableHeightSansKeyboard - usableHeightNow; // ... } }
I know next to nothing about Android development so if there are any mistakes do help to correct them, thanks!
hello,When i pack app ,log ViewCompat no exist and i change it to View, it also log error. I should change it to ?Thanks
Use rootView.setOnApplyWindowInsetsListener if you're not using ViewCompat, I'll edit my original message to make it clearer.
Follow the API here Android View reference
hello.I try use rootView pack app,however it still log error as follows,Thanks for your work !!!OnApplyWindowInsetsListener �ҵ�: View,(v,insets)[...](); }
Can you paste the entire error, the error you pasted seems to be cut off and has some odd characters
I made the following changes to CDVIonicKeyboard.java as a fix, it seems to work on my end (Oppo Reno Z with software navbar and Samsung Galaxy S7 with hardware navbar) but I don't know if it works for all cases/devices.
...
I know next to nothing about Android development so if there are any mistakes do help to correct them, thanks!
Thanks for this solution but it has one downside, it does not quite work in landscape orientation (leaves an ugly margin area where navbar used to be in portrait mode, and does not copy over the navbar background). At least on my OnePlus 3T with android 9.
Please see my fix that does not override the original onApplyWindowInsetsListener, gets the insets at init time and takes into account device orientation (android >21) to calculate the correct height.
Here is the complete CDVIonicKeyboard.java file, changes are marked with // FIX
. For some reason it won't properly format as either code or comment so apologies for the broken formatting.
Anyway, hope it helps someone.
package io.ionic.keyboard;
import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaInterface; import org.apache.cordova.CordovaPlugin; import org.apache.cordova.CordovaWebView; import org.apache.cordova.PluginResult; import org.apache.cordova.PluginResult.Status; import org.json.JSONArray; import org.json.JSONException;
import android.content.Context; import android.graphics.Rect; import android.util.DisplayMetrics; import android.view.View; import android.view.WindowInsets; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.inputmethod.InputMethodManager;
// import additionally required classes for calculating screen height import android.view.Display; import android.graphics.Point; import android.os.Build; import android.widget.FrameLayout;
public class CDVIonicKeyboard extends CordovaPlugin { private OnGlobalLayoutListener list; private View rootView; private View mChildOfContent; private int usableHeightPrevious; private FrameLayout.LayoutParams frameLayoutParams;
/// FIX ADDED private int navbarOffset = 0; /// public void initialize(CordovaInterface cordova, CordovaWebView webView) { super.initialize(cordova, webView); } public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException { if ("hide".equals(action)) { cordova.getThreadPool().execute(new Runnable() { public void run() { //http://stackoverflow.com/a/7696791/1091751 InputMethodManager inputManager = (InputMethodManager) cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); View v = cordova.getActivity().getCurrentFocus(); if (v == null) { callbackContext.error("No current focus"); } else { inputManager.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); callbackContext.success(); // Thread-safe. } } }); return true; } if ("show".equals(action)) { cordova.getThreadPool().execute(new Runnable() { public void run() { ((InputMethodManager) cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY); callbackContext.success(); // Thread-safe. } }); return true; } if ("init".equals(action)) { cordova.getThreadPool().execute(new Runnable() { public void run() { //calculate density-independent pixels (dp) //http://developer.android.com/guide/practices/screens_support.html DisplayMetrics dm = new DisplayMetrics(); cordova.getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); final float density = dm.density; //http://stackoverflow.com/a/4737265/1091751 detect if keyboard is showing FrameLayout content = (FrameLayout) cordova.getActivity().findViewById(android.R.id.content); rootView = content.getRootView(); /// FIX ADDED WindowInsets insets = rootView.getRootWindowInsets(); navbarOffset = insets.getSystemWindowInsetBottom(); /// list = new OnGlobalLayoutListener() { int previousHeightDiff = 0; @Override public void onGlobalLayout() { boolean resize = preferences.getBoolean("resizeOnFullScreen", false); if (resize) { possiblyResizeChildOfContent(); } Rect r = new Rect(); //r will be populated with the coordinates of your view that area still visible. rootView.getWindowVisibleDisplayFrame(r); PluginResult result; // cache properties for later use int rootViewHeight = rootView.getRootView().getHeight(); int resultBottom = r.bottom; // calculate screen height differently for android versions >= 21: Lollipop 5.x, Marshmallow 6.x //http://stackoverflow.com/a/29257533/3642890 beware of nexus 5 int screenHeight; if (Build.VERSION.SDK_INT >= 21) { Display display = cordova.getActivity().getWindowManager().getDefaultDisplay(); Point size = new Point(); display.getSize(size); screenHeight = size.y; } else { screenHeight = rootViewHeight; } int heightDiff = screenHeight - resultBottom; int pixelHeightDiff = (int)(heightDiff / density); if (pixelHeightDiff > 100 && pixelHeightDiff != previousHeightDiff) { // if more than 100 pixels, its probably a keyboard... String msg = "S" + Integer.toString(pixelHeightDiff); result = new PluginResult(PluginResult.Status.OK, msg); result.setKeepCallback(true); callbackContext.sendPluginResult(result); } else if ( pixelHeightDiff != previousHeightDiff && ( previousHeightDiff - pixelHeightDiff ) > 100 ){ String msg = "H"; result = new PluginResult(PluginResult.Status.OK, msg); result.setKeepCallback(true); callbackContext.sendPluginResult(result); } previousHeightDiff = pixelHeightDiff; } /// FIX ADDED private boolean isPortrait() { if (Build.VERSION.SDK_INT >= 21) { Display display = cordova.getActivity().getWindowManager().getDefaultDisplay(); int rotation = display.getRotation(); if (rotation == 0) return true; else return false; } return true; } /// private void possiblyResizeChildOfContent() { int usableHeightNow = computeUsableHeight(); if (usableHeightNow != usableHeightPrevious) { /// FIX MODIFIED int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight(); if (this.isPortrait()) usableHeightSansKeyboard = usableHeightSansKeyboard - navbarOffset; /// int heightDifference = usableHeightSansKeyboard - usableHeightNow; if (heightDifference > (usableHeightSansKeyboard/4)) { frameLayoutParams.height = usableHeightSansKeyboard - heightDifference; } else { frameLayoutParams.height = usableHeightSansKeyboard; } mChildOfContent.requestLayout(); usableHeightPrevious = usableHeightNow; } } private int computeUsableHeight() { Rect r = new Rect(); mChildOfContent.getWindowVisibleDisplayFrame(r); return (r.bottom - r.top); } }; mChildOfContent = content.getChildAt(0); rootView.getViewTreeObserver().addOnGlobalLayoutListener(list); frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams(); PluginResult dataResult = new PluginResult(PluginResult.Status.OK); dataResult.setKeepCallback(true); callbackContext.sendPluginResult(dataResult); } }); return true; } return false; // Returning false results in a "MethodNotFound" error. } @Override public void onDestroy() { rootView.getViewTreeObserver().removeOnGlobalLayoutListener(list); }
}
I have made this changes and it works well in my app (both in portrait and landscape mode):
// ...
private void possiblyResizeChildOfContent() {
int usableHeightNow = computeUsableHeight();
if (usableHeightNow != usableHeightPrevious) {
// COMMENT THIS LINES
// int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
// int heightDifference = usableHeightSansKeyboard - usableHeightNow;
// if (heightDifference > (usableHeightSansKeyboard/4)) {
// frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
// } else {
// frameLayoutParams.height = usableHeightSansKeyboard;
// }
frameLayoutParams.height = usableHeightNow; // ADD THIS LINE
mChildOfContent.requestLayout();
usableHeightPrevious = usableHeightNow;
}
}
// ...
Tested in OnePlus 6 (Android 10) and Huawei P Smart (Android 8.0.0)
I'm not an Android developer and I don't understand why the commented lines were added.
There is an Android bug that prevents the keyboard from resizing the WebView when the app is in full screen (i.e. if StatusBar plugin is used to hide the StatusBar). This setting, if set to true, add a workaround that resizes the WebView even when the app is in full screen.
It's strange that this flag is supposed to fix an Android bug but it itself introduced another bug which is way weird. 😃
By the way, we can also reproduce this in our fresh Ionic 5 app. Basically, when keyboard hides, the content in ion-footer
got hidden behind the navigation bar.
If Ionic team wants a demo app to reproduce, we can provide that.
same problem this solution: rootView.setOnApplyWindowInsetsListener((v, insets) -> { navbarOffset = insets.getSystemWindowInsetBottom(); return insets.consumeSystemWindowInsets(); });
btw, here's what I've been using to work around this: https://github.com/SamDV-ich/cordova-plugin-ionic-keyboard-fixed
Hopefully the approach taken in that fork can be of help resolving this issue.
Hello! Did as ldittel
wrote but unfortunately a strip appears on many devices
got this at android device, ios works fine.
I still have this same issue, can someone please assist me as I have tried everything but no luck, here are some info:
Ionic:
Ionic CLI : 6.11.9 (/usr/local/lib/node_modules/@ionic/cli) Ionic Framework : @ionic/angular 5.3.3 @angular-devkit/build-angular : 0.901.12 @angular-devkit/schematics : 9.1.12 @angular/cli : 9.1.12 @ionic/angular-toolkit : 2.3.3
Cordova:
Cordova CLI : 10.0.0 Cordova Platforms : android 9.0.0, ios 5.1.1 Cordova Plugins : cordova-plugin-ionic-keyboard 2.2.0, cordova-plugin-ionic-webview 5.0.0, (and 19 other plugins)
Utility:
cordova-res : 0.15.1 native-run : 1.1.0
System:
Android SDK Tools : 26.1.1 (/Users/****/Library/Android/sdk) ios-deploy : 1.11.1 ios-sim : 8.0.2 NodeJS : v12.18.3 (/usr/local/bin/node) npm : 6.14.6 OS : macOS Catalina Xcode : Xcode 12.0.1 Build version 12A7300
I still face the same problem and use ionic 5
I call this function in app.component to detect the keyboard show or hide and if show will add scrollIntoView so I don't need to add resizeOnFullScreen in config.xml that will have problem with statusbar plugin coz I need to use statusbar overlay function
subscribeKeyboard() {
this.keyboardSubscribeHide = this.keyboard.onKeyboardDidHide().subscribe((res: any) => {
console.log('onKeyboardDidHide', res)
this.zone.run(() => {
this.keyboard_visibility = false;
})
})
this.keyboardSubscribeShow = this.keyboard.onKeyboardDidShow().subscribe((res: any) => {
console.log('onKeyboardDidShow', res)
this.zone.run(() => {
this.keyboard_visibility = true;
if (!this.ios) {
document.activeElement.scrollIntoView(true);
}
})
})
}
this can do the trick and the keyboard_visibility variable here to show or hide my ion-footer if keyboard show/hide
Note: this.ios is the indicator if the platform is ios or not, if not ios only add document.activeElement.scrollIntoView(true);
When using
resizeOnFullScreen
on Android, it makes the app extend below the Navigation Bar./cc @jcesarmobile