Skip to content

Commit

Permalink
Initial files
Browse files Browse the repository at this point in the history
  • Loading branch information
thevole committed May 21, 2010
0 parents commit 80f3e61
Show file tree
Hide file tree
Showing 12 changed files with 623 additions and 0 deletions.
13 changes: 13 additions & 0 deletions Classes/PageLoopViewController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

#import <UIKit/UIKit.h>

@interface PageLoopViewController : UIViewController {
NSMutableArray *_pageViews;
UIScrollView *_scrollView;
NSUInteger _currentPageIndex;
NSUInteger _currentPhysicalPageIndex;
BOOL _pageLoopEnabled;
BOOL _rotationInProgress;
}

@end
230 changes: 230 additions & 0 deletions Classes/PageLoopViewController.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@

#import "PageLoopViewController.h"


@interface PageLoopViewController () <UIScrollViewDelegate>

@property (nonatomic, retain) NSMutableArray *pageViews;
@property (nonatomic, retain) UIScrollView *scrollView;
@property (nonatomic, readonly) NSUInteger currentPageIndex;
@property (nonatomic) NSUInteger physicalPageIndex;

- (NSUInteger)physicalPageForPage:(NSUInteger)page;
- (NSUInteger)pageForPhysicalPage:(NSUInteger)physicalPage;

@end


@implementation PageLoopViewController

@synthesize pageViews=_pageViews, scrollView=_scrollView, currentPageIndex=_currentPageIndex;

- (UIView *)loadViewForPage:(NSUInteger)pageIndex {
UIImage *image = nil;
switch(pageIndex % 3) {
case 0: image = [UIImage imageNamed:@"image1.png"]; break;
case 1: image = [UIImage imageNamed:@"image2.png"]; break;
case 2: image = [UIImage imageNamed:@"image3.png"]; break;
}
UIImageView *pageView = [[[UIImageView alloc] initWithImage:image] autorelease];
pageView.contentMode = UIViewContentModeScaleToFill;
return pageView;
}

- (CGRect)alignView:(UIView *)view forPage:(NSUInteger)pageIndex inRect:(CGRect)rect {
UIImageView *imageView = (UIImageView *)view;
CGSize imageSize = imageView.image.size;
CGFloat ratioX = rect.size.width / imageSize.width, ratioY = rect.size.height / imageSize.height;
CGSize size = (ratioX < ratioY ?
CGSizeMake(rect.size.width, ratioX * imageSize.height) :
CGSizeMake(ratioY * imageSize.width, rect.size.height));
return CGRectMake(rect.origin.x + (rect.size.width - size.width) / 2,
rect.origin.y + (rect.size.height - size.height) / 2,
size.width, size.height);
}

- (NSUInteger)numberOfPages {
return 3;
}

- (UIView *)viewForPhysicalPage:(NSUInteger)pageIndex {
NSParameterAssert(pageIndex >= 0);
NSParameterAssert(pageIndex < [self.pageViews count]);

UIView *pageView;
if ([self.pageViews objectAtIndex:pageIndex] == [NSNull null]) {
pageView = [self loadViewForPage:pageIndex];
[self.pageViews replaceObjectAtIndex:pageIndex withObject:pageView];
[self.scrollView addSubview:pageView];
NSLog(@"View loaded for page %d", pageIndex);
} else {
pageView = [self.pageViews objectAtIndex:pageIndex];
}
return pageView;
}

- (CGSize)pageSize {
return self.scrollView.frame.size;
}

- (BOOL)isPhysicalPageLoaded:(NSUInteger)pageIndex {
return [self.pageViews objectAtIndex:pageIndex] != [NSNull null];
}

- (void)layoutPhysicalPage:(NSUInteger)pageIndex {
UIView *pageView = [self viewForPhysicalPage:pageIndex];
CGSize pageSize = [self pageSize];
pageView.frame = [self alignView:pageView forPage:[self pageForPhysicalPage:pageIndex] inRect:CGRectMake(pageIndex * pageSize.width, 0, pageSize.width, pageSize.height)];
}

- (void)loadView {
_pageLoopEnabled = YES;

self.scrollView = [[[UIScrollView alloc] init] autorelease];
CGRect rect = [[UIScreen mainScreen] applicationFrame];
self.scrollView.frame = rect;
self.scrollView.delegate = self;
self.scrollView.pagingEnabled = YES;
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.showsVerticalScrollIndicator = NO;
self.view = self.scrollView;
}

- (void)viewDidLoad {
self.pageViews = [NSMutableArray array];
// to save time and memory, we won't load the page views immediately
NSUInteger numberOfPhysicalPages = (_pageLoopEnabled ? 3 * [self numberOfPages] : [self numberOfPages]);
for (NSUInteger i = 0; i < numberOfPhysicalPages; ++i)
[self.pageViews addObject:[NSNull null]];
}

- (void)currentPageIndexDidChange {
[self layoutPhysicalPage:_currentPhysicalPageIndex];
if (_currentPhysicalPageIndex+1 < [self.pageViews count])
[self layoutPhysicalPage:_currentPhysicalPageIndex+1];
if (_currentPhysicalPageIndex > 0)
[self layoutPhysicalPage:_currentPhysicalPageIndex-1];
self.navigationItem.title = [NSString stringWithFormat:@"%d of %d", 1+_currentPageIndex, [self numberOfPages]];
}

- (void)layoutPages {
CGSize pageSize = [self pageSize];
self.scrollView.contentSize = CGSizeMake([self.pageViews count] * pageSize.width, pageSize.height);
// move all visible pages to their places, because otherwise they may overlap
for (NSUInteger pageIndex = 0; pageIndex < [self.pageViews count]; ++pageIndex)
if ([self isPhysicalPageLoaded:pageIndex])
[self layoutPhysicalPage:pageIndex];
}

- (void)viewWillAppear:(BOOL)animated {
[self layoutPages];
[self currentPageIndexDidChange];
[self setPhysicalPageIndex:[self physicalPageForPage:_currentPageIndex]];
}

- (NSUInteger)physicalPageIndex {
CGSize pageSize = [self pageSize];
return (self.scrollView.contentOffset.x + pageSize.width / 2) / pageSize.width;
}

- (void)setPhysicalPageIndex:(NSUInteger)newIndex {
self.scrollView.contentOffset = CGPointMake(newIndex * [self pageSize].width, 0);
}

- (NSUInteger)physicalPageForPage:(NSUInteger)page {
NSParameterAssert(page < [self numberOfPages]);
return (_pageLoopEnabled ? page + [self numberOfPages] : page);
}

- (NSUInteger)pageForPhysicalPage:(NSUInteger)physicalPage {
if (_pageLoopEnabled) {
NSParameterAssert(physicalPage < 3 * [self numberOfPages]);
return physicalPage % [self numberOfPages];
} else {
NSParameterAssert(physicalPage < [self numberOfPages]);
return physicalPage;
}
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (_rotationInProgress)
return; // UIScrollView layoutSubviews code adjusts contentOffset, breaking our logic

NSUInteger newPageIndex = self.physicalPageIndex;
if (newPageIndex == _currentPhysicalPageIndex) return;
_currentPhysicalPageIndex = newPageIndex;
_currentPageIndex = [self pageForPhysicalPage:_currentPhysicalPageIndex];

[self currentPageIndexDidChange];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
NSLog(@"scrollViewDidEndDecelerating");
NSUInteger physicalPage = self.physicalPageIndex;
NSUInteger properPage = [self physicalPageForPage:[self pageForPhysicalPage:physicalPage]];
if (physicalPage != properPage)
self.physicalPageIndex = properPage;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
_rotationInProgress = YES;

// hide other page views because they may overlap the current page during animation
for (NSUInteger pageIndex = 0; pageIndex < [self.pageViews count]; ++pageIndex)
if ([self isPhysicalPageLoaded:pageIndex])
[self viewForPhysicalPage:pageIndex].hidden = (pageIndex != _currentPhysicalPageIndex);
}

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)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)
CGSize pageSize = [self pageSize];
UIView *pageView = [self viewForPhysicalPage:_currentPhysicalPageIndex];
pageView.frame = [self alignView:pageView forPage:_currentPageIndex inRect:CGRectMake(self.scrollView.contentOffset.x, 0, pageSize.width, pageSize.height)];
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
// adjust frames according to the new page size - this does not cause any visible changes
[self layoutPages];
self.physicalPageIndex = _currentPhysicalPageIndex;

// unhide
for (NSUInteger pageIndex = 0; pageIndex < [self.pageViews count]; ++pageIndex)
if ([self isPhysicalPageLoaded:pageIndex])
[self viewForPhysicalPage:pageIndex].hidden = NO;

_rotationInProgress = NO;
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
if (self.pageViews) {
// unload non-visible pages in case the memory is scarse
for (NSUInteger pageIndex = 0; pageIndex < [self.pageViews count]; ++pageIndex)
if (pageIndex < _currentPhysicalPageIndex-1 || pageIndex > _currentPhysicalPageIndex+1)
if ([self isPhysicalPageLoaded:pageIndex]) {
UIView *pageView = [self.pageViews objectAtIndex:pageIndex];
[self.pageViews replaceObjectAtIndex:pageIndex withObject:[NSNull null]];
[pageView removeFromSuperview];
}
}
}

- (void)viewDidUnload {
self.pageViews = nil;
self.scrollView = nil;
}

- (void)dealloc {
[self viewDidUnload];
[super dealloc];
}

@end
21 changes: 21 additions & 0 deletions Classes/ScrollerAppDelegate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// ScrollerAppDelegate.h
// Scroller
//
// Created by Martin Volerich on 5/21/10.
// Copyright Bill Bear Technologies 2010. All rights reserved.
//

#import <UIKit/UIKit.h>

@class PageLoopViewController;

@interface ScrollerAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
PageLoopViewController *viewController;
}



@end

36 changes: 36 additions & 0 deletions Classes/ScrollerAppDelegate.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// ScrollerAppDelegate.m
// Scroller
//
// Created by Martin Volerich on 5/21/10.
// Copyright Bill Bear Technologies 2010. All rights reserved.
//

#import "ScrollerAppDelegate.h"
#import "PageLoopViewController.h"

@implementation ScrollerAppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

viewController = [[PageLoopViewController alloc] init];

window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

// Override point for customization after app launch
[window addSubview:viewController.view];
[window makeKeyAndVisible];

return YES;
}


- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}


@end
35 changes: 35 additions & 0 deletions Scroller-Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string>ipadicon.png</string>
<key>CFBundleIdentifier</key>
<string>com.volerich.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
Loading

0 comments on commit 80f3e61

Please sign in to comment.