【问题标题】:DidFinishAnimating and WillTransition for UIPageViewController, how do I properly implement these methods?UIPageViewController 的 DidFinishAnimating 和 WillTransition,如何正确实现这些方法?
【发布时间】:2017-06-14 19:09:25
【问题描述】:

我的 UIPageViewControllerDelegate 方法有问题。当用户向一个方向滑动时,它无法正确跟踪页面,没有完成该滑动并滑动回第一页。

例如

  1. 我在第 1 页,我从右向左滑动
  2. 当我滑动时,我看到了第 2 页。但是,在“第 1 页到第 2 页”转换完成之前,我停止向那个方向滑动并从左向右滑动(不抬起手指)。
  3. 现在我在第 1 页,但我看到的所有内容都与第 2 页对齐。

我是这样实现这些方法的:

public Action<int> PageSwiped { get; set; }

public override void WillTransition(
    UIPageViewController pageViewController, UIViewController[] pendingViewControllers)
{
    _currentController = pendingViewControllers[0] as AssetViewController;
}

public override void DidFinishAnimating(
    UIPageViewController pageViewController, bool finished,
    UIViewController[] previousViewControllers, bool completed)
{
    if (completed)
    {
        PageSwiped(_currentController.CurrentMedia.Content.ProofIndex);
    }
}

“PageSwiped”动作被触发以允许其他类知道页面已被刷过。

我已经尝试替换:

if (completed)

if (finished)

并且遇到了完全相同的问题。

所以这两种方法一定是我做错了什么,有什么建议吗?

【问题讨论】:

    标签: c# ios iphone xamarin uipageviewcontroller


    【解决方案1】:

    当使用UIPageViewController 时,您不需要实现这些方法来在页面之间导航(ViewControllers)。

    您应该直接在UIPageViewController 中实现IUIPageViewControllerDataSource 接口,并将您的数据源设置为this 或子类UIPageViewControllerDataSource,并将数据源设置为创建的对象。

    在任何一种情况下,您都将实现/覆盖这两种方法

    UIViewController IUIPageViewControllerDataSource.GetNextViewController(UIPageViewController pageViewController, UIViewController referenceViewController)
    {
    }
    
    UIViewController IUIPageViewControllerDataSource.GetPreviousViewController(UIPageViewController pageViewController, UIViewController referenceViewController)
    {
    }
    

    这些是返回将要显示的页面(UIViewController)的方法。

    在这里,您只需找到当前屏幕上控件的索引,然后获取下一个或上一个,然后从集合中返回该项目。

    获取下一个 ViewController:

    UIViewController IUIPageViewControllerDataSource.GetNextViewController(UIPageViewController pageViewController, UIViewController referenceViewController)
    {
        var index = MyViewControllers.IndexOf(referenceViewController);
    
        var nextIndex = index + 1;
    
        return MyViewControllers.ElementAtOrDefault(nextIndex);
    }
    

    获取之前的 ViewController:

    UIViewController IUIPageViewControllerDataSource.GetPreviousViewController(UIPageViewController pageViewController, UIViewController referenceViewController)
    {
        var index = MyViewControllers.IndexOf(referenceViewController);
    
        var previousIndex = index - 1;
    
        return MyViewControllers.ElementAtOrDefault(previousIndex);
    }
    

    不同之处在于这些方法仅在转换成功完成时才被调用。

    这是完整的代码:

    public partial class MyPageViewController : UIPageViewController, IUIPageViewControllerDataSource
    {
        List<UIViewController> MyViewControllers = new List<UIViewController>();
    
        public MyPageViewController (IntPtr handle) : base (handle)
        {
    
        }
    
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
    
            var redViewController = UIStoryboard.FromName("Main", null).InstantiateViewController("redViewController");
            var greenViewController = UIStoryboard.FromName("Main", null).InstantiateViewController("greenViewController");
            var blueViewController = UIStoryboard.FromName("Main", null).InstantiateViewController("blueViewController");
    
            MyViewControllers.Add(redViewController);
            MyViewControllers.Add(greenViewController);
            MyViewControllers.Add(blueViewController);
    
            DataSource = this;
    
            SetViewControllers(new UIViewController[] { MyViewControllers.First() }, UIPageViewControllerNavigationDirection.Forward, true, null);
    
        }
    
        public override void ViewWillAppear(bool animated)
        {
            base.ViewWillAppear(animated);
        }
    
        UIViewController IUIPageViewControllerDataSource.GetNextViewController(UIPageViewController pageViewController, UIViewController referenceViewController)
        {
            var index = MyViewControllers.IndexOf(referenceViewController);
    
            var nextIndex = index + 1;
    
            return MyViewControllers.ElementAtOrDefault(nextIndex);
        }
    
        UIViewController IUIPageViewControllerDataSource.GetPreviousViewController(UIPageViewController pageViewController, UIViewController referenceViewController)
        {
            var index = MyViewControllers.IndexOf(referenceViewController);
    
            var previousIndex = index - 1;
    
            return MyViewControllers.ElementAtOrDefault(previousIndex);
        }
    }
    

    希望这会有所帮助!

    【讨论】:

    • 这绝对有帮助,谢谢!但这是我现在遇到的问题;我需要能够准确地知道滑动发生和完成的时间,以便能够更新新可见控制器周围的数据。在这种情况下,每个控制器都包含一些媒体,这些媒体可以让 cmets 与该媒体相关联。因此,当寻呼机中可见新控制器时,我需要能够更新 cmets 列表。有了这个实现,GetNext/PreviousViewController 方法的触发方式使得很难知道转换何时完成与转换何时......
    • 开始然后取消(向一个方向滑动一半然后再返回)。
    • 我试图解决的问题是当用户执行半滑动时,cmets 并不总是正确地排列到可见媒体(转换被取消,即在 DidFinishAnimating 中,finished = true,完成=假)
    • @kformeck 如果您需要在出现时更新 ViewController 的状态,为什么不在 ViewController ViewWillAppear 方法上更新它?每次用户滑入 ViewController 时,都会在每个 ViewController 上调用此方法。
    • 太完美了!在 ViewWillAppear 中执行所有视图更新逻辑就是这样做的方法。谢谢,既然一切正常,我将接受您的回答。
    猜你喜欢
    • 1970-01-01
    • 2012-11-11
    • 1970-01-01
    • 2019-09-01
    • 1970-01-01
    • 2020-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多