Ionic 3 keyboard hides input field when in landscape mode - android

I have an Ionic app that must be in landscape mode. When a user tap on an input field to type, the keyboard comes up, so the user can only see the header, footer and the keyboard, thus the user can't see what he is typing. I saw on native apps when I do the same thing, the keyboard comes up with a separate textbox, which will be perfect for my Ionic app. How can I do it in Ionic? Here are some screenshots:
The screen in landscape mode before typing
The screen when typing starts
The screen on native apps when typing

Try to use scrollAssist: true for IonicModule.
IonicModule.forRoot(MyApp, {
scrollAssist: true
}),

I got it to work. Looks like the only way to fix this is to hide the header and footer when keyboard is showing and show header and footer when keyboard is hiding. I also had to remove some margins so that the focused input is at the top. Here's my code I added in the app.component.ts:
keyboard.onKeyboardShow().subscribe(() => {
let headers = document.querySelectorAll("ion-header"); //Get all headers
headers[headers.length - 1].setAttribute("style", "display: none"); //Hide ACTIVE header
let footers = document.querySelectorAll("ion-footer"); //Get all footers
footers[footers.length - 1].setAttribute("style", "display: none"); //Hide ACTIVE footer
let contents = document.querySelectorAll("ion-content"); //Get all content
contents[contents.length - 1].querySelector("div.scroll-content").removeAttribute("style"); // Remove styling from content (margins)
});
keyboard.onKeyboardHide().subscribe(() => {
let headers = document.querySelectorAll("ion-header"); //Get all headers
headers[headers.length - 1].removeAttribute("style"); //Show ACTIVE header again
let footers = document.querySelectorAll("ion-footer"); //Get all footers
footers[footers.length - 1].removeAttribute("style"); //Show ACTIVE footer
let contents = document.querySelectorAll("ion-content"); //Get all content
contents[contents.length - 1].querySelector("div.scroll-content").setAttribute("style", "margin-top: 56px; margin-bottom: 56px;"); //Set styling again (margins)
});

Related

Xamarin Forms Android - keyboard input going to page behind

I've got a strange issue where when I'm on a page (Page 1) that has an Entry, I tap the Entry to give it focus, then I tap a button that calls Navigation.PushModalAsync to bring up another page (Page 2) which only has a Label on it, I type on the physical keyboard, then hit back to go back to Page 1, I magically find the text I'd typed when on Page 2 is in the Entry on Page 1!
That feels like a bug to me? How can I stop keyboard entry going to Page 1 when Page 2 is displayed?
I'm using VS2022, Xamarin Forms 5.0.0.2196, and an Android Emulator using Android 9 / API 29.
public class Page1 : ContentPage
{
public Page1()
{
StackLayout stackLayout = new StackLayout();
stackLayout.Children.Add(new Label() { Text = "Page 1. Tap in Entry A, and then tap the Click Me button." });
stackLayout.Children.Add(new Entry() { Placeholder = "Entry A" });
Button button = new Button() { Text = "Click Me" };
stackLayout.Children.Add(button);
Content = stackLayout;
button.Clicked += Button_Clicked;
}
private async void Button_Clicked(object sender, EventArgs e)
{
ContentPage page2 = new ContentPage();
page2.Content = new Label() { Text = "Page 2. Type some letters on the physical keyboard, and then hit the Back button to get back to Page 1." };
await Navigation.PushModalAsync(new NavigationPage(page2));
}
}
I had test your code on different versions of Android. And at first, when you tap the button, the Entry should be unfocused. Because if I tapped the Entry and then tapped the other field, the cursor will disappear from the Entry. But when I typed on the physical keyboard, the soft keyboard will appear and the text I'd typed will show on the Entry on the Android 9.0.
On the Android 10.0, the soft keyboard will appear but the text will not show on the Entry.
On the Android 11.0, both the keyboard and the text don't show.
In addition, on the Android 9.0, if you don't have tapped the Entry at first, the soft keyboard and the text will not show when you typed on the physical keyboard.
So, this should be the different handling of physical input events in Xamarin.Forms in different Android version. You can also post the issue to the Xamarin.Forms to get the answer.

Cordova android keyboard push up content

I have some content/input fields that are covered when the android keyboard is shown in my cordova app. I have
android:windowSoftInputMode="adjustPan" and <preference name="fullscreen" value="false" />
I tried android:windowSoftInputMode="adjustResize but it kept shrinking my content because it was resizing the window (My content is sized based on viewport width and viewport height). Thank you for any suggestions!
So I had a work around myself that may or may not work for everyone, but I figured I could post this to hopefully help someone who comes across this!
I found a lot of answers but none really helped me. So in my AndroidManinfest.xml file I set android:windowSoftInputMode="adjustPan|stateHidden". Yes, this will still cover the content below the keyboard when it's opened.
To avoid that, I gave all of my scroll views that would be affected by the keyboard being shown a class of inputScrollContainer. Name them whatever you would like.
Since every container (for me) was the same height as was the top bar for each page, I did the following: (you will have to install the device plugin and the keyboard plugin from cordova
Got window.innerHeight at the beginning of my js (if you do this inside of your native.keyboardshow function, iOS will give you the resized view based on the keyboard's height)
Then, inside my native.keyboardShow function, I did the following:
- Then got the height of the top bar (I chose one as they were all the same)
- Added the added the keyboard height and top bar height together
- Then I subtracted those from the window height
Doing this now gave me the height "leftover" for the scroll view to have. After that I:
Got all elements by class name inputScrollContainer
Looped through them and assigned the new height to each (you can assign it to the only scroll view currently in view, but I only had three affected views so I wasn't worried about it)
Now the scroll view was resized to whatever was left between the top bar and the keyboard. Then on my native.keyboardhide function, I just restored the height to what the original height for all of the scroll views was before.
I'm sure there are other ways to do this, but doing it this way gave me flexibility and consistency across iOS and Android. I hope this helps someone!
To move the layout up when the keyboard is visible/shown add the following activity.
<activity android:windowSoftInputMode="adjustPan|adjustResize"> </activity>
adjustResize : The activity's main window is always resized to make room for the soft keyboard on screen.
adjustPan : The activity's main window is not resized to make room for the soft keyboard. Rather, the contents of the window are automatically panned so that the current focus is never obscured by the keyboard and users can always see what they are typing. This is generally less desirable than resizing, because the user may need to close the soft keyboard to get at and interact with obscured parts of the window.
In your scenario you can make use of adjust pan
However it works based on the android versions. It may not work in particular versions. please be find and use.
Please have look at this answer you will come to know a lot.
Viewport height is the problem here.
There is some way to correct the problem with mediaqueries, or with javascript (modifying all of your dom element with the correct height).
But in my case, I had lots of dom elements, and really didn't want to change all of this with javascript.
My trick is :
- Change all of your vh with rem and divide your value by 4
- use this little javascript in all of your page :
$("html").css({"font-size": ($(window).height()/25)+"px"});
Here we go, in this example, font-size is 4% of window height (cause font-size has a minimum value on mobile app), so :
1rem=4% of widow height=4vh
0.25rem = 1vh etc...
In my case, I use a SASS function to divide with 4 all of my vh, so it was easier to change all css. (1h = rem(1) = 0.25rem)
Hope this will help someday.
This JS option delivers a UX similar to iOS:
let events = {
android: {
keyboard: {
threshold: 300, //px
transition: 300, //ms
visible: false,
last_el: null
}
}
}
onAndroidKeyboard() {
if(is_android) {
let threshold = events.android.keyboard.threshold;
let transition = events.android.keyboard.transition;
function onIn(e) {
let target = e.target;
if(target.nodeName.toLowerCase() !== 'input') {
return false
}
let visible = events.android.keyboard.visible;
let h = window.innerHeight;
try {
let bottom = target.getBoundingClientRect().bottom;
if(bottom) {
let diff = h - bottom;
if(diff < threshold) {
if(!visible) {
let animate_amount = threshold - diff;
events.android.keyboard.visible = true;
document.body.style.transform = 'translateY(0)';
document.body.style.webkitTransition = `all ${transition}ms`;
document.body.style.transition = `all ${transition}ms`;
events.android.keyboard.visible = true;
events.android.keyboard.last_el = target;
requestAnimationFrame(function () {
document.body.style.transform = `translateY(-${animate_amount}px)`;
});
}
}
}
} catch (e) {
console.error(e);
}
}
function onOut(e) {
let visible = events.android.keyboard.visible;
if(visible) {
document.body.style.transform = 'translateY(0)';
setTimeout(function () {
requestAnimationFrame(function () {
document.body.style.removeProperty('transform');
document.body.style.removeProperty('transition');
document.body.style.removeProperty('webkitTransition');
events.android.keyboard.visible = false;
events.android.keyboard.last_el = null;
});
}, transition)
}
}
document.addEventListener('focusin', onIn, false);
document.addEventListener('focusout', onOut, false);
}
}

Android softkeyboard issue with input in focus

I have an issue with the android softkeyboard overlapping the input fields when in focus. I have tried various solutions but to no avail. My application is built using phonegap I have tried to change the android:windowSoftInputMode to various solutions but everything doesn't work. these are the issues i ahve
1) The login screen input field does not focus into the center of the screen when in focus unless it is typed into. This is when the android:windowSoftInputMode="adjustPan".
2) If android:windowSoftInputMode="adjustResize" the input field does come into the center of the screen but only when typed into and this also breaks the layout of a bottom nav bar which is pushed up by the keyboard.
Does anyone have any advice on what I should do??
I had the same problem. Here is a workaround:
Install com.ionic.keyboard plugin
Set this in your config.xml
<preference name="fullscreen" value="true" />
Add this to the bottom of your page
<div id="kbs" class="keyboardspace"></div>
Give the surrounding element the id "frame"
Add this to your css
.keyboardspace {
width: 100%;
height: 0;
}
Now register these two event listeners (I'm using jquery here, but it should also be possible without)
var window = angular.element($window);
window.on('native.keyboardshow', function (e) {
$("#kbs").height(e.keyboardHeight);
var focus = $(document.activeElement);
var pos = focus.offset();
var bottom = pos.top + focus.height() + 10;
var maxpos = $($window).height() - e.keyboardHeight;
if (bottom > maxpos) {
$("#frame").scrollTop(bottom - maxpos);
}
});
window.on('native.keyboardhide', function () {
console.log("native.keyboardhide");
$("#kbs").height(0);
});
Note that the frame has to be scrollable for this to work.
You use this code in your Softkeyboard.java:
#override
public void onComputeInsets(Insets outInsets){
super.onComputeInsets(outInsets);
if(!isFullscreenMode()){
outInsets.contentTopInsets = outInsets.visibleTopInsets;
}
}

Phonegap Android keyboard covers input elements scrolling is disabled

I've tried many different solutions and nothing is quite what I want. What I want is for the keyboard to show on top of the content (keeping the content the same size) while being able to scroll to input elements that are covered by the keyboard.
Every solution I've tried will either give me one or the other, but not both.
Solutions I've tried:
Solution here. Adding android:windowSoftInputMode="adjustPan" and android:configChanges="orientation|keyboardHidden" to the main activity in my AndroidManifest.xml.
The above solution using "adjustResize" instead of "adjustPan".
Solution here. Adding to my confix.xml.
Using adjustPan keeps my elements the same size, but disables scrolling. Using adjustResize resizes the entire page, making everything miniature. Keeping default settings, only the wrapper containing the input elements is resized, but scrolling is enabled.
I managed to find the exact same problem (unanswered) here. They were able to "fix" it by resizing their app to 150% and scroll to the covered input element, but like they said it's not ideal.
Any help is appreciated.
For most of the cases in config.xml change the full screen preference to false. that'll do the trick.
<preference name="fullscreen" value="false" />
I have the most efficient solution to scroll into input automatically and make it visible.
First you need to add the ionic keyboard plugin (works on any cordova project) because the eventlistener 'showkeyboard' does not work now.
cordova plugin add ionic-plugin-keyboard --save
Then on your event handler of 'keyboardshow' event add the following code:
window.addEventListener('native.keyboardshow', function(e){
setTimeout(function() {
document.activeElement.scrollIntoViewIfNeeded();
}, 100);
});
P.S: This is supported only on Android (Chrome) and Safari. :D
I had the same problem for android project output and in my situation the input elements were not moving upwards the keyboard . And after a-night-taking search (including those config changes and others) I found that in my angularjs cordova project
StatusBar.overlaysWebView(true);
StatusBar.hide();
lines which are in my controller causing that annoying problem . And I was using those lines for ios statusbar issues now I took those in an if condition and the problem is fixed.
if( device.platform=="iOS")
{
StatusBar.overlaysWebView(true);
StatusBar.hide();
}
You can detect focused textarea or input, then wait a while until keyboard is shown and finally scroll the page to reach focused input.
$("#textarea").focus(function(e) {
var container = $('#container'),
scrollTo = $('#textarea');
setTimeout((function() {
container.animate({
scrollTop: scrollTo.offset().top - container.offset().top + container.scrollTop()
});
}), 500);
});
When keyboard is hidden the textarea keeps focused, so if it's clicked again the keyboard will show and the container needs to scroll again to show the input
$("#textarea").click(function(e) {
e.stopPropagation();
var container = $('#container'), //container element to be scrolled, contains input
scrollTo = $('#textarea');
setTimeout((function() {
container.animate({
scrollTop: scrollTo.offset().top - container.offset().top + container.scrollTop()
});
}), 500);
});
Hope this helps, cheers!
I added an event listener for the keyboard event and scrolled to the input only if it was off screen.
For my case I only wanted to scroll when the keyboard was being shown for the first time, and only if the input item was offscreen.
document.addEventListener('showkeyboard', onKeyboardShow, false);
function onKeyboardShow(e) {
setTimeout(function() {
e.target.activeElement.scrollIntoViewIfNeeded()
}, 500) //needed timeout to wait for viewport to resize
}
To get the showkeyboard event to fire I needed to have the following in my AndroidManifest.xml
android:windowSoftInputMode="adjustResize"
I was also facing the same issue as it is a framework related issue. I have found work around-
constructor(
private platform: Platform,
private keyboard: Keyboard
) {
if(this.platform.is('android')){
this.keyboard.onKeyboardShow().subscribe((e) => {
var keyboardHeight = e.keyboardHeight;
keyboardHeight = keyboardHeight ? keyboardHeight : '337';
$('body').css('height', 'calc(100vh - ' + keyboardHeight + 'px)');
});
this.keyboard.onKeyboardHide().subscribe(e => {
$("body").css("height", "100vh");
});
}
}
I have used 337 which is keyboard height for default, mainly for that condition if keyboard height in not available.
library needed:
npm install jquery
npm install #types/jquery
ionic cordova plugin add cordova-plugin-ionic-keyboard
npm install #ionic-native/keyboard
imports
import { Platform } from '#ionic/angular';
import * as $ from "jquery";
import { Keyboard } from '#ionic-native/keyboard/ngx';
I came up with this solution. I have a full screen Vuejs application which the container has the height of the screen height and then absolute positioned to the bottom, left and right to fix the same sort of issue on IOS.
I then had the same issue on Android so came up with the following;
window.cordovaPluginIonicKeyboardShift = function()
{
/** This is my container (Vuejs instance) **/
const inst = document.querySelector('#app');
/** Get the height of the document **/
const height = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
/** Where we will store the active input **/
let input;
/** The keyboard displaying is around 200 milliseconds **/
inst.style.transition = 'transform 0.2s';
/** Makes me feel better having this on to increase performance **/
inst.style.transform = 'translateZ(0)';
/**
* Set Input
* #param e
*/
let setInput = function(e) {
input = e.target;
};
/**
* On Keyboard Show
* #param event
*/
let onKeyboardShow = function(event) {
let offset = input.getBoundingClientRect();
if(offset.top + input.clientHeight > height - event.keyboardHeight) {
inst.style.transform = `translateZ(0) translateY(-${event.keyboardHeight}px)`;
}
};
/**
* OnKeyboard Hide
*/
let onKeyboardHide = function() {
inst.style.transform = `translateZ(0) translateY(0px)`;
};
/**
* Hide Keyboard
* #param e
*/
let hideKeyboard = function(e) {
if(e.target.tagName.toLowerCase() !== 'input' && e.target.tagName.toLowerCase() !== 'textarea') {
if(typeof input !== 'undefined') input.blur();
if(Keyboard.isVisible) Keyboard.hide();
}
};
/**
* Go through all inputs and textarea's on document and attach touchstart
* event. Using touchstart to define the input before focus which is what will trigger
* the keyboard.
*/
inst.querySelectorAll('input, textarea').forEach(function(elm) {
elm.removeEventListener('touchstart', setInput, false);
elm.addEventListener('touchstart', setInput, false);
});
/**
* Need to get the height to shift the document up by x amount
*/
window.removeEventListener('keyboardWillShow', onKeyboardShow, false);
window.addEventListener('keyboardWillShow', onKeyboardShow, false);
/**
* Shift it back down on keyboard hiding
*/
window.removeEventListener('keyboardWillHide', onKeyboardHide, false);
window.addEventListener('keyboardWillHide', onKeyboardHide, false);
/**
* Some browsers/phone models act odd when touching off the input
* so this is in to cover all bases
*/
document.removeEventListener('touchstart', hideKeyboard, false);
document.addEventListener('touchstart', hideKeyboard, false);
};
It also turns out even installing the plugin has affected the normal use of the keyboard which is why the hide method is called as the keyboard doesn't go away without it.
Then on my Vuejs instances I have the following updated method;
updated: function () {
this.$nextTick(function () {
cordovaPluginIonicKeyboardShift();
})
},
You'll also need to add this plugin;
phonegap cordova plugin add cordova-plugin-ionic-keyboard
Doing the above I have a successfully working fullscreen app with a working keyboard.
If you find yourself testing on Xcode Simulator and the keyboard is not showing, go to Simulator -> Device -> Erase all content and settings and re-install the app. No idea why this occurs but this will save you a lot of head aches.
Hope this helps someone
I figured out the problem. I have a media query in my CSS where the size of certain elements change for smaller screen sizes. Editing that query fixed my problem.
I am using the Cordova plugin 'ionic-plugin-keyboard' and listen to the 'native.keyboardshow' and 'native.keyboardhide' events to resize the HTML container element of my form:
window.addEventListener('native.keyboardshow', function (e) {
container.style.bottom = e.keyboardHeight + "px";
});
window.addEventListener('native.keyboardhide', function () {
container.style.bottom = null;
});
This results in the proper input fields to scroll into view (also when tabbing back and forward between the fields.
If you have made correctly the project as Cordova documentation says, It won't happen.
May be are you using a scroll library like iScroll?

PhoneGap: Android soft keyboard covers input fields

I am having issues with a PhoneGap application that I'm working in. My app has lots of forms, since the objective of the app is mostly to provide a nice user interface to a database. However, whenever the user tries to edit an input field that is close to the bottom, the Android keyboard will pop up and cover the field, so that the user cannot see what he/she is writing.
Do you know if there is a workaround for this? Has anyone come across this issue on their apps?
What you can do in this case (what I did when I had this problem...): add on-focus event on fields, and scroll up document. So you will see input field on the top of page :)
I agree with Paulius, for Android I found this to be the cleanest solution.
I know this is an old question but I will share my solution for other people if any body is still facing this issue.
// fix keyboard hiding focused input texts
// using native keyboard plugin and move.min.js
// https://github.com/vitohe/ionic-plugins-keyboard/tree/f94842fec1bacf72107083d2e44735e417e8439d
// http://visionmedia.github.io/move.js/
// not tested on iOS so implementation is for Android only
if ($cordovaDevice.getPlatform() === "Android") {
// device is running Android
// attach showkeyboard event listener
// which is triggered when the native keyboard is opened
window.addEventListener('native.showkeyboard', keyboardShowHandler);
// native.showkeyboard callback
// e contains keyboard height
function keyboardShowHandler(e) {
// get viewport height
var viewportHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
// get the maximum allowed height without the need to scroll the page up/down
var scrollLimit = viewportHeight - (document.activeElement.offsetHeight + document.activeElement.offsetTop);
// if the keyboard height is bigger than the maximum allowed height
if (e.keyboardHeight > scrollLimit) {
// calculate the Y distance
var scrollYDistance = document.activeElement.offsetHeight + (e.keyboardHeight - scrollLimit);
// animate using move.min.js (CSS3 animations)
move(document.body).to(0, -scrollYDistance).duration('.2s').ease('in-out').end();
}
}
window.addEventListener('native.hidekeyboard', keyboardHideHandler);
// native.hidekeyboard callback
function keyboardHideHandler() {
// remove focus from activeElement
// which is naturally an input since the nativekeyboard is hiding
document.activeElement.blur();
// animate using move.min.js (CSS3 animations)
move(document.body).to(0, 0).duration('.2s').ease('in-out').end();
}
}
The end result is unbelievably smooth.

Categories

Resources