In a post, Making Long Scrolls on the iPhone Not Suck, Aza Raskin describes an alternative scrollbar control that's better at getting around on very long pages:
It's not important that the scrollbar "remains for some amount of time" to activate it; I'm fine with simply swiping along the right edge of the iPhone's screen to grab hold of the scrollbar handle. The idea is that if I drag the handle 3/4 of the way down on the physical screen, I'd be 3/4 of the way down on the page.
Tthe Dropbox iPhone app (it's great, btw!) has exactly this kind of scrollbar for long PDF documents. Regular scrolling is done by dragging anywhere but on the handle; dragging the handle moves the view to that location. This seems to have been implemented "from scratch", as I don't think the SDK is flexible enough to customize the behavior of the existing scrollbar.
However, Dropbox uses the native document viewers to show documents on the iPhone, so somehow they add the scrollbar functionality to it. See the scrollbar handle? You can drag that to quickly get somewhere else in the document.
This concept is very similar to how index bars work in UITableView (ie. Contacts.app); the index appears as a bar on the right hand side of the table (for example, "a" through "z"), and you can touch a particular label to jump to the target section. In this case, however, a very long page doesn't have sections, and it should work for general-purpose scrolling, not jumping to sections.
So how can I go about implementing this method of scrolling? I'm looking for general ideas and specific implementation details. I'm also interested if an open-开发者_如何学JAVAsource implementation exists (this seems like a general-purpose problem/solution).
A general idea:
I grabbed the dropbox app (it is awesome) and played around with a bit. It looks like pdf viewing takes a bit from the photo app in that it conditionally displays a translucent navbar and toolbar on touches, in addition to supporting the scrollbar. I'm pretty sure what's going on is that they have a custom view controller intercepting touches and reacting accordingly.
On a touch:
- If it's a tap, show/hide the navbar and toolbar.
- If it's on
the scrubber, begin tracking the
touch and scrolling the
scrollview/webview (whatever they're
displaying with). I'm sure the
scrolling is something simple like
scrollView.contentOffset = CGPointMake(0, (scrubber.y / [UIScreen mainScreen].bounds.size.height) * scrollView.contentSize.height)
. 3) - Else, pass the touch on to the enclosed view.
There may be other hidden magic with PDF displaying (I've never done it in cocoa touch) but something tells me this is their basic process.
I don't know of any iPhone specific solutions, but this is an old and well travelled topic in the world of Flash development... and you could probably extract a ton of pseudo code from that realm.
If you know the height of your window, and the height of your content, and the current offset of the content (which you do), then you have all the tools you need to create a custom UIView which can serve as a touch-responding slider. And then just paint it over the default scroller.
There's probably an open source implementation for this. I don't know any. Maybe shoot an email to Dropbox developers?
Anyway, the way I'd do this is:
@interface UICustomisedScrollView : UISCrollView
{
BOOL showingScroller;
UIView scroller; //Customise this, either in IB or in viewDidLoad
}
@implementation UICustomisedScrollView
- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view {
showingScroller = !showingScroller;
if(showingScroller)
scroller.hidden = NO;
else
scroller.hidden = YES;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if(showingScroller) {
if(/*the touch is on the scroller*/) {
/* scrollview.setContentOffset(...) we want to scroll according to how much the user scrolls here */
}
//move scroller.frame.origin to where the touch is.
}
}
I'm guessing it won't be too difficult... But I haven't tested the above code yet. That's the general idea anyway =)
Try using a UIPanGestureRecognizer
. In your action, can use the locationInView
to determine the point the user is touching. Do this when the state is UIGestureRecognizerStateBegan
and if it's close enough to the side of the view implement fast scrolling. Otherwise, implement slow scrolling.
精彩评论