rintoj / ngx-virtual-scroller

Virtual Scroll displays a virtual, "infinite" list.
https://rintoj.github.io/ngx-virtual-scroller
MIT License
977 stars 294 forks source link

Scolling is Jittery in iOS #351

Open jsBiztech opened 5 years ago

jsBiztech commented 5 years ago

I am using this virtual scroll to display data with lazy loading in Ionic 3. It is working fine with browser and android app but in iOS sometimes the scrolling becomes jittery because of some reasons, which I was unable to find. Here are the details:

Ionic:
   Ionic CLI          : 5.2.1
   Ionic Framework    : ionic-angular 3.9.2
   @ionic/app-scripts : 3.2.1

Cordova:
   Cordova CLI       : 7.1.0
   Cordova Platforms : android 6.3.0
   Cordova Plugins   : cordova-plugin-ionic-keyboard 2.1.3, cordova-plugin-ionic-webview 4.0.1, (and 21 other plugins)

Utility:
   cordova-res : not installed
   native-run  : not installed

System:
   NodeJS : v10.15.3
   npm    : 6.4.1
   OS     : Linux 4.18

Package Version: 
  angular2-virtual-scroll: ^0.4.9,

Template Structure:

<ion-content no-bounce>
    <div [ngClass]="isPlatformBrowser == true ? 'page-wrapper':'mobile-wrapper'">
        <div class="library-wrapper" [class.no-data]="searchRelateData?.length == 0"
                [ngClass]="isPlatformBrowser == true ? 'lg-wrapper-main':'sm-wrapper-main'">
            <ng-template [ngIf]="!listprogress" [ngIfElse]="loadingTemplate">
                <ng-container>
                    <ion-content no-padding no-bounce *ngIf="!isPlatformBrowser">
                        <div class="scroll">
                            <virtual-scroll id="library-vs" [class.no-data]='!filteredListing?.length' (scroll)="onListChange($event)" [items]="filteredListing"
                                (update)="viewPortItems = $event" [childHeight]="6" [bufferAmount]="limit">
                                <div class="item text-elipsis" *ngFor="let item of filteredListing | customFilterPipe">
                                    <custom-component></custom-component>
                                </div>
                                <div *ngIf="listLoading" class="loader">LOADING...</div>
                            </virtual-scroll>
                        </div>
                    </ion-content>
                </ng-container>
            </ng-template>
        </div>
    </div>
</ion-content>
luqmaants commented 5 years ago

I was having the same issue. I found that using <li> works best, instead of using div or <ion-item>.

jsBiztech commented 5 years ago

Thanks for the reply @luqmaants .Did you used <li> inside <virtual-scroll>. Also I am facing this issue in iOS only, Do you think this will resolve the issue?

lincolnthree commented 5 years ago

Same issue here. @luqmaants and @nagdevbharat did this help you? It doesn't seem to make a difference for me.

jsBiztech commented 4 years ago

@lincolnthree , the issue still persists. Have you found any solution for this?

lincolnthree commented 4 years ago

Negative. No ideas here. I'm not very practiced with animations/etc. I try to avoid that level of UI unless absolutely necessary. I tried replacing with ion-virtual-scroll, but that component has even more issues. Just suffering through the jitter at the moment.

ambu50 commented 4 years ago

I was having the same issue, solved it by installing WKWebView. ionic cordova plugin add cordova-plugin-ionic-webview --save

jsBiztech commented 4 years ago

@ambu50 , I have webview installed: ionic-native/ionic-webview: ^5.6.1 and the issue still persists

IfreannMedia commented 4 years ago

@nagdevbharat @lincolnthree I Just implemented a solution for my use case, here's what it looks like:

` <virtual-scroller #scroll [items]="arrayOfItems"" [executeRefreshOutsideAngularZone]="executeRefreshOutsideAngular" (vsStart)="vsStartUpdate($event)">

CONTENT
</virtual-scroller>`

And in the typescript file:

`public executeRefreshOutsideAngular: boolean = false;

public vsStartUpdate(event: IPageInfo) { if(!this.arrayOfItems) return; this.toggleChangeDetectionOfVirtualScroller(event); }

private toggleChangeDetectionOfVirtualScroller(event: IPageInfo){ if(event.endIndex >= this.arrayOfItems.length-1){ // we are at the bottom of the list // executeRefreshOutsideAngularZone IF the user is not scrolling up // if (event.scrollStartPosition <= event.scrollEndPosition) // means we are scrolling upwards, and wa want to set the boolean to false, otherwise true // this.executeRefreshOutsideAngular = event.scrollStartPosition <= event.scrollEndPosition; } else { this.executeRefreshOutsideAngular = false; this.forceDetectChanges(); } }

public forceDetectChanges() { this.changeDetectorRef.detectChanges(); }`

Basically I check if the last item in the viewport is the last item in the list of items. If it is, and if the user is not scrolling back up, i set executeRefreshOutsideAngularZone to true, otherwise false. when setting the executeRefreshOutsideAngularZone back to false, I also force change detection because otherwise it was being a bit buggy

jsBiztech commented 4 years ago

Hi @IfreannMedia , Sorry for the late reply. I tried the code and it doesn't seem to be working in my project. Can you please provide more details on what happens when change detection is called? Thanks

felixble commented 4 years ago

I tried the solution of @IfreannMedia, too. Unfortunately, this didn't solve the issue for me. It looks as if it makes it even worse 😕

julianpoy commented 4 years ago

Can confirm this. Happens in any browser in IOS