Slight pause in scrolling animation (iPad)
I am relatively new to programming on the iPad and I was trying to put together a simple program. Basically, it's a children's book and I need the functionality of a comic book style (or photo) viewer, where people swipe to change "pages" (or images).
Each image is 1024x768. Currently, they are stored as JPGs because of the very large file sizes PNGs seem to produce. For this story, there are 28 pages.
I took a look at the PageControl example, implementing a UIScrollView. On initialization, I create a big enough scrollview area. Then as the user scrolls, I load in the previous and next images. Again, just like the example only without implementing the page control at the bottom.
The problem I am running into is a very slight pause in the animation when I am flipping. Once the images are loaded or cached, this doesn't happen. Now, I know the photo application doesn't do this and I'm not sure what is causing it.
Here is my code for the scrollViewDidScroll method. I keep up with the page number and it will only call the loadPageIntoScrollView when a page has changed - I was thinking that the insane number of calls it was making was causing the slight pause in animation, but it turned out not to be the case.
- (void) scrollViewDidScroll: (UIScrollView *) sender
{
CGFloat pageWidth = scrollView.frame.size.width;
int localPage = floor( (scrollView.contentOffset.x - pageWidth / 2 ) / pageWidth ) + 1;
if( localPage != currentPage )
{
currentPage = localPage;
[self loadPageIntoScrollView:localPage - 1];
[self loadPageIntoScrollView:localPage];
[self loadPageIntoScrollView:localPage + 1];
}
} // scrollViewDidScroll
And here is my loadPageIntoScrollView
method. I'm only creating a UIImageView and loading an image into that - I don't see how that could be much "leaner". But somehow it's causing the pause. Again, it's not a HUGE pause, just one of those things you notice and is enough to make the scrolling look like it has a very. very 开发者_开发技巧slight hiccup.
Thank you in advance for any help you could provide.
- (void) loadPageIntoScrollView: (int)page
{
if( page < 0 || page >= kNumberOfPages )
return;
UIImageView *controller = [pages objectAtIndex:page];
NSLog( @"checking pages" );
if( (NSNull *)controller == [NSNull null] )
{
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
NSString *pageName = [[NSString alloc] initWithFormat:@"%d.jpg", page];
controller = [[UIImageView alloc]initWithImage:[UIImage imageNamed:pageName]];
[controller setUserInteractionEnabled:YES];
[controller addGestureRecognizer:singleTap];
[pages replaceObjectAtIndex:page withObject:controller];
[controller release];
} // if controller == null
// add the page to the scrollview
if( controller.superview == nil )
{
NSLog(@"superview was nil, adding page %d", page );
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
controller.frame = frame;
[scrollView addSubview:controller];
} // if
} // loadPageIntoScrollView
Since you say after an image is loaded in it no longer lags, I'd suspect that it is disk access that is causing your lag, but you should run your app through instruments to try to rule out cpu-spikes as well as evaluate file system usage. You may try to pre-load images to the left and right of whatever image you are on so that the user doesn't perceive as much lag.
First off, you should be able to use PNG's just fine. I have build several apps that do exactly what you are doing here, you can fit 3 1024 x 768 PNGs in memory without running out (but you can't do much more). You should also use PNG's as they are the preferred format for iOS as they are optimized when the app is bundled together during build.
The slight lag is caused by loading the image, in this line:
controller = [[UIImageView alloc]initWithImage:[UIImage imageNamed:pageName]];
What I usually do is load the images in a separate thread, using something like this:
[self performSelectorInBackground:@selector(loadPageIntoScrollView:) withObject:[NSNumber numberWithInt:localPage]];
Note that you need to put your localPage
integer into a NSNumber
object to pass it along, so don't forget to change your loadPageIntoScrollView:
method:
- (void) loadPageIntoScrollView: (NSNumber *)pageNumber
{
int page = [pageNumber intValue];
....
精彩评论