I\'m displaying a series of images in a UIScrollView. I pretty much want to replicate the Photos application.
My current architecture is:
This is the Andrey's code with c# translation for monotouch developers... First you need to edit your xib file.. Insert 3 view controllers and make outlets like _page1, _page2, _mainpage.. and link these outlets with views. note you must referance to view controller's view outlet with _mainpage view. (sorry for my english)
public partial class Test_Details_Controller : UIViewController
{
private UIPageControl _pageCont;
private UIScrollView _scView;
private Object[] _pageViews;
private int _currentPageIndex;
private bool _rotationInProgress;
void InitializeAfterLoad ()
{
this.Title = "Test";
this._pageCont = CreatePageControll();
}
private UIPageControl CreatePageControll()
{
UIPageControl pageControll = new UIPageControl( new RectangleF( 146,348, 38, 20 ) );
pageControll.BackgroundColor = UIColor.Red;
pageControll.Alpha = 0.7f;
return pageControll;
}
private void UpdatePageControll(UIPageControl cont, int current, int pages, UIView showed)
{
cont.CurrentPage = current;
cont.Pages = pages;
cont.UpdateCurrentPageDisplay();
UIPageControl.AnimationsEnabled = true;
UIPageControl.BeginAnimations(string.Empty, this.Handle);
cont.Frame = new RectangleF(showed.Frame.Location.X
, cont.Frame.Location.Y , pageSize().Width, cont.Frame.Height);
UIPageControl.CommitAnimations();
}
private UIView loadViewForPage(int pageIndex){
UIView _view = null;
switch ( pageIndex ) {
case 1:
_view = this._page1;
break;
case 2:
_view = this._page2;
break;
default:
_view = this._page1;
break;
}
return _view;
}
private int numberOfPages(){
return (int)this._pageViews.Count();
}
private UIView viewForPage( int pageIndex ){
UIView pageView;
if(this._pageViews.ElementAt( pageIndex ) == null)
{
pageView = loadViewForPage( pageIndex );
_pageViews[ pageIndex ] = pageView;
}
else{
pageView = (UIView)_pageViews[ pageIndex ];
}
_scView.AddSubview( pageView );
return pageView;
}
private SizeF pageSize(){
return this._scView.Frame.Size;
}
private bool isPageLoaded( int pageIndex ){
return this._pageViews.ElementAt( pageIndex ) != null;
}
private void layoutPage( int pageIndex ){
SizeF pageSize = this.pageSize();
((UIView)this._pageViews[pageIndex]).Frame = new RectangleF( pageIndex * pageSize.Width,0, pageSize.Width, pageSize.Height );
this.viewForPage( pageIndex );
}
private void loadView(){
this._scView = new UIScrollView();
this._scView.Delegate = new ScViewDelegate( this );
this._scView.PagingEnabled = true;
this._scView.ShowsHorizontalScrollIndicator = false;
this._scView.ShowsVerticalScrollIndicator = false;
this._scView.Layer.BorderWidth = 2;
this._scView.AddSubview( _pageCont );
this.View = this._scView;
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
InitializeAfterLoad ();
this._pageViews = new Object[]{ _page1, _page2 };
this.loadView();
}
private void currentPageIndexDidChange(){
this.layoutPage( _currentPageIndex );
if(_currentPageIndex+1 < this.numberOfPages()){
this.layoutPage( _currentPageIndex + 1 );
}
if(_currentPageIndex >0){
this.layoutPage( _currentPageIndex - 1 );
}
this.UpdatePageControll( _pageCont, _currentPageIndex, this.numberOfPages(), ((UIView)this._pageViews[_currentPageIndex]) );
this._scView.BringSubviewToFront( _pageCont );
this.NavigationController.Title = string.Format( "{0} of {1}", _currentPageIndex + 1, this.numberOfPages() );
}
private void layoutPages(){
SizeF pageSize = this.pageSize();
this._scView.ContentSize = new SizeF( this.numberOfPages() * pageSize.Width, pageSize.Height );
// move all visible pages to their places, because otherwise they may overlap
for (int pageIndex = 0; pageIndex < this.numberOfPages(); pageIndex++) {
if(this.isPageLoaded( pageIndex ))
this.layoutPage( pageIndex );
}
}
public override void ViewWillAppear (bool animated)
{
this.layoutPages();
this.currentPageIndexDidChange();
this._scView.ContentOffset = new PointF( _currentPageIndex * this.pageSize().Width, 0 );
}
class ScViewDelegate : UIScrollViewDelegate
{
Test_Details_Controller id;
public ScViewDelegate ( Test_Details_Controller id )
{
this.id = id;
}
public override void Scrolled (UIScrollView scrollView)
{
if(id._rotationInProgress)
return;// UIScrollView layoutSubviews code adjusts contentOffset, breaking our logic
SizeF pageSize = id.pageSize();
int newPageIndex = ((int)id._scView.ContentOffset.X + (int)pageSize.Width / 2) / (int)pageSize.Width;
if( newPageIndex == id._currentPageIndex )
return;
id._currentPageIndex = newPageIndex;
id.currentPageIndexDidChange();
}
}
public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
{
return toInterfaceOrientation != UIInterfaceOrientation.PortraitUpsideDown;
}
public override void WillRotate (UIInterfaceOrientation toInterfaceOrientation, double duration)
{
_rotationInProgress = true;
// hide other page views because they may overlap the current page during animation
for (int pageIndex = 0; pageIndex < this.numberOfPages(); pageIndex++) {
if(this.isPageLoaded( pageIndex ))
this.viewForPage( pageIndex ).Hidden = ( pageIndex != _currentPageIndex );
}
}
public override void WillAnimateRotation (UIInterfaceOrientation toInterfaceOrientation, double duration)
{
// resize and reposition the page view, but use the current contentOffset as page origin
// (note that the scrollview has already been resized by the time this method is called)
SizeF pageSize = this.pageSize();
UIView pageView = this.viewForPage( _currentPageIndex );
this.viewForPage( _currentPageIndex ).Frame = new RectangleF( this._scView.ContentOffset.X, 0, pageSize.Width, pageSize.Height );
}
public override void DidRotate (UIInterfaceOrientation fromInterfaceOrientation)
{
base.DidRotate (fromInterfaceOrientation);
// adjust frames according to the new page size - this does not cause any visible changes
this.layoutPages();
this._scView.ContentOffset = new PointF( _currentPageIndex * this.pageSize().Width, 0 );
//unhide
for (int pageIndex = 0; pageIndex < this.numberOfPages(); pageIndex++) {
if( this.isPageLoaded( pageIndex ) )
this.viewForPage( pageIndex ).Hidden = false;
}
_rotationInProgress = false;
}
public override void DidReceiveMemoryWarning ()
{
//SuperHandle = DidReceiveMemoryWarning();
if(this._pageViews != null)
{
// unload non-visible pages in case the memory is scarse
for (int pageIndex = 0; pageIndex < this.numberOfPages(); pageIndex++) {
if( pageIndex < _currentPageIndex - 1 || pageIndex > _currentPageIndex + 1 )
if( this.isPageLoaded(pageIndex) ){
UIView pageview = (UIView)this._pageViews[ pageIndex ];
this._pageViews[ pageIndex ] = null;
pageview.RemoveFromSuperview();
}
}
}
}
public override void ViewDidUnload ()
{
this._pageViews = null;
this._scView = null;
}
}