Search code examples
iosxamarinxamarin.formsxamarin.iosuiwebview

UICollectionView initial lag with PagingEnabled = true


There are my case :

  • Using UICollectionView with UICollectionViewFlowLayout to display many WebView
    • PagingEnabled = true
    • Working same as Carousel View control

Problem is :

  • WebView take a little time from initial loading. First webview loading is okay. But i swipe to left or right, it will display a blank page before fully loading.

=> Expected: I don't want it display blank page on that moment.

This is my code :

public class CarouselWebTouch
    : UIView,
    IUICollectionViewSource,
    IUICollectionViewDelegateFlowLayout,
    ICarouselWebTouch
{
    const string DAY_CELL_ID = "webCellId";

    IList<PageItem> Pages = new List<PageItem>();
    UICollectionView CollectionView;
    Dictionary<int, CarouselWebCell> CacheWebCell = new Dictionary<int, CarouselWebCell>();

    ...

    public CarouselWebTouch()
    {
        var layout = new UICollectionViewFlowLayout();
        layout.MinimumLineSpacing = 0;
        layout.MinimumInteritemSpacing = 0;
        layout.ScrollDirection = UICollectionViewScrollDirection.Horizontal;
        layout.SectionInset = UIEdgeInsets.Zero;
        layout.HeaderReferenceSize = CGSize.Empty;
        layout.FooterReferenceSize = CGSize.Empty;

        CollectionView = new UICollectionView(CGRect.Empty, layout);
        CollectionView.AllowsSelection = true;
        CollectionView.BackgroundColor = UIColor.Clear;
        CollectionView.PagingEnabled = true;
        CollectionView.Delegate = this;
        CollectionView.DataSource = this;
        CollectionView.ShowsHorizontalScrollIndicator = false;
        CollectionView.RegisterClassForCell(typeof(CarouselWebCell), DAY_CELL_ID);
        Add(CollectionView);
    }

    public UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
    {
        var reusableCell = (CarouselWebCell)collectionView.DequeueReusableCell(DAY_CELL_ID, indexPath);
        return reusableCell;
    }
}

Function GetCell called in first initial loading for section 0. I want to generate cell of previous and next of it. (Mean section 1 too).

Does any way to force it generate number of cell in initial loading phrase ?


Solution

  • UICollectionViewDataSourcePrefetching

    A protocol that provides advance warning of the data requirements for a collection view, allowing the triggering of asynchronous data load operations.

    You can implement the IUICollectionViewDataSourcePrefetching interface on an existing NSObject-based class (I do it on my collection view data source) and assign it to the PrefetchDataSource property:

    CollectionView.PrefetchDataSource = this;
    CollectionView.PrefetchingEnabled = true; 
    

    Note: It is not required to set PrefetchingEnabled to true if you are setting a PrefetchDataSource, but you can toggle it on/off it you need to turn prefetching off temporarily for a reason.

    You have one required method (PrefetchItems) and one optional (CancelPrefetching) and I HIGHLY recommend that you read the Apple documentation so you understand when these methods are called (they are not necessarily called for every cell)

    public void PrefetchItems(UICollectionView collectionView, NSIndexPath[] indexPaths)
    {
        foreach (var prefetch in indexPaths)
        {
            Console.WriteLine($"PreFetch {prefetch.LongRow}");
        }
    }
    
    [Export("collectionView:cancelPrefetchingForItemsAtIndexPaths:")]
    public void CancelPrefetching(UICollectionView collectionView, NSIndexPath[] indexPaths)
    {
        foreach (var prefetch in indexPaths)
        {
            Console.WriteLine($"Cancel PreFetch {prefetch.LongRow}");
        }
    }
    

    Note: Since CancelPrefetching is optional in the Xamarin/C# interface you need to Export it otherwise the UICollectionView is not going to see that it is implemented and not call it.

    Apple Doc: UICollectionViewDataSourcePrefetching