web-dev-qa-db-fra.com

Dans Ionic 2, comment faire flotter un élément au-dessus du clavier lorsque le clavier s'affiche?

Je veux que ma barre de saisie de message flotte au-dessus du clavier lorsque le clavier s'affiche, mais il semble qu'il n'y ait pas directive d'attachement du clavier ( comme v1 ) dans Ionic 2 encore ( peut-être en préparation ?). Y a-t-il une alternative/solution?

Comportement actuel:

Comportement recherché:

Voici le code de ma barre de saisie de message:

<ion-toolbar position="bottom" *ngIf="userIsAdmin">

    <form (ngSubmit)="onSubmit(f)" #f="ngForm" class="message-form">

        <ion-badge class="message-form-badge">Admin</ion-badge>

        <ion-input type="text" placeholder="Type a message..." ngControl="messageInput"></ion-input>

        <button type="submit" small class="message-form-button">Send <ion-icon name="send"></ion-icon></button>

    </form>

</ion-toolbar>
21
nunoarruda

J'ai trouvé une solution qui fonctionne pour moi sur IOS.

Lorsque vous inspectez le <ion-item> avec <ion-input> dans le navigateur (débogage avec Safari pour IOS), vous pouvez constater que ionic génère un <div class='input-cover'> qui a le style position: absolute;.

Écrivez un CSS qui remplace cela comme ci-dessous

.input-cover {
  position: static;
}

Cela a fait l'affaire pour moi et maintenant, lorsque vous vous concentrez sur un champ de saisie, il défile dans la vue et ne se cache plus sous le clavier et tout cela fonctionne de manière fluide.

32
Anees.jsdev

J'ai également eu besoin de mettre en œuvre cela. Je l'ai fait et cela fonctionne parfaitement.

Vous devez d'abord utiliser le clavier des plugins cordova, et au début, appelez cordova.plugins.Keyboard.disableScroll(true); pour que le clavier ne pousse pas votre vue vers le haut. 2e, vous devez écouter sur les claviers et les événements de masquage du clavier comme celui-ci avec les gestionnaires:

cordova.plugins.Keyboard.disableScroll(true);
                    window.addEventListener('native.keyboardshow', this.dispatchMe);
                    window.addEventListener('native.keyboardhide', this.dispatchMeHide);

    dispatchMe(e) {
        var event = new CustomEvent('keyboardShown');
        event['keyboardHeight'] = e.keyboardHeight;
        document.dispatchEvent(event);
    }

    dispatchMeHide() {
        var event = new CustomEvent('keyboardShown');
        event['closed'] = true;
        document.dispatchEvent(event);
    }

Que vous pouvez faire un événement observable comme celui-ci:

this.keyboardObservable = Observable.fromEvent(document, 'keyboardShown');

Alors vous pouvez écouter ce qui est observable. Si le clavier est ouvert, vous modifiez la hauteur du conteneur dans lequel vos messages sont affichés. Vous devez essentiellement le réduire pour la hauteur du clavier. Voici comment j'ai fait ça

this.chatService.keyboardObservable
            .subscribe(data => {
                if (data.closed) {
                    this.sectionHeight = 85 + '%';
                    this.inputBottom = 0 + '%';
                }
                else {
                    this.docHeight = document.body.clientHeight;
                    this.sectionHeight = ((this.docHeight - data.keyboardHeight - (document.getElementById('toptoolbar').clientHeight + document.getElementById('inputchat').clientHeight)) / this.docHeight) * 100 + '%';
                    this.inputBottom = data.keyboardHeight / this.docHeight * 100 + '%';
                }

            });

et vous modifiez ces propriétés avec ngStyle comme ceci

[ngStyle]="{'height': sectionHeight}"

J'avais également besoin de cela pour chatapp, et maintenant cela fonctionne parfaitement (même si vous faites pivoter le mode portrait/paysage à l'écran), l'entrée flotte toujours au-dessus du clavier, tout comme dans les applications natives :)

J'espère que cela t'aidera!

5
Denko Mancheski

La solution que j'ai finalement utilisée et qui me satisfait est la suivante:

  1. Suppression de Keyboard.disableScroll(true);
  2. En utilisant un <input type="text"> au lieu de <ion-input type="text">

Fonctionne parfaitement maintenant!

2
nunoarruda

J'avais ce problème avec Android, j'ai donc créé une méthode de service que je pouvais mettre dans des composants individuels. Il est basé sur l'utilisation de <ion-input> champs à l'intérieur d'un <ion-content> tag.

Cela tire parti de la méthode setScrollTop qui a été ajoutée à la classe Content.

Un service

export class KeyboardService {

    autoKeyboardScroll(content:Content, scrollBackAfterKeyboardClose?:boolean) {
        if (!content) {
            return;
        }
        var previousScrollTop = null;
        function onKeyboardShow(e) {
            // if the content no longer exists, stop the listener
            if (removeListenersForMissingContent()) {
                return;
            }
            previousScrollTop = content.getScrollTop();
            // find the input that's currently in focus
            var focusedElement = document.activeElement;
            if (focusedElement && ['INPUT', 'TEXTAREA'].indexOf(focusedElement.tagName)!==-1) {
                // determine the total offset between the top of the "ion-content" and this element.
                // we will do this by climbing up the dom until we reach the "ion-content"
                var offsetTop = focusedElement.offsetTop + focusedElement.scrollHeight;
                var parentEl = focusedElement.offsetParent;
                while (parentEl && parentEl.tagName!=='ION-CONTENT') {
                    offsetTop += parentEl.offsetTop;
                    parentEl = parentEl.offsetParent;
                }
                // we want to move the input so that the bottom of the focused input is just above the keyboard
                var contentDimensions = content.getContentDimensions();
                var newScrollTop = offsetTop - (contentDimensions.contentHeight - focusedElement.scrollHeight);
                content.setScrollTop(newScrollTop);
            }
        }
        function onKeyboardHide(e) {
            // if the content no longer exists, stop the listener
            if (removeListenersForMissingContent()) {
                return;
            }
            // set the scroll top back to the initial position, if requested
            if (scrollBackAfterKeyboardClose) {
                content.setScrollTop(previousScrollTop);
            }
        }
        function removeListenersForMissingContent() {
            // if there is no content, remove the keyboard listeners
            if (!content || content.getContentDimensions().contentHeight===0) {
                window.removeEventListener('native.keyboardshow', onKeyboardShow);
                window.removeEventListener('native.keyboardhide', onKeyboardHide);
                return true;
            }
        }
        // setup listeners
        window.addEventListener('native.keyboardshow', onKeyboardShow);
        window.addEventListener('native.keyboardhide', onKeyboardHide);
    }
}

Composant

@Component({
    template: `<ion-content>
        <ion-list>
            <ion-item>
                <div style="height: 400px"></div>
            </ion-item>
            <ion-item>
                <ion-label>Field 1</ion-label>
                <ion-input type="text"></ion-input>
            </ion-item>
            <ion-item>
                <ion-label>Field 2</ion-label>
                <ion-input type="text"></ion-input>
            </ion-item>
            <ion-item>
                <ion-label>Field 3</ion-label>
                <ion-input type="text"></ion-input>
            </ion-item>
            <ion-item>
                <ion-label>Field 4</ion-label>
                <ion-input type="text"></ion-input>
            </ion-item>
            <ion-item>
                <ion-label>Field 5</ion-label>
                <ion-input type="text"></ion-input>
            </ion-item>
            <ion-item>
                <ion-label>Field 6</ion-label>
                <ion-input type="text"></ion-input>
            </ion-item>
        </ion-list>
    </ion-content>`
})
export class MyPage {
    @ViewChild(Content) content: Content;

    constructor(private: keyboardService: KeyboardService) {}

    // add the keyboard scroll action to this page. this is added after the view has been created,
    // so the content element will be avaialble.
    ionViewDidEnter() {

        // timeout seems to be required, to ensure that the content child is available
        setTimeout(() => {
            // set the keyboard to auto-scroll to the focused input, when it opens
            this.keyboardService.autoKeyboardScroll(this.content);
        });
    }
}
1
Dustin