Я создаю простое приложение для чата, и у меня возникла проблема с настройкой положения прокрутки в iOS. Кажется, он отлично работает на других платформах, включая браузер. Ioni c v5, с использованием Capacitor, сборка с Appflow.
Контейнер должен быть прокручен по умолчанию при загрузке данных. Затем страница прослушивает новые сообщения. Если добавляется новое сообщение, то страница должна прокручиваться вниз, если позиция прокрутки находится в пределах нижних 150% высоты клиента. Если нет, появляется FAB, указывающий, что появилось новое сообщение, и пользователь может выбрать кнопку для прокрутки до кнопки.
Разметка такая же. У меня есть специальная директива domChange, которая прослушивает изменения dom в div. Я предпочитаю размещать логи прокрутки c здесь, так как я испытывал ошибки, помещая его в прослушиватель сообщений ранее.
<ion-content>
<div class="chat-container" (click)="containerClick();" (scroll)="scroll($event)" #chatContainer>
<div class="wrapper" *ngIf="messages.length > 0" (domChange)="onDomChange($event)">
<!-- Excuse my inline styling, this is just for debug -->
<div style="width:100%;text-align:center;padding:20px;" *ngIf="loadingMore"><ion-spinner></ion-spinner></div>
<ng-container *ngFor="let message of messages">
<chat-bubble
[sent]="message.from === authService.user.id"
[delivered]="message.delivered"
[position]="message.position"
[timestamp]="message.createdAt.getTime()"
[content]="message.content"
>
</chat-bubble>
</ng-container>
</div>
</div>
<ion-fab vertical="bottom" horizontal="center" slot="fixed" *ngIf="showScrollBtn">
<ion-fab-button size="small" (click)="scrollToBottom()"><ion-icon name="arrow-down-outline"></ion-icon></ion-fab-button>
</ion-fab>
</ion-content>
CSS относительно прост, но я использую flexbox с обратным столбцом и Я думаю, что это может быть одной из причин этой проблемы. Обратный столбец означает, что веб-просмотр по умолчанию отображает прокрутку внизу.
.chat-container {
height: 100%;
flex-grow: 1;
overflow: auto;
display: flex;
flex-direction: column-reverse;
overflow-x: hidden;
padding: 0 16px 0 16px;
}
А затем соответствующие функции:
public onDomChange(event: any) {
if(event.addedNodes.length > 0 && event.addedNodes[0].localName == 'chat-bubble') {
const scrollTop = (this.platform.is('ios') && !this.platform.is('mobileweb')) ? this.chatContainer.nativeElement.scrollTop + this.chatContainer.nativeElement.scrollHeight : this.chatContainer.nativeElement.scrollTop;
/*
* Because of the column-reverse iOS sees the bottom of the div as scrollTop = 0 and the top of the div as scrollTop = -scrollHeight
* Android sees it as scrollTop = scrollHeight at the bottom and scrollTop = 0 at the top
*/
const scrollHeight = this.chatContainer.nativeElement.scrollHeight;
const clientHeight = this.chatContainer.nativeElement.clientHeight * 1.5;
const newMessageIndex = this.messages[this.messages.length - 1].index;
if((this.messages.length <= 30 || scrollHeight - scrollTop <= clientHeight) && this.channel.lastConsumedMessageIndex < newMessageIndex) {
this.scrollToBottom();
} else if(this.channel.lastConsumedMessageIndex < newMessageIndex) {
this.showScrollBtn = true;
}
}
}
public scrollToBottom(): Promise<any> {
this.showScrollBtn = false;
this.chatContainer.nativeElement.scrollTop = this.chatContainer.nativeElement.scrollHeight;
return this.channel.setAllMessagesConsumed();
}
Функция scrollToBottom()
работает абсолютно нормально, когда запускается событием нажатия кнопки, но, похоже, ничего не делает, когда срабатывает в триггере domChange. Я думаю, это потому, что триггер вызывается до того, как элемент пузыря чата рендерится, но я не уверен, как это исправить.
Буду признателен за любые идеи / мысли
Заранее спасибо