"Infinite UIScrollView" containing UIWebViews
The background:
First of all, the background. I've created an "infinite scrollview" by using an UIScrollView with the width of three pa开发者_运维知识库ges (0, 1 and 2) and then made sure that the UIScrollView always is centered on page 1 when not being scrolled upon. When you scroll to either page 0 or page 2 and the UIScrollViewDelegate senses that the scrolling ended, the content of all the three pages first switches in the direction that you've scrolled and then the UIScrollView instantly moves back to page 1, simulating the effect that you can continue to scroll through an endless stream of pages.
At first, I used a UITextView to display the text content of each page, but pretty soon wanted something more flexible when it comes to styling the text. I therefore ended up using a UIWebView in which I load an NSString containing the styled HTML content I wish to display. This worked perfectly, just the way I wanted it to look.
The problem:
Naturally, it takes longer time to load, parse and show a simple HTML page in a UIWebView than it takes to just load a static text in a UITextView. Because of this, when you've scrolled in whatever direction, and the scroll view automatically moves back and switches the content of the pages, you can hint the old content for a tenth of a second before the new one shows.
My solution (that did not work):
I searched for the UIWebViewDelegate in the documentation and found that there's an event when the page is done loading. I hooked this up to do this:
- User scrolls from page 1 to page 2.
- UIScrollViewDelegate calls scrollViewDidEndDecelerating, telling page 1 to switch it's content to the same content currently being displayed at page 2.
- UIWebViewDelegate of page 1 calls webViewDidFinishLoad, telling the UIScrollView to move back to page 1 and then switch the content of page 0 and 2.
In my head this would fix this problem, but apparently it's still not enough. Therefore, I ask you for help. Any ideas? Might be worth mentioning that I've had NSLog in all the methods and made sure that they're being called. If there's anything else, I'd be glad to answer any questions you have.
Thanks in advance!
View Controller containing UIScrollView:
// Sense when the UIScrollView stops accelerating
- (void)scrollViewDidEndDecelerating:(UIScrollView *)sender {
if(pScrollView.contentOffset.x > pScrollView.frame.size.width) {
[self switchToNextPost];
} else if (pScrollView.contentOffset.x < pScrollView.frame.size.width) {
[self switchToPreviousPost];
}
}
// Update the currentPost variable and switch page 1
- (void)switchToNextPost {
[prefs setInteger:[[self getNextKey:nil] intValue] forKey:@"currentPost"];
[self loadPostWithKey:[self getCurrentKey] atPage:[NSNumber numberWithInt:1] withViewController:currentPage];
}
// Update the currentPost variable and switch page 1
- (void)switchToPreviousPost {
[prefs setInteger:[[self getPreviousKey:nil] intValue] forKey:@"currentPost"];
[self loadPostWithKey:[self getCurrentKey] atPage:[NSNumber numberWithInt:1] withViewController:currentPage];
}
// Custom delegate function. Scrolls UIScrollView to page 1 and then loads new content on page 1 and 3
- (void)webViewFinishedLoading {
[pScrollView scrollRectToVisible:CGRectMake(pScrollView.frame.size.width, 0, pScrollView.frame.size.width, pScrollView.frame.size.height) animated:NO];
[self loadPostWithKey:[self getPreviousKey:nil] atPage:[NSNumber numberWithInt:0] withViewController:previousPage];
[self loadPostWithKey:[self getNextKey:nil] atPage:[NSNumber numberWithInt:2] withViewController:nextPage];
}
View Controller for the subviews being displayed as separate pages in the UIScrollView
// The delegate shown in previous code
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[[self delegate] webViewFinishedLoading];
}
what you can do , i think, is
- populate all three pages with relevant content from the beginning.. (you are probably doing that already)...
- when scrolling starts, the next (or previous) page shows up as you scroll..
- when scrolling finishes, move the scroll content view to center as you already do, and instead of changing text in each web view, change the frames of the views so that relevant web view (i.e. the one user has scrolled to) remains in the center, and other two are adjusted on both sides
- change the content of the both web views (which are not visible) so that they are ready for next scroll movement..
this would still fail in case of fast scrolling.. but because of the lag in loading content i any approach would file there (i think) so you can probably make all web views blank (load nothing) and show an activity indicator in case of fast scrolling..
精彩评论