在 Ionic 2 中,如何在键盘显示时将元素浮动到键盘上方?

In Ionic 2, how to float an element above the keyboard when the keyboard shows?

我希望我的消息输入栏在键盘显示时浮动在键盘上方,但看起来没有 keyboard-attach directive (like v1) in Ionic 2 yet (maybe in the works?)。有没有alternative/workaround?

这是我的消息输入栏的代码:

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

我也需要实现这个。我做到了,而且效果很好。

1st你需要使用cordova插件键盘,并在开始调用 cordova.plugins.Keyboard.disableScroll(true); 因此键盘不会将您的视图向上推。 第二,您需要使用处理程序收听 keyboardshow 和 keyboard hide 事件:

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

我也需要这个用于聊天应用程序,现在它可以完美运行(即使你旋转屏幕 portrait/landscape 模式),输入始终浮动在键盘上方,就像在本机应用程序中一样:)

希望对您有所帮助!

我最终使用的解决方案和我满意的解决方案是:

  1. 删除Keyboard.disableScroll(true);
  2. 使用常规 <input type="text"> 而不是 <ion-input type="text">

现在完美运行!

我在使用 Android 时遇到了这个问题,所以我创建了一个可以放入各个组件的服务方法。它基于在 <ion-content> 标签内使用 <ion-input> 字段。

这利用了添加到 Content class 的 setScrollTop 方法。

服务

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

组件

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

我在 IOS.

上找到了适合我的解决方案

当您在浏览器中使用 <ion-input> 检查 <ion-item> 时(使用 Safari 调试 IOS),您会发现 ionic 生成了具有以下样式的 <div class='input-cover'> position: absolute;.

写一个 CSS 覆盖它如下

.input-cover {
  position: static;
}

这对我有用,现在当你专注于一个输入字段时,它会滚动到视图中并且不再隐藏在键盘下方并且所有这一切都非常顺利。