2

In my Ionic application I need to animate the ion-content element with Angular animation when the keyboard appear/disappear.

I have the following code:

<ion-content padding [@shiftContent]="isKeyboardOpen">

and

@Component({
  selector: 'page',
  templateUrl: 'page.html',
  animations: [
    trigger('shiftContent', [
      state('0', style({
        top: '0px'
      })),
      state('1', style({
        top: "-200px"
      })),
      transition('* <=> *', animate('50ms')),
    ])
  ]
})

and

  ionViewDidEnter() {

    this.keyboardOpenObs = this.keyboard.onKeyboardShow().subscribe(() => {
      this.isKeyboardOpen = true;
    });
    this.keyboardCloseObs = this.keyboard.onKeyboardHide().subscribe(() => {
      this.isKeyboardOpen = false;
    });
  }

When the page load and I open the keyboard for the first time nothing happen, then when I close the keyboard it start working but in the opposite direction (if I open I get the closing animation and vice versa).

The same setup works great if I control the variable with a button instead of the keyboard event.

The listener to the keyboard open/close works, I tried by logging the variable on the keyboard event.

AleCat83
  • 1,443
  • 3
  • 22
  • 41
  • I have exactly the same issue. Would you mind opening an issue on GitHub at Ionic? I tried debuging it a hole day with no success... Seems like the iOS Event blocks ionic events somehow. – muuvmuuv Sep 14 '19 at 11:34
  • @muuvmuuv, I found a good workaround, I posted it below, it may be useful to you. – AleCat83 Sep 16 '19 at 21:05

3 Answers3

2

I've used a similar approach as Jonathan (thanks for the tip!) but using AnimationController from ionic, as follows

On the inputs you want to trigger the shift up.

<ion-input class="login-input" type="number" formControlName="weight"
          (ionFocus)="onKeyboardStateChange(true)" (ionBlur)="onKeyboardStateChange(false)">
        </ion-input>

attach class="content-to-shift" to the element you want to shift up, e.g.

<ion-content fullscreen="true" class="content-to-shift">

imports

import { AnimationController, Platform } from '@ionic/angular';

constructor

private animationController: AnimationController,
private platform: Platform

in page.ts

onKeyboardStateChange(event) {
if (this.platform.is('cordova')) {
  if (event) {
    this.isKeyboardOpen = true;
    const anim = this.animationController.create()
      .addElement(document.querySelector('.content-to-shift'))
      .duration(200)
      .iterations(1)
      .fromTo('transform', 'translateY(0px)', 'translateY(-200px)');
    anim.play();
  } else {
    this.isKeyboardOpen = false;
    const anim = this.animationController.create()
      .addElement(document.querySelector('.content-to-shift'))
      .duration(200)
      .iterations(1)
      .fromTo('transform', 'translateY(-200px)', 'translateY(0px)');
    anim.play();
  }
}

}

joplaete
  • 113
  • 1
  • 9
1

I solved it in this way:

In my template:

<ion-content [@shiftContent]="isKeyboardOpen">

and on every input that triggers the keyboard

          <ion-input
            value=""
            type="text"
            placeholder="Email"
            (ionFocus)="onKeyboardStateChange(true)"
            (ionBlur)="onKeyboardStateChange(false)">
          </ion-input>

then, in the page decorator inside the controller I have the animation:

  animations: [
    trigger('shiftContent', [
      state('0', style({
        top: '0px'
      })),
      state('1', style({
        top: "-150px"
      })),
      transition('* <=> *', animate('200ms')),
    ])
  ]

then the method to trigger the animation:

  onKeyboardStateChange(event) {
      if (event) {
        this.isKeyboardOpen = true;
      }
      else {
        this.isKeyboardOpen = false;
      }
    
  }

Basically, instead of relying on the keyboard's event "onKeyboardShow" and "onKeyboardHide", I trigger the animation when the input gets focused. It is clearly a workaround but in my case it solved the problem.

AleCat83
  • 1,443
  • 3
  • 22
  • 41
0

I cannot see any issue in your code from the given problematic. But what might help you to find out if your animation does anything is to check the two ouputs angular-animation provides you: Start and Done (AnimationEvents). You will receive a event that contains informations about your new states. If you receive some, then you might need to check your animation in detail, or the css around.

animationDone(event) {
  console.log(event)
}

animationStarted(event) {
  console.log(event)
}
<ion-content padding
[@shiftContent]="isKeyboardOpen"
(@shiftContext.start)="animationStarted($event)"
(@shiftContext.done)="animationDone($event)">
Jonathan Stellwag
  • 3,843
  • 4
  • 25
  • 50
  • 1
    Thanks, this is a good start to debug this. Meanwhile I reach the result in another way, avoiding the keyboard open / close callbacks and controlling the animation with the ionFocus and ionBlur events on each input field. The animation stay the same, this makes me think that the problem is related to the keyboard callbacks (it is strange thou cause they are called correctly, I tested them printing in the console). It works but I have to call the event from any input. – AleCat83 Mar 06 '19 at 12:41
  • Then my question - Do you get any Done or Start event or is this never reaching the animation. What also could help is the put in the state via observable and | async pipe - Then you can listen (subscribe) to your animation input and check what values go into the animation, without the need to find the animationState = foo place. – Jonathan Stellwag Mar 06 '19 at 12:57