UIScrollView horizontal paging like Mobile Safari tabs
A UIScrollView
with paging enabled will stop at multiples of its frame width (or height). So the first step is to figure out how wide you want your pages to be. Make that the width of the UIScrollView
. Then, set your subview's sizes however big you need them to be, and set their centers based on multiples of the UIScrollView
's width.
Then, since you want to see the other pages, of course, set clipsToBounds
to NO
as mhjoy stated. The trick part now is getting it to scroll when the user starts the drag outside the range of the UIScrollView
's frame. My solution (when I had to do this very recently) was as follows:
Create a UIView
subclass (i.e. ClipView
) that will contain the UIScrollView
and it's subviews. Essentially, it should have the frame of what you would assume the UIScrollView
would have under normal circumstances. Place the UIScrollView
in the center of the ClipView
. Make sure the ClipView
's clipsToBounds
is set to YES
if its width is less than that of its parent view. Also, the ClipView
needs a reference to the UIScrollView
.
The final step is to override - (UIView *)hitTest:withEvent:
inside the ClipView
.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
return [self pointInside:point withEvent:event] ? scrollView : nil;
}
This basically expands the touch area of the UIScrollView
to the frame of its parent's view, exactly what you need.
Another option would be to subclass UIScrollView
and override its - (BOOL)pointInside:(CGPoint) point withEvent:(UIEvent *) event
method, however you will still need a container view to do the clipping, and it may be difficult to determine when to return YES
based only on the UIScrollView
's frame.
NOTE: You should also take a look at Juri Pakaste's hitTest:withEvent: modification if you are having issues with subview user interaction.
The ClipView
solution above worked for me, but I had to do a different -[UIView hitTest:withEvent:]
implementation. Ed Marty's version didn't get user interaction working with vertical scrollviews I have inside the horizontal one.
The following version worked for me:
-(UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
UIView* child = nil;
if ((child = [super hitTest:point withEvent:event]) == self)
return self.scrollView;
return child;
}