В Ionic 2, как плавать элемент над клавиатурой, когда клавиатура показывает?

Я хочу, чтобы панель ввода сообщения плавала над клавиатурой, когда отображается клавиатура, но похоже, что нет директивы для подключения клавиатуры (как v1) в Ionic 2 еще (возможно в работах?). Есть ли альтернатива/обходной путь?

Текущее поведение:

17e1422aab4f42b38cfe582064ca35d09a511df6.PNGab8ac73b7e8c3958b262d02a601b64fe2f772779.PNG

Требуемое поведение:

d74b3624a4e88353ba644224642a592b49a2ef55.PNG

Вот код строки ввода моего сообщения:

<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>

Ответы

Ответ 1

Я нашел решение, которое работает для меня на IOS.

Когда вы просматриваете <ion-item> с <ion-input> в браузере (отладка использует Safari для IOS), вы можете обнаружить, что ионный генерирует <div class='input-cover'>, который имеет стиль position: absolute;.

Напишите CSS, который переопределяет это, как показано ниже

.input-cover {
  position: static;
}

Это помогло, и теперь, когда вы фокусируетесь на поле ввода, он прокручивается в поле зрения и больше не скрывается под клавиатурой, и все это работает маслянисто.

Ответ 2

Мне также нужно было это реализовать. Я сделал это, и он отлично работает.

В первую очередь вам нужно использовать клавиатуру плагинов cordova и при стартовом вызове cordova.plugins.Keyboard.disableScroll(true);, чтобы клавиатура не увеличивала ваш вид. 2-й вам нужно прослушивать клавиатуру, а клавиатура скрывает такие события с помощью обработчиков:

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);
    }

Чем вы можете сделать наблюдаемое из такого события:

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

Чем вы можете слушать это наблюдаемое. Если клавиатура открыта, чем вы изменяете высоту контейнера, где отображаются ваши сообщения. Вы в основном должны сделать его ниже для высоты клавиатуры. Вот как я это сделал

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 + '%';
                }

            });

и вы изменяете эти свойства с помощью ngStyle, как этот

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

Мне также понадобилось это для chatapp, и теперь он работает отлично (даже если вы поворачиваете экранный/альбомный режим экрана), вход всегда плавает над клавиатурой, как в родных приложениях:)

Я надеюсь, что это поможет вам!

Ответ 3

Решение, которое я закончил, и я удовлетворен тем, что:

  • Удаление Keyboard.disableScroll(true);
  • Используя обычный <input type="text"> вместо <ion-input type="text">

Теперь работает отлично!

Ответ 4

У меня была эта проблема с Android, поэтому я создал сервисный метод, который я мог бы разместить в отдельных компонентах. Он основан на использовании полей <ion-input> внутри тега <ion-content>.

Это использует метод setScrollTop, который был добавлен в класс Content.

Сервис

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 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);
    }
}

Компонент

@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);
        });
    }
}