I'm experiencing some very odd behavior when using UIPageViewController in my app. On the first swipe to the next view or anytime the direction of swiping changes (i.e. at the end of the list and going back), the resulting view is blank and I am required to swipe the same direction again for the appropriate view to show.
Example workflow with 3 views:
I noticed via logging when the blinking happens (2 & 3 above), the sequence of events is as follows:
Then when I swipe again GetNextViewController is appropriately called and the view is shown.
My problem is, obviously, the second view should show without the blinking in and out. I have tried various things but nothing fruitful.
UPDATE
Here is a sample single-controller app that reproduces the problem:
using System;
using System.Drawing;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System.Collections.Generic;
namespace TestPageView
{
public partial class TestPageViewViewController : UIViewController
{
public TestPageViewViewController () : base ("TestPageViewViewController", null)
{
}
public override void DidReceiveMemoryWarning ()
{
// Releases the view if it doesn't have a superview.
base.DidReceiveMemoryWarning ();
// Release any cached data, images, etc that aren't in use.
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
var controllers = new List<UIViewController>
{
new TestViewController(View, 1),
new TestViewController(View, 2),
new TestViewController(View, 3),
new TestViewController(View, 4)
};
var _pageViewController = new UIPageViewController(UIPageViewControllerTransitionStyle.Scroll, UIPageViewControllerNavigationOrientation.Horizontal);
var dataSource = new ViewDataSource(controllers);
_pageViewController.DataSource = dataSource;
//ViewDataSource has an indexer that returns it's controllers
_pageViewController.SetViewControllers(new[] { controllers[0] }, UIPageViewControllerNavigationDirection.Forward, false, null);
View.AddSubview(_pageViewController.View);
}
public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
{
// Return true for supported orientations
return (toInterfaceOrientation != UIInterfaceOrientation.PortraitUpsideDown);
}
}
public class TestViewController : UIViewController
{
private readonly UIView _parent;
private readonly int _number;
public TestViewController(UIView parent, int number)
{
_parent = parent;
_number = number;
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
var textView = new UITextView(_parent.Bounds);
textView.TextAlignment = UITextAlignment.Center;
textView.AttributedText = new NSAttributedString(_number.ToString(), UIFont.BoldSystemFontOfSize(18));
View.Add(textView);
}
}
public class ViewDataSource : UIPageViewControllerDataSource
{
private LinkedListNode<UIViewController> current;
public ViewDataSource(IEnumerable<UIViewController> controllers)
{
var controllerLiist = new LinkedList<UIViewController>(controllers);
current = controllerLiist.First;
}
public override UIViewController GetPreviousViewController(UIPageViewController pageViewController, UIViewController referenceViewController)
{
if(current.Previous == null){
Console.WriteLine("returning previous nothing");
return null;
}
Console.WriteLine("returning previous something");
current = current.Previous;
return current.Value;
}
public override UIViewController GetNextViewController(UIPageViewController pageViewController, UIViewController referenceViewController)
{
if(current.Next == null){
Console.WriteLine("returning next nothing");
return null;
}
Console.WriteLine("returning next something");
current = current.Next;
return current.Value;
}
}
}
iOS will call GetPreviousViewController and GetNextViewController twice: first for current controller and second for backflip of current controller.
You should do that
current = current.Previous;
only at first call.
Check referenceViewController to do that:
public override UIViewController GetPreviousViewController (UIPageViewController pageViewController, UIViewController referenceViewController)
{
var __c = Pages.Find(referenceViewController);
if (__c.Previous != null)
return __c.Previous.Value;
else
return null;
}
public override UIViewController GetNextViewController (UIPageViewController pageViewController, UIViewController referenceViewController)
{
var __c = Pages.Find(referenceViewController);
if (__c.Next != null)
return __c.Next.Value;
else
return null;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With