「チャット」と「コンテンツ」の2つのセグメントでページをコーディングしようとしています。 1つの「チャット」でページを自動スクロールして、効果なしで下にスクロールするようにします。チャットは<ion-list>
いくつかの<ion-item>
。
<ion-list>
<ion-item> item 1 </ion-item>
<ion-item> item 2 </ion-item>
....
<ion-item> item 20 </ion-item>
<ion-item> item 21 </ion-item> <!-- user should see directly this item on bottom of the page -->
</ion-list>
TypeScriptではなくJavascriptを使用していますが、jQueryを使用したくありません。ありがとう:)さらに、「コンテンツ」セグメントに移動して「チャット」に戻ると、チャットを再度自動スクロールしたいと思います。
まず第一に、@ rinukkusuの答えは正しいですが、<ion-content>
(<ion-list>
の親)にはいくつかのバグがあるため(私の場合は動作しません)(イオン開発者が作業中です)、その要素にscroll:hidden
を追加し、内部に2番目のコンテンツを作成して自動スクロールを適用します。最後に、適切な(s)cssを使用して、ページが読み込まれ、ユーザーが「チャット」セグメントをクリックするたびに、construtor
で関数を呼び出しました。
chat.html
<!-- I create the segment and call the `autoScroll()` when users clicks on "chat" -->
<ion-toolbar primary class="toolbar-segment">
<ion-segment light [(ngModel)]="segment">
<ion-segment-button value="chat" (click)="autoScroll()">
Chat
</ion-segment-button>
<ion-segment-button value="profile">
Profile
</ion-segment-button>
</ion-segment>
</ion-toolbar>
<!--I wrote the css inline just as example.
DON'T do it on your project D: -->
<!-- overflow:hidden prevent the ion-content to scroll -->
<ion-content [ngSwitch]="segment" style="overflow: hidden;">
<!-- height: 100% to force scroll if the content overflows the container.
#chat-autoscroll is used by javascript.-->
<div class="content-scroll" id="chat-autoscroll" *ngSwitchWhen="'chat'" style="height: 100%; overflow: scroll">
(... make sure the content is bigger
than the container to see the auto scroll effect ...)
</div>
<!-- here it's just a normal scroll -->
<div *ngSwitchWhen="'profile'" class="content-scroll" style="height: 100%; overflow: auto">
(... content of profile segment ...)
</div>
</ion-content>
chat.js
constructor () {
// when the user opens the page, it shows the "chat" segment as initial value
this.segment = 'chat';
// when page loads, it calls autoScroll();
if (this.segment == 'chat') {
console.log('chat');
this.autoScroll();
};
}
/*Here comes the tricky.
If you don't use setTimeout, the console will say that
#chat-autoscroll doesn't exist in the first call (inside constructor).
This happens because the script runs before the DOM is ready.
I did a workaround with a timeOut of 10ms.
It's enough time to DOM loads and then autoScroll() works fine.
*/
autoScroll() {
setTimeout(function () {
var itemList = document.getElementById("chat-autoscroll");
itemList.scrollTop = itemList.scrollHeight;
}, 10);
}
結論:関数は2回呼び出されます。ページが読み込まれたとき(コンストラクター)、ユーザーが「チャット」セグメントに戻るたびに。 (クリック)= "autoScroll()"
これが誰かの助けになることを願っています。より良い方法を知っているなら、私に知らせてください!私は数週間前にAngular2とIonic2で遊んでいたので、ここでは見逃しているかもしれないコンセプト/ベースがたくさんあります。
ありがとう:)
以下がその方法です。
chatPage.html
<ion-content #content padding class="chatPage">
<ion-list no-lines>
<ion-item *ngFor="let msg of messages" >
<chat-bubble [message]="msg"></chat-bubble>
</ion-item>
</ion-list>
</ion-content>
chatPage.htmlの重要なビットは、#content
on <ion-content>
です。 ViewChild
を使用してchatPage.jsで#content
識別子を使用して<ion-content>
への参照を取得します。
実際のスクロールロジックの場合:
chatPage.js
import {Component, ViewChild} from '@angular/core';
@Component({
templateUrl: 'build/pages/chatPage/chatPage.html',
queries: {
content: new ViewChild('content')
}
})
export class ChatPage {
constructor() {
}
//scrolls to bottom whenever the page has loaded
ionViewDidEnter(){
this.content.scrollToBottom(300);//300ms animation speed
}
}
また、私のchatPageがリストに別のチャットメッセージを表示する必要がある場合(新しいメッセージを受信するか、新しいメッセージを送信する場合)は、次のコードを使用して新しい下までスクロールします。
setTimeout(() => {
this.content.scrollToBottom(300);//300ms animation speed
});
TypeScriptの更新
この答えを返したとき、JavaScriptバージョンのIonic 2プロジェクトで作業していました。TypeScriptに切り替えましたが、答えを更新するのを忘れていたので、ここでchatPage.js(ts):
chatPage.ts
import {Component, ViewChild} from '@angular/core';
@Component({
templateUrl: 'chatPage.html'
})
export class ChatPage {
@ViewChild('content') content:any;
constructor() { }
//scrolls to bottom whenever the page has loaded
ionViewDidEnter(){
this.content.scrollToBottom(300);//300ms animation speed
}
}
Ionicにはこれを行うオプションがあり、かなりうまく機能します。そして、これはangular 2+およびIonicで最も適切な方法です。
import {Content} from 'ionic-angular'; export class CommentsPage { @ ViewChild(Content)content:Content; ionViewWillEnter():void { this.scrollToBottom(); } scrollToBottom(){ setTimeout(() => { this.content.scrollToBottom(); }); } }
これは誰かを助けるかもしれません、私は同様の答えを与えました in Ionic forum 。これはIonic 3。
この機能を実現するためにngAfterViewChecked()
を使用しました。以下は私のコード構造です-
home.html-
<ion-content padding>
<div #scrollMe id="messages-container" style="overflow: auto; height: 100%;">
// All messages elemets. Scroll
</div>
</ion-content>
home.ts-
import { Component,ViewChild, AfterViewChecked, * * } from '@angular/core';
.
.
export class HomePage implements AfterViewChecked{
// used for scrolling the pane
@ViewChild('scrollMe') private myScrollContainer: ElementRef;
ngAfterViewChecked() {
this.scrollToBottom();
}
scrollToBottom(): void {
// method used to enable scrolling
this.myScrollContainer.nativeElement.scrollTop = this.myScrollContainer.nativeElement.scrollHeight;
}
}
.scrollTop
および.scrollHeight
はJavaScriptプロパティ、 こちらを参照 です。
別の解決策は、スクロールビューの変更を「観察」し、自動的にスクロールすることです。つまり、メッセージが表示される新しいHTML要素がある場合は、一番下までスクロールします。
export class MessagesPage implements OnInit, OnDestroy {
autoScroller: MutationObserver;
ngOnInit() {
this.autoScroller = this.autoScroll();
}
ngOnDestroy() {
this.autoScroller.disconnect();
}
autoScroll(): MutationObserver {
const autoScroller = new MutationObserver(this.scrollDown.bind(this));
autoScroller.observe(this.messagesList, {
childList: true,
subtree: true
});
return autoScroller;
}
scrollDown(): void {
this.scroller.scrollTop = this.scroller.scrollHeight;
this.messageEditor.focus();
}
private get messageEditor(): HTMLInputElement {
return <HTMLInputElement>document.querySelector('ion-input');
}
private get messagesList(): Element {
return document.querySelector('.messages');
}
private get scroller(): Element {
return this.messagesList.querySelector('.scroll-content');
}
}
テンプレート:
<ion-content>
<ion-scroll scrollY="true" class="messages">
<ion-list>
<div *ngFor="let message of messages">
<p [innerHtml]="message.text"></p>
</div>
</ion-list>
</ion-scroll>
</ion-content>
<ion-footer>
<ion-toolbar>
<ion-input [(ngModel)]="message" type="text" placeholder="Write a message..." autocomplete="true" spellcheck="true" tappable></ion-input>
<ion-buttons end>
<button ion-button icon-only (click)="sendMessage()">
<ion-icon name="paper-plane"></ion-icon>
</button>
</ion-buttons>
</ion-toolbar>
</ion-footer>
(Githubの Ionic2CLI-Meteor-WhatsAppから取得します )
ユーザーが上にスクロールしようとしたかどうかを確認するチェックを追加しました。
<div style="overflow: scroll; height: xyz;" #scrollMe [scrollTop]="scrollMe.scrollHeight">
<div class="..."
*ngFor="..."
...>
</div>
</div>