amitairos
amitairos

Reputation: 2967

Ionic 4 keyboard covers input field

I have an Ionic 4 app that has a form with inputs in it.
When the user clicks on the input, it opens the keyboard, but it hides the content, without scrolling.
Is there any way around this?

This is my code:

<form #f="ngForm" (ngSubmit)="sendMail()">
   <ion-item>
     <ion-label position="floating">name
     </ion-label>
     <ion-input [(ngModel)]="senderName">
     </ion-input>
   </ion-item>

   <ion-item>
      <ion-label position="floating">mail
      </ion-label>
      <ion-input [(ngModel)]="senderMail">
      </ion-input>
    </ion-item>

    <ion-item class="borderedTextArea">
      <ion-textarea [(ngModel)]="mailText" style="height:150px;"></ion-textarea>
    </ion-item>

    <ion-button type="submit" style="float:left">send</ion-button>

</form>

Upvotes: 6

Views: 12761

Answers (9)

Sani Asani
Sani Asani

Reputation: 1

WorkAround I haven't found a solution, but I discovered a workaround for the ion-input being covered by the keyboard problem, I just gave the ion-input a pointer-events:none;

ion-input{
  pointer-events: none;
}

This solved the issue for me

Upvotes: 0

Martin &#197;hlin
Martin &#197;hlin

Reputation: 2914

I'm currently using Ionic4 with Cordova 9 and all the latest packages, and I could not find any settings within the framework that worked for me. In the end I made this workaround that completely circumvents the framework. It has a little animation and looks pretty OK, so I'm using it until the framework solves this properly.

import * as $ from "jquery";

global.scss

ion-app {
    /*animation of native keyboard show*/
    transition: margin 300ms;
}

app.component.ts

declare var $: any;

ngAfterViewInit() {
    // This element never changes.
    let ionapp = document.getElementsByTagName("ion-app")[0];

    window.addEventListener('keyboardDidShow', async (event) => {
        // Move ion-app up, to give room for keyboard
        let kbHeight: number = event["keyboardHeight"];
        let viewportHeight: number = $(window).height();
        let inputFieldOffsetFromBottomViewPort: number = viewportHeight - $(':focus')[0].getBoundingClientRect().bottom;
        let inputScrollPixels = kbHeight - inputFieldOffsetFromBottomViewPort;

        // Set margin to give space for native keyboard.
        ionapp.style["margin-bottom"] = kbHeight.toString() + "px";

        // But this diminishes ion-content and may hide the input field...
        if (inputScrollPixels > 0) {
            // ...so, get the ionScroll element from ion-content and scroll correspondingly
            // The current ion-content element is always the last. If there are tabs or other hidden ion-content elements, they will go above.
            let ionScroll = await $("ion-content").last()[0].getScrollElement();
            setTimeout(() => {
                $(ionScroll).animate({
                    scrollTop: ionScroll.scrollTop + inputScrollPixels
                }, 300);
            }, 300); // Matches scroll animation from css.
        }
    });
    window.addEventListener('keyboardDidHide', () => {
        // Move ion-app down again
        // Scroll not necessary.
        ionapp.style["margin-bottom"] = "0px";
    });
}

Upvotes: 12

David
David

Reputation: 525

The following works for me to show the input box just over the keyboard. I am using Ionic 7 with react.

Using IonFooter achieves that the content is at the bottom and not hidden. Using IonModal with height equal to 'auto' achieves that the modal is just as tall as its content.

Important: You must add the following line to variables.css so that the modal has an auto height.

ion-modal.auto-height {
  --height: auto;
}

The example component:

export const TestPage: React.FC = () => {
  return (
    <>
      <IonContent>
        <IonText><h2>Content area</h2></IonText>
      </IonContent>
      {/* Added green background to make the footer/modal area visible for this example. */}
      <IonFooter style={{ backgroundColor: 'green' }}>
        <IonButton id="open-custom-dialog" fill='clear'>
          <IonLabel>Open modal</IonLabel>
        </IonButton>
        <IonModal
          breakpoints={[0, 1]}
          initialBreakpoint={1}
          handle={false}
          trigger="open-custom-dialog"
          className='auto-height'>
          <IonList>
            <IonItem>
              <IonInput
                label="Your input"
                placeholder="Type here"/>
            </IonItem>
          </IonList>
        </IonModal>
      </IonFooter>
    </>
  );
}

Screenshot

Upvotes: 0

Reniel Gimeno
Reniel Gimeno

Reputation: 11

<preference name="resizeOnFullScreen" value="true" />

You can install cordova-plugin-ionic-keyboard and edit your config.xml file and add this line of code

cordova-plugin-ionic-keyboard

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.

Upvotes: 1

D4NT3
D4NT3

Reputation: 141

you could try some combination of

ionFocus

https://ionicframework.com/docs/api/input#events and

scrollIntoView

https://developer.mozilla.org/de/docs/Web/API/Element/scrollIntoView if nothing else is working

Upvotes: 0

Ibni Amin
Ibni Amin

Reputation: 1

Simply solve it with ionFocus event and scrollToBottom fuction and then call it in ionFocus so when you focus in input your content will scroll to bottomstrong text

Upvotes: 0

angelvals
angelvals

Reputation: 21

I was having that issue too but only in android, what i did was to create a script that get the height of the focused element and the keyboard, and using jQuery I added a marginTop to move the body above the keyboard when the keyboard shows, this is my code:

constructor(
    private platform: Platform,
    private keyboard: Keyboard
  ) {
    if(this.platform.is('android')){
      this.keyboard.onKeyboardShow().subscribe((e) => {
        const offset = $(document.activeElement).offset().top;
        let height = (offset - e.keyboardHeight)*-1;
        height = height > 0 ? 0 : height;      
        $('body').animate({ 'marginTop': height + 'px' }, 100);
      });
      this.keyboard.onKeyboardHide().subscribe(e => {
        $('body').animate({ 'marginTop': 0 + 'px' }, 100);
      });
    }
}

libs 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';
   

Is not an elegant solution but it works

Just some change in this code will give better experience

this.keyboard.onKeyboardShow().subscribe((e) => {
    const safeArea = 40 ;
    const offset1 = $(document.activeElement).offset().top;
    const offset2 = window.innerHeight - e.keyboardHeight - $(document.activeElement).height() - safeArea ;
    const diff = offset1 - offset2;
    if(offset1 > window.innerHeight -  e.keyboardHeight - safeArea)
        $('body').animate({ 'marginTop': -1 * diff + 'px' }, 100);
});

Upvotes: 1

poimsm2
poimsm2

Reputation: 562

I solve that by downgrading the keyboard plugin

ionic cordova plugin remove cordova-plugin-ionic-keyboard

ionic cordova plugin add [email protected]

and then remove the android platform and add it again

Upvotes: 0

lokoxumusu
lokoxumusu

Reputation: 71

I've solved this Ionic bug provisionally with:

...
<ion-texarea (ionFocus)="fixTextareaBug()">
...

and in your .ts

@ViewChild(IonTextarea)
public ionTextArea: IonTextarea;
private focusFix = false;

...
...

public fixTextareaBug() {
  setTimeout(() => {
    if (this.focusFix) {
      this.focusFix = false;
      return;
    }
    (this.ionTextArea as any).el.lastElementChild.blur();
    this.focusFix = true;
    (this.ionTextArea as any).el.lastElementChild.focus();
  }, TEXTAREA_TIMEOUT);
}

I hope it solved your problem

Upvotes: 0

Related Questions