简体   繁体   中英

DidFinishAnimating and WillTransition for UIPageViewController, how do I properly implement these methods?

I am having an issue with my UIPageViewControllerDelegate methods. It doesn't track the pages properly when the user swipes in one direction, doesn't complete that swipe and swipes back to the first page.

Ex.

  1. I'm on page 1 and I swipe from right to left
  2. As I swipe, I see page 2. But, I stop swiping in that direction and swipe left to right (without lifting the finger) before the 'page 1 to page 2' transition completes.
  3. Now I'm on page 1 but everything I see lines up with page 2.

Here is how I implement these methods:

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

The 'PageSwiped' action is fired to allow other classes to know that the page was swiped.

I have tried replacing:

if (completed)

with

if (finished)

and had the exact same issue.

So there has to be something I'm doing wrong in these two methods, any suggestions?

When using UIPageViewController you don't need to implement those methods to navigate between pages (ViewControllers).

You should either implement the IUIPageViewControllerDataSource interface right in the UIPageViewController and set your datasource as this or subclass UIPageViewControllerDataSource and set the datasource as the object created.

In either case you will be implementing/overriding these two methods

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

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

These are the methods which returns the Page (UIViewController) that will be displayed.

Here you just find what it's the index of the control currently on screen and get the next or previous and return that item from the collection.

Getting the Next ViewController:

UIViewController IUIPageViewControllerDataSource.GetNextViewController(UIPageViewController pageViewController, UIViewController referenceViewController)
{
    var index = MyViewControllers.IndexOf(referenceViewController);

    var nextIndex = index + 1;

    return MyViewControllers.ElementAtOrDefault(nextIndex);
}

Getting the previous ViewController:

UIViewController IUIPageViewControllerDataSource.GetPreviousViewController(UIPageViewController pageViewController, UIViewController referenceViewController)
{
    var index = MyViewControllers.IndexOf(referenceViewController);

    var previousIndex = index - 1;

    return MyViewControllers.ElementAtOrDefault(previousIndex);
}

The difference is that these methods are called only when the transition has successfully completed.

Here's the full code:

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

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM