代码之家  ›  专栏  ›  技术社区  ›  Rizan Zaky

PageControl触发的iOS CollectionView的SetContentOffset上的自定义动画不平滑

  •  0
  • Rizan Zaky  · 技术社区  · 7 年前

    我有一个xamarin.ios项目。我使用的是启用了分页的uicollectionview。然后有一个uipagecontrol与uicollectionview同步。

    需要两个功能,

    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);
              });
      }
      

      我不能用动画true调用setContentOffset,

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

      因为我需要 CollectionSource.DecelerationEnded(CollectionView); 在通过setContentOffset方法定位页面之后。

      问题是 ,当我使用此自定义动画时,CollectionView未正确设置动画,

      enter image description here

    我怎样才能克服这一点?

    1 回复  |  直到 7 年前
        1
  •  0
  •   Rizan Zaky    7 年前

    uicollectionview如何在 分页 启用。

    整页宽度 ( 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);
    

    这个 - 1 在里面 CardCollectionView.Frame.Width - 1 就是所谓的解决办法。

    然后你必须在动画之后处理这个减少。也就是说,在上面的uiview.animate代码中,回调函数应该有一个额外的行,

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

    然后 uiview.动画 看起来像,

    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);
        });
    

    现在自定义动画可以非常平滑地工作了