PageControl 触发的 IOs CollectionView 的 SetContentOffset 自定义动画不流畅

Custom animation on SetContentOffset for IOs CollectionView triggered by PageControl is not smooth

我有一个 Xamarin.IOs 项目。我正在使用启用了分页的 UICollectionView。然后是与 UICollectionView 同步的 UIPageControl。

需要两个功能,

  1. 滑动UICollectionView时,CollectionView的当前页面会发生变化,UIPageControl的当前指示器也会同步变化

    实施:

    在 UICollectionViewSource 中,

    public override void DecelerationEnded(UIScrollView scrollView)
    {
        Index = (int)(scrollView.ContentOffset.X / scrollView.Frame.Width);
        PageControl.CurrentPage = Index;
        CardSwiped?.Invoke(this, new CustomEventArgs(Index));
    }
    

    在相关ViewController,

    private void SomeMethod()
    {
        CollectionSource.CardSwiped += OnCardSwiped;
    }
    
    private void OnCardSwiped(object sender, CustomEventArgs args)
    {
        // Perform some action
    }
    

    工作正常!

  2. 点击UIPageControl时,CollectionView当前页面会随着点击而变化,UIPageControl的当前指示器也会同步变化。

    实施:

    在相关ViewController,

    private void SomeMethod()
    {
        PageControl.PrimaryActionTriggered += OnPageControlTapped;
    }
    
    private void OnPageControlTapped(object sender, EventArgs args)
    {
        // Some action
    
        var pageControlIndex = CardPageControl.CurrentPage;
        var sourceIndex = CollectionSource.Index;
        var distanceToScroll = CardCollectionView.Frame.Width * (pageControlIndex - sourceIndex);
    
        UIView.Animate(0.5, 0, UIViewAnimationOptions.TransitionNone,
            () =>
            {
                CollectionView.SetContentOffset(
                    new CGPoint(CollectionView.ContentOffset.X + distanceToScroll, CollectionView.ContentOffset.Y),
                    false);
            },
            () =>
            {
                CollectionSource.DecelerationEnded(CollectionView);
            });
    }
    

    我无法在动画为真时调用 SetContentOffset,

    CollectionView.SetContentOffset(new CGPoint(CollectionView.ContentOffset.X + y, CollectionView.ContentOffset.Y), true);
    

    因为我需要在 SetContentOffset 方法定位页面后调用 CollectionSource.DecelerationEnded(CollectionView);

    问题是,当我使用这个自定义动画时,CollectionView 的动画效果不正确,

我该如何克服这个问题?

启用 Paging 时,UICollectionView 如何使用自定义动画滚动 SetContentOffset 似乎存在一些问题。

当以整页宽度(CardCollectionView.Frame.Width)为滚动距离时,

var distanceToScroll = CardCollectionView.Frame.Width * (pageControlIndex - sourceIndex);

并在 SetContentOffset 中使用,

CollectionView.SetContentOffset(
            new CGPoint(CollectionView.ContentOffset.X + distanceToScroll, CollectionView.ContentOffset.Y),
            false);

那么它就不会像使用自定义动画那样设置动画。

解决方案:

您不应为 整页宽度 滚动距离自定义动画,而应将滚动距离减少 1 像素 (选择 1 个像素以使其不那么引人注目,任何其他数量也可以) 来自 整页宽度 。也就是说,

var distanceToScroll = (CardCollectionView.Frame.Width - 1) * (pageControlIndex - sourceIndex);

CardCollectionView.Frame.Width - 1 中的 -1 就是所谓的解决方法。

然后你必须在动画之后解决这个减少问题。即在上面的UIView.Animate代码中,回调函数要多出一行,

CardCollectionView.SetContentOffset(
    new CGPoint(CardCollectionView.ContentOffset.X + (pageControlIndex - sourceIndex), CardCollectionView.ContentOffset.Y), 
    false);

那么 UIView.Animate 看起来像,

UIView.Animate(0.5, 0, UIViewAnimationOptions.TransitionNone,
    () =>
    {
        CollectionView.SetContentOffset(
            new CGPoint(CollectionView.ContentOffset.X + distanceToScroll, CollectionView.ContentOffset.Y),
            false);
    },
    () =>
    {
        CardCollectionView.SetContentOffset(
            new CGPoint(CardCollectionView.ContentOffset.X + (pageControlIndex - sourceIndex), CardCollectionView.ContentOffset.Y), 
            false);
        CollectionSource.DecelerationEnded(CollectionView);
    });

现在自定义动画会非常流畅