ios - 由 PageControl 触发的 IO 的 SetContentOffset 上的自定义动画 CollectionView 不流畅
问题描述
我有一个 Xamarin.IOs 项目。我正在使用启用了分页的 UICollectionView。然后是一个与 UICollectionView 同步的 UIPageControl。
需要两个功能,
在滑动 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 }
工作正常!
在点击 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 的动画不正确,
我该如何克服呢?
解决方案
在启用分页时,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);
});
现在自定义动画会非常流畅
推荐阅读
- vue.js - 模板内的Vue for循环
- ruby-on-rails - SAAS 应用架构微服务 vs 单体
- sql - SQL中按组连续出现的值的最大次数
- android - 阻止我的应用程序复制 textview 的文本
- android - Android viewpager 滞后于 recyclerviews
- java - 我不明白为什么我的计算不起作用
- python - 将带有参数的 Python 装饰器合并为一个
- mysql - 如何在mysql中执行全文搜索
- javascript - Passport-ldapauth:缺少凭据
- javascript - 使用 jQquery 或 JavaScript 对嵌套的 html 元素进行排序