首页 > 解决方案 > 由 PageControl 触发的 IO 的 SetContentOffset 上的自定义动画 CollectionView 不流畅

问题描述

我有一个 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);
    

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

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

    在此处输入图像描述

我该如何克服呢?

标签: iosxamarin.iosuicollectionviewuiviewanimationuipagecontrol

解决方案


在启用分页时,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);

那么它就不会像使用自定义动画那样制作动画了。

解决方案:

您不应该为整个页面宽度滚动距离自定义动画,而是应该将滚动距离从full page width 减少1 个像素 (选择 1 个像素以使其不那么显着,任何其他数量也可以)。那是,

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

-1 inCardCollectionView.Frame.Width - 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);
    });

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


推荐阅读