Reputation: 6490
I am new to iPad
developer,
I am reading EPUB
content on UIWebView
I'm using UIWebView
on the iPhone to display EPUB
content, but I want to implement page turning animation similar to book.
Here is Demo Example. And
here is my code snippet,
http://www.mediafire.com/?pxb6xxfknxoarz6
Thanks In Advance !
Upvotes: 1
Views: 2108
Reputation: 7778
Ms. Sadun has open source code that will build your pages here
Here is another person's tutorial
Once you have the page turn animation working, the content can be anything, including an HTML page/link.
I used Erica's samples to build a book. Most of the pages were pngs, but I used an html page as a table of contents. This page had links to specific pages within the book. Inline CSS worked to style the page.
Note that UIPageViewController only works on iPad.
The following code is how I implemented it. Note that my version shows one page at a time, not two.
This is my page view controller code:
/*
About this class:
- it assumes western left-to-right usage for the page flips
- it assumes one page in both landscape and portrait
- it stores but does not use the current page
*/
#import "InfoPageController.h"
#define IS_IPHONE ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
#define SAFE_ADD(_Array_, _Object_) {if (_Object_ && [_Array_ isKindOfClass:[NSMutableArray class]]) [pageControllers addObject:_Object_];}
#define SAFE_PERFORM_WITH_ARG(THE_OBJECT, THE_SELECTOR, THE_ARG) (([THE_OBJECT respondsToSelector:THE_SELECTOR]) ? [THE_OBJECT performSelector:THE_SELECTOR withObject:THE_ARG] : nil)
#pragma Utility Class - VC that Rotates
@interface RotatableInfoVC : UIViewController
@end
@implementation RotatableInfoVC
- (void) loadView
{
[super loadView];
self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
self.view.backgroundColor = [UIColor whiteColor];
}
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return YES;
}
@end
#pragma Page Controller
@implementation InfoPageController
@synthesize infoPageDelegate, pageNumber;
/*
#pragma mark Debug / Utility
- (int) currentPage
{
NSLog(@"%s", __FUNCTION__);
int pageCheck = ((UIViewController *)[self.viewControllers objectAtIndex:0]).view.tag;
NSLog(@"pageCheck is %i", pageCheck);
return pageCheck;
}
*/
#pragma mark Page Handling
// Update if you'd rather use some other decision style
- (BOOL) useSideBySide: (UIInterfaceOrientation) orientation
{
return NO;
}
// Store the new page and update the delegate
- (void) updatePageTo: (uint) newPageNumber
{
//NSLog(@"%s", __FUNCTION__);
pageNumber = newPageNumber;
[[NSUserDefaults standardUserDefaults] setInteger:pageNumber forKey:DEFAULTS_INFOPAGE];
[[NSUserDefaults standardUserDefaults] synchronize];
SAFE_PERFORM_WITH_ARG(infoPageDelegate, @selector(infoPageControllerDidTurnToPage:), [NSNumber numberWithInt:pageNumber]);
}
// Request controller from delegate
- (UIViewController *) controllerAtPage: (int) aPageNumber
{
//NSLog(@"%s", __FUNCTION__);
if (infoPageDelegate &&
[infoPageDelegate respondsToSelector:@selector(viewControllerForPage:)])
{
UIViewController *controller = [infoPageDelegate viewControllerForPage:aPageNumber];
controller.view.tag = aPageNumber;
return controller;
}
return nil;
}
// Update interface to the given page
- (void) fetchControllersForPage: (uint) requestedPage orientation: (UIInterfaceOrientation) orientation
{
//NSLog(@"%s", __FUNCTION__);
int numberOfPagesNeeded = 1;
int currentCount = self.viewControllers.count;
uint leftPage = requestedPage;
// Only check against current page when count is appropriate
if (currentCount && (currentCount == numberOfPagesNeeded))
{
if (pageNumber == requestedPage) return;
if (pageNumber == leftPage) return;
}
// Decide the prevailing direction by checking the new page against the old
UIPageViewControllerNavigationDirection direction = (requestedPage > pageNumber) ? UIPageViewControllerNavigationDirectionForward : UIPageViewControllerNavigationDirectionReverse;
[self updatePageTo:requestedPage];
// Update the controllers
NSMutableArray *pageControllers = [NSMutableArray array];
SAFE_ADD(pageControllers, [self controllerAtPage:leftPage]);
//SAFE_ADD(pageControllers, [self controllerAtPage:leftPage + 1]);
[self setViewControllers:pageControllers direction: direction animated:YES completion:nil];
}
// Entry point for external move request
- (void) moveToPage: (uint) requestedPage
{
//NSLog(@"%s", __FUNCTION__);
[self fetchControllersForPage:requestedPage orientation:(UIInterfaceOrientation)[UIDevice currentDevice].orientation];
}
#pragma mark Data Source
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
//NSLog(@"%s", __FUNCTION__);
[self updatePageTo:pageNumber + 1];
return [self controllerAtPage:(viewController.view.tag + 1)];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
//NSLog(@"%s", __FUNCTION__);
[self updatePageTo:pageNumber - 1];
return [self controllerAtPage:(viewController.view.tag - 1)];
}
#pragma mark Delegate
- (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation
{
//NSLog(@"%s", __FUNCTION__);
return UIPageViewControllerSpineLocationMin;
}
#pragma mark Class utility routines
// Return a UIViewController that knows how to rotate
+ (id) rotatableInfoViewController
{
//NSLog(@"%s", __FUNCTION__);
UIViewController *vc = [[RotatableInfoVC alloc] init];
return vc;
}
// Return a new book
+ (id) infoPageWithDelegate: (id) theDelegate
{
//NSLog(@"%s", __FUNCTION__);
InfoPageController *infoPage = [[InfoPageController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
infoPage.dataSource = infoPage;
infoPage.delegate = infoPage;
infoPage.infoPageDelegate = theDelegate;
return infoPage;
}
and this is the code I use to feed pages to the page view controller class:
@implementation InfoViewController
@synthesize delegate;
@synthesize infoViewController;
- (void) viewDidLoad
{
//NSLog(@"%s", __FUNCTION__);
// Add the child controller, and set it to the first page
[self.view addSubview:infoPageController.view];
[self addChildViewController:infoPageController];
[infoPageController didMoveToParentViewController:self];
[infoPageController moveToPage:0];
}
- (void) loadView
{
[super loadView];
//NSLog(@"%s", __FUNCTION__);
// Build the view
CGRect appRect = [[UIScreen mainScreen] bounds];
self.view = [[UIView alloc] initWithFrame: appRect];
self.view.backgroundColor = [UIColor whiteColor];
self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
self.navigationItem.rightBarButtonItem = nil;
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"DONE", @"") style:UIBarButtonItemStyleBordered
target:self
action:@selector(dismiss:)];
self.navigationItem.rightBarButtonItem = doneButton;
UIBarButtonItem *tocButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"TOC", @"") style:UIBarButtonItemStyleBordered
target:self action:@selector(tocButtonTapped:)];
self.navigationItem.leftBarButtonItem = tocButton;
self.navigationController.navigationBar.tintColor = [UIColor blackColor];
self.title = NSLocalizedString(@"Information", @"");
// Establish the page view controller
infoPageController = [InfoPageController infoPageWithDelegate:self];
infoPageController.view.frame = (CGRect){.size = appRect.size};
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
// THIS IS WHERE THE PAGES ARE CREATED / LOADED.
- (id) viewControllerForPage: (int) pageNumber
{
// CHANGE THIS TO PAGE NUMBER - DEPENDING ON HOW MANY PAGES YOU HAVE.
//NSLog(@"%s", __FUNCTION__);
AppDelegate *mainDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
if (pageNumber < 0) return nil;
if (pageNumber > [mainDelegate.infoPageData count]) {
pageNumber = 1;
}
//NSLog(@"viewControllerForPage - selectedPage is: %i", pageNumber);
// Establish a new controller
UIViewController *controller = [InfoPageController rotatableInfoViewController];
// Add an image
if (pageNumber == 2) { //TOC
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle]
pathForResource:@"infotoc" ofType:@"html"]isDirectory:NO]]];
//webView.backgroundColor = [UIColor clearColor];
webView.frame = CGRectMake(0,0,550,800);
webView.delegate = self;
[controller.view addSubview:webView];
} else {
NSString *imageName = [NSString stringWithFormat:@"dreamcatchingInstructions.%i.png", pageNumber +1];
//NSLog(@"imageName is: %@", imageName);
UIImage *image = [UIImage imageNamed: imageName];
CGRect viewFrame = self.view.frame;
//viewFrame.origin.y = 50;
viewFrame.size.width = 540;
viewFrame.size.height = 600;
UIImageView *imageView = [[UIImageView alloc] initWithFrame:viewFrame];
imageView.image = image;
[controller.view addSubview:imageView];
}
return controller;
}
- (void)doneButtonTapped {
[delegate doneButtonTapped];
}
- (IBAction)dismiss:(id)sender {
//NSLog(@"%s", __FUNCTION__);
[self dismissModalViewControllerAnimated:YES];
}
-(void)tocButton {
//NSLog(@"%s", __FUNCTION__);
[delegate tocButton];
}
- (IBAction)tocButtonTapped:(id)sender {
//NSLog(@"%s", __FUNCTION__);
[infoPageController moveToPage:2];
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
//NSLog(@"%s", __FUNCTION__);
NSString *absoluteUrl = [[request URL] absoluteString];
//NSLog(@"absoluteUrl is %@", absoluteUrl);
if ([absoluteUrl isEqualToString:@"didtap://button1"]) {
//NSLog(@"Button1");
[self didTapButton1];
return NO;
}
if ([absoluteUrl isEqualToString:@"didtap://button2"]) {
//NSLog(@"Button2");
[self didTapButton2];
return NO;
}
if ([absoluteUrl isEqualToString:@"didtap://button3"]) {
//NSLog(@"Button3");
[self didTapButton3];
return NO;
}
if ([absoluteUrl isEqualToString:@"didtap://button4"]) {
//NSLog(@"Button4");
[self didTapButton4];
return NO;
}
if ([absoluteUrl isEqualToString:@"didtap://button5"]) {
//NSLog(@"Button5");
[self didTapButton5];
return NO;
}
if ([absoluteUrl isEqualToString:@"didtap://button6"]) {
//NSLog(@"Button6");
[self didTapButton6];
return NO;
}
if ([absoluteUrl isEqualToString:@"didtap://button7"]) {
//NSLog(@"Button7");
[self didTapButton7];
return NO;
}
if ([absoluteUrl isEqualToString:@"didtap://button8"]) {
//NSLog(@"Button8");
[self didTapButton8];
return NO;
}
if ([absoluteUrl isEqualToString:@"didtap://button9"]) {
//NSLog(@"Button9");
[self didTapButton9];
return NO;
}
//NSLog(@"No");
return YES;
}
-(void)didTapButton1 {
//NSLog(@"%s", __FUNCTION__);
[infoPageController moveToPage:3];
}
-(void)didTapButton2 {
//NSLog(@"%s", __FUNCTION__);
[infoPageController moveToPage:11];
}
-(void)didTapButton3 {
//NSLog(@"%s", __FUNCTION__);
[infoPageController moveToPage:15];
}
-(void)didTapButton4 {
//NSLog(@"%s", __FUNCTION__);
[infoPageController moveToPage:29];
}
-(void)didTapButton5 {
//NSLog(@"%s", __FUNCTION__);
[infoPageController moveToPage:43];
}
-(void)didTapButton6 {
//NSLog(@"%s", __FUNCTION__);
[infoPageController moveToPage:50];
}
-(void)didTapButton7 {
//NSLog(@"%s", __FUNCTION__);
[infoPageController moveToPage:56];
}
-(void)didTapButton8 {
//NSLog(@"%s", __FUNCTION__);
[infoPageController moveToPage:60];
}
-(void)didTapButton9 {
//NSLog(@"%s", __FUNCTION__);
[infoPageController moveToPage:67];
}
Finally, my table of contents page (web writing) is like this:
<html>
<head>
<title>DreamCatching</title>
<style type="text/css">
body {
/*width: 700px;*/
position: relative;
background: url('DreamCatchingWhite3.png') no-repeat;
opacity:0.6;
font: 30px "Copperplate",sans-serif;
font-weight: 100;
/*margin: 0;*/
font-style: normal;
}
img {
opacity:0.3;
}
h1 {
height: 70px;
font: 36px "Gill Sans",sans-serif;
font-weight: 200;
text-align: center;
}
h2 {
font: 28px "Gill Sans",sans-serif;
font-weight: 200;
text-align: center;
}
#header1 {
position: relative;
margin-top: 40;
text-align:center;
width: 100%;
font: 36px "Copperplate",sans-serif;
font-weight: 200;
text-transform: small-caps;
/*border-bottom: 3px double #600;*/
height: 100px;
}
#body1 {
position: relative;
/*width: 80%;*/
font: 26px "Copperplate",sans-serif;
font-weight: 200;
background-image:DreamCatchingWhite2.png;
/*border-bottom: 3px double #600;*/
height: 300px;
}
p {
text-align: center;
}
td, th {
/*border: 1px solid #eee;*/
font: 20px "Copperplate",sans-serif;
margin-bottom:40;
font-weight: 200;
}
tr {
position:relative;
border:10;
margin-bottom:40;
height:70;
text-align: center;
text-transform: small-caps;
}
table {
width:100%;
margin-bottom:40;
border-collapse:collapse;
font: 20px "Copperplate",sans-serif;
font-weight: 200;
text-transform: small-caps;
}
a {
color: black;
text-decoration: none;
text-align: center;
text-transform: small-caps;
}
</style>
</head>
<body>
<div id="header1">
<h1>TABLE OF CONTENTS</h1>
</div>
<div id="body1">
<table border="0" cellspacing="6">
<tr>
<td><a href="didtap://button1">Getting Started</a></td>
<td><a href="didtap://button2">Voice Recording</a></td>
<td><a href="didtap://button3">Adding Details</a></td>
</tr>
<tr>
<td><a href="didtap://button4">Styles</a></td>
<td><a href="didtap://button5">Exploration</a></td>
<td><a href="didtap://button6">Deleting and Saving</a></td>
</tr>
<tr>
<td><a href="didtap://button7">Email and Sharing</a></td>
<td><a href="didtap://button8">Drawing</a></td>
<td><a href="didtap://button9">Summary</a></td>
</tr>
</table>
</div>
</body>
</html>
Upvotes: 2
Reputation: 16714
Since you are using a UIWebView, you will want to use JavaScript and/or CSS to accomplish the page turning animation.
There are a few routes you could go here.
Check out turn.js and jquery mobile page transitions. One of these solutions should work for you.
Here is the sample code for turn.js:
#magazine{
width:800px;
height:400px;
}
#magazine .turn-page{
width:400px;
height:400px;
background-color:#ccc;
}
<div id='magazine'>
<div> Page 1 </div>
<div> Page 2 </div>
<div> Page 3 </div>
</div>
$('#magazine').turn();
Upvotes: 0