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

时间:2022-11-27 23:02:09

I want my message input bar to float above the keyboard when the keyboard shows but it looks like there's no keyboard-attach directive (like v1) in Ionic 2 yet (maybe in the works?). Is there any alternative/workaround?

当键盘显示时,我希望我的消息输入栏浮动在键盘上方但看起来在Ionic 2中没有键盘附加指令(如v1)(可能在工作中?)。有替代方案/解决方法吗?

Current behaviour:

目前的行为:

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

Wanted behaviour:

通缉行为:

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

Here's the code of my message input bar:

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

<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 个解决方案

#1


30  

I found a solution which works for me on IOS.

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

When you inspect the <ion-item> with <ion-input> in the browser(debugging use Safari for IOS) you can find that ionic generates a <div class='input-cover'> which has the style position: absolute;.

当您在浏览器中使用 检查 (调试使用Safari for IOS)时,您会发现离子生成一个

,其样式位置为:absolute; 。

Write a CSS which overrides this as below

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

.input-cover {
  position: static;
}

This did the trick for me and now when you focus on an input field, it scrolls into view and does not hide below the keyboard anymore and all this works buttery smooth.

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

#2


5  

I've also needed to implement this. I did it and it works perfectly.

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

1st you need to use cordova plugins keyboard, and at the start call cordova.plugins.Keyboard.disableScroll(true); so the keyboard will not push your view up. 2nd you need to listen on keyboardshow and keyboard hide events like this with a the handlers:

1,你需要使用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);
    }

Than you can make an observable from event like this:

你可以从这样的事件中观察到:

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

Than you can listen to that observable. If the keyboard is open than you change the height of the container where your messages are shown. You basically have to make it lower for the height of the keyboard. Here is how I did that

比你能听到那个可观察的。如果键盘打开,则更改显示消息的容器高度。你基本上必须降低键盘的高度。我就是这样做的

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

            });

and you change these properties with ngStyle like this

并使用ngStyle更改这些属性

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

I also needed this for chatapp, and now it works perfectly (even if you rotate the screen portrait/landscape mode), the input always floats above the keyboard just like in the native apps :)

我也需要这个用于chatapp,现在它完美运行(即使你旋转屏幕纵向/横向模式),输入总是漂浮在键盘上方,就像在原生应用程序中一样:)

I hope this will help you!

我希望这能帮到您!

#3


2  

The solution I ended up using and one that I'm satisfied with is:

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

  1. Removing Keyboard.disableScroll(true);
  2. 删除Keyboard.disableScroll(true);
  3. Using a regular <input type="text"> instead of <ion-input type="text">
  4. 使用常规而不是

Works perfectly now!

现在完美运作!

#4


1  

I was having this problem with Android, so I created a service method that I could put into individual components. It's based on using <ion-input> fields inside of an <ion-content> tag.

我遇到了Android的这个问题,所以我创建了一个可以放入单个组件的服务方法。它基于 标签内的 字段。

This takes advantage of the setScrollTop method that was added to the Content class.

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

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

Component

@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


30  

I found a solution which works for me on IOS.

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

When you inspect the <ion-item> with <ion-input> in the browser(debugging use Safari for IOS) you can find that ionic generates a <div class='input-cover'> which has the style position: absolute;.

当您在浏览器中使用 检查 (调试使用Safari for IOS)时,您会发现离子生成一个

,其样式位置为:absolute; 。

Write a CSS which overrides this as below

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

.input-cover {
  position: static;
}

This did the trick for me and now when you focus on an input field, it scrolls into view and does not hide below the keyboard anymore and all this works buttery smooth.

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

#2


5  

I've also needed to implement this. I did it and it works perfectly.

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

1st you need to use cordova plugins keyboard, and at the start call cordova.plugins.Keyboard.disableScroll(true); so the keyboard will not push your view up. 2nd you need to listen on keyboardshow and keyboard hide events like this with a the handlers:

1,你需要使用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);
    }

Than you can make an observable from event like this:

你可以从这样的事件中观察到:

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

Than you can listen to that observable. If the keyboard is open than you change the height of the container where your messages are shown. You basically have to make it lower for the height of the keyboard. Here is how I did that

比你能听到那个可观察的。如果键盘打开,则更改显示消息的容器高度。你基本上必须降低键盘的高度。我就是这样做的

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

            });

and you change these properties with ngStyle like this

并使用ngStyle更改这些属性

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

I also needed this for chatapp, and now it works perfectly (even if you rotate the screen portrait/landscape mode), the input always floats above the keyboard just like in the native apps :)

我也需要这个用于chatapp,现在它完美运行(即使你旋转屏幕纵向/横向模式),输入总是漂浮在键盘上方,就像在原生应用程序中一样:)

I hope this will help you!

我希望这能帮到您!

#3


2  

The solution I ended up using and one that I'm satisfied with is:

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

  1. Removing Keyboard.disableScroll(true);
  2. 删除Keyboard.disableScroll(true);
  3. Using a regular <input type="text"> instead of <ion-input type="text">
  4. 使用常规而不是

Works perfectly now!

现在完美运作!

#4


1  

I was having this problem with Android, so I created a service method that I could put into individual components. It's based on using <ion-input> fields inside of an <ion-content> tag.

我遇到了Android的这个问题,所以我创建了一个可以放入单个组件的服务方法。它基于 标签内的 字段。

This takes advantage of the setScrollTop method that was added to the Content class.

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

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

Component

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