Skip to content

Instantly share code, notes, and snippets.

@alexrainman
Last active August 29, 2015 14:22
Show Gist options
  • Save alexrainman/df03bd8d03a21783237d to your computer and use it in GitHub Desktop.
Save alexrainman/df03bd8d03a21783237d to your computer and use it in GitHub Desktop.
Dynamic UIViewPageController for Xamarin iOS
using System;
using UIKit;
using System.Collections.Generic;
using CoreGraphics;
// ported from https://github.com/nsobadzhiev/DynamicPageViewController/blob/master/DynamicPageViewController/DMDynamicViewController.swift
namespace YourNamespace
{
/*protocol DMDynamicPageViewControllerDelegate {
func pageViewController(pageController: DMDynamicViewController, didSwitchToViewController viewController: UIViewController)
func pageViewController(pageController: DMDynamicViewController, didChangeViewControllers viewControllers: Array<UIViewController>)
}*/
public class DPageViewController: UIViewController, IUIScrollViewDelegate {
/*var delegate: DMDynamicPageViewControllerDelegate? = nil
func notifyDelegateDidSwitchPage() {
self.delegate?.pageViewController(self, didSwitchToViewController: self.viewControllers![self.currentPage])
}
func notifyDelegateDidChangeControllers() {
self.delegate?.pageViewController(self, didChangeViewControllers: self.viewControllers!)
}*/
UIScrollView containerScrollView;
nfloat pageWidth = 1f;
public List<UIViewController> ViewControllers;
int _currentPage;
public int CurrentPage {
get { return _currentPage; }
set {
_currentPage = value;
if (_currentPage >= ViewControllers.Count)
{
_currentPage = ViewControllers.Count - 1;
}
containerScrollView.Delegate = null;
containerScrollView.ContentOffset = new CGPoint ((nfloat)_currentPage * View.Bounds.Size.Width, 0.0);
containerScrollView.Delegate = this;
// Set the fully switched page in order to notify the delegates about it if needed.
FullySwitchedPage = CurrentPage;
}
}
int _fullySwitchedPage;
public int FullySwitchedPage {
get { return _fullySwitchedPage; }
set {
if (value != _fullySwitchedPage) {
// The page is fully switched.
if (_fullySwitchedPage < ViewControllers.Count) {
var previousViewController = ViewControllers[_fullySwitchedPage];
// Perform the "disappear" sequence of methods manually when the view of
// the controller is not visible at all.
previousViewController.WillMoveToParentViewController(this);
previousViewController.ViewWillDisappear (false);
previousViewController.ViewDidDisappear (false);
previousViewController.DidMoveToParentViewController (this);
previousViewController.WillMoveToParentViewController (this);
previousViewController.ViewWillAppear (false);
previousViewController.ViewDidAppear (false);
previousViewController.DidMoveToParentViewController (this);
}
}
_fullySwitchedPage = value;
}
}
public DPageViewController(List<UIViewController> viewControllers) {
//super.init(nibName: nil, bundle: nil)
ViewControllers = viewControllers;
//self.notifyDelegateDidChangeControllers()
}
/*init(viewControllers: Array<UIViewController>) {
super.init(nibName: nil, bundle: nil)
self.viewControllers = viewControllers
self.notifyDelegateDidChangeControllers()
}
required override init(nibName nibN ameOrNil: String!, bundle nibBundleOrNil: NSBundle!) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
required init(coder: NSCoder) {
super.init(coder: coder)
}*/
public override void ViewDidLoad() {
base.ViewDidLoad ();
containerScrollView = new UIScrollView (new CGRect(0, 44, View.Frame.Size.Width, View.Frame.Size.Height - 90)); //frame: self.view.bounds
containerScrollView.PagingEnabled = true;
containerScrollView.AlwaysBounceVertical = false;
containerScrollView.AlwaysBounceHorizontal = true; // drag with only one view controller
containerScrollView.ShowsHorizontalScrollIndicator = false;
containerScrollView.Delegate = this;
pageWidth = View.Frame.Size.Width;
View.AddSubview(containerScrollView);
LayoutPages();
}
public override void ViewDidLayoutSubviews() {
for (var i = 0; i < ViewControllers.Count; i += 1) {
var pageX = (nfloat)i * View.Bounds.Size.Width;
ViewControllers [i].View.Frame = new CGRect (pageX, 0.0, View.Bounds.Size.Width, View.Bounds.Size.Height);
}
// It is important to set the pageWidth property before the contentSize and contentOffset,
// in order to use the new width into scrollView delegate methods.
pageWidth = View.Bounds.Size.Width;
containerScrollView.ContentSize = new CGSize ((nfloat)ViewControllers.Count * View.Bounds.Size.Width, 1.0);
containerScrollView.ContentOffset = new CGPoint ((nfloat)CurrentPage * View.Bounds.Size.Width, 0.0);
}
public override void DidReceiveMemoryWarning() {
base.DidReceiveMemoryWarning ();
// Dispose of any resources that can be recreated.
}
void LayoutPages() {
foreach(var pageView in containerScrollView.Subviews) {
pageView.RemoveFromSuperview();
}
for (var i = 0; i < ViewControllers.Count; i++) {
var page = ViewControllers [i];
AddChildViewController(page);
var nextFrame = new CGRect ((nfloat)i * View.Bounds.Size.Width, View.Frame.Y, View.Frame.Size.Width, View.Frame.Size.Height); // Origin.Y
page.View.Frame = nextFrame;
containerScrollView.AddSubview (page.View);
page.DidMoveToParentViewController (this);
}
containerScrollView.ContentSize = new CGSize(View.Bounds.Size.Width * (nfloat)ViewControllers.Count, 1.0);
}
void WillMoveToParentViewController() {
var page = (int)((containerScrollView.ContentOffset.X - pageWidth / 2.0) / pageWidth) + 1;
if (CurrentPage != page)
{
CurrentPage = page;
//FullySwitchedPage = page;
}
}
public void InsertPage(UIViewController viewController, int index) {
ViewControllers.Insert(index, viewController);
LayoutPages();
CurrentPage = index;
//self.notifyDelegateDidChangeControllers()
}
public void RemovePage(UIViewController viewController) {
for (var i = 0; i < ViewControllers.Count; i += 1) {
if (ViewControllers[i] == viewController) {
ViewControllers.RemoveAt (i);
LayoutPages();
//self.notifyDelegateDidChangeControllers()
}
}
}
// MARK: UIScrollViewDelegate
[Foundation.Export ("scrollViewDidScroll:")]
public void Scrolled (UIScrollView scrollView)
{
// Update the page when more than 50% of the previous/next page is visible
var page = Math.Floor((containerScrollView.ContentOffset.X - pageWidth / 2) / pageWidth) + 1;
/*if (CurrentPage != (int)page) {
// Check the page to avoid "index out of bounds" exception.
if (page >= 0 && (int)page < ViewControllers.Count)
{
//self.notifyDelegateDidSwitchPage()
}
}*/
// Check whether the current view controller is fully presented.
if ((int)containerScrollView.ContentOffset.X % (int)pageWidth == 0)
{
CurrentPage = (int)page;
//FullySwitchedPage = CurrentPage;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment