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

时间:2016-04-19 00:16:17

标签: cordova typescript ionic-framework angular ionic2

我希望我的信息输入栏在键盘显示时漂浮在键盘上方但看起来在Ionic 2中还没有keyboard-attach directivelike v1)(maybe in the works ?)。有没有替代/解决方法?

当前行为:

通缉行为:

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

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

4 个答案:

答案 0 :(得分:32)

我找到了一个适用于IOS的解决方案。

当您在浏览器中检查<ion-item> <ion-input>时(调试使用Safari for IOS),您会发现离子生成<div class='input-cover'>,其样式为position: absolute;

编写一个覆盖它的CSS,如下所示

.input-cover {
  position: static;
}

这对我来说很有把握,现在当你专注于一个输入字段时,它会滚动到视图中并且不再隐藏在键盘下方,所有这些都可以使黄油变得平滑。

答案 1 :(得分:5)

我还需要实现这一点。我做到了,它完美无缺。

首先你需要使用cordova插件键盘,并在开始通话时 cordova.plugins.Keyboard.disableScroll(true);所以键盘不会推动您的视图。 第二,你需要在键盘显示和键盘上使用处理程序隐藏这样的事件:

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,现在它完美运行(即使你旋转屏幕纵向/横向模式),输入总是漂浮在键盘上方,就像在原生应用程序中一样:)

我希望这会对你有所帮助!

答案 2 :(得分:2)

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

  1. 删除Keyboard.disableScroll(true);
  2. 使用常规<input type="text">代替<ion-input type="text">
  3. 现在完美运作!

答案 3 :(得分:1)

我遇到了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'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);
        });
    }
}