Reputation: 3432
I created the UIScrollView with content insets.
scrollView.frame = CGRectMake(-80, 180, 480, 190)
self.scrollView.contentInset = UIEdgeInsetsMake(0, 160, 0, 160);
self.scrollView.pagingEnabled = YES;
[self.scrollView setContentSize:CGSizeMake(480, 190)];
// Add three Views
[self.scrollView addSubview:view1];
[self.scrollView addSubview:view2];
[self.scrollView addSubview:view3];
[view1 setFrame:CGRectMake(0, 0, 160, 190)];
[view2 setFrame:CGRectMake(160, 0, 160, 190)];
[view3 setFrame:CGRectMake(320, 0, 160, 190)];
At first time, scrollView.contentOffset.x
was -160.0
But the weird problem is when I tap on scrollView(Yellow Area), content offset x value is resetting to 0 and shown like this.
I tried several times, but tapping on Scroll View resets the content offset to 0.
How can I prevent this?
Upvotes: 16
Views: 22728
Reputation: 3432
In addition to alex's first approach with setting clipsToBounds to NO, I need to react to the scroll outside of the scroll view bounds. So I created ScrollForwarderView class which is subclass of UIView.
ScrollForwarderView.h
#import <UIKit/UIKit.h>
@interface ScrollForwarderView : UIView
@property (nonatomic, weak) UIScrollView *scrollView;
@end
ScrollForwarderView.m
...
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if ([self pointInside:point withEvent:event]) {
return _scrollView;
}
return nil;
}
Then place UIView with custom class ScrollForwarderView above the scroll view, link scrollView property to my scroll view and it nicely forwarded the user events to scrollview.
Upvotes: 3
Reputation: 5454
UIScrollView
paging works by scrolling pages with the same width of the scrollView (in your case pages of 480 width). This means that you have 1 single page (you'd still be able to scroll left and right due to the 160 content inset).
One way to make this work would be:
self.scrollView.frame = CGRectMake(80, 180, 160, 190);
self.scrollView.clipsToBounds = NO;
self.scrollView.contentInset = UIEdgeInsetsZero;
self.scrollView.pagingEnabled = YES;
[self.scrollView setContentSize:CGSizeMake(480, 190)];
This will draw and scroll correctly, however, the sides of the screen will not be interactive (80 pixels on each side, since the control starts at frame.origin.x=80 and ends at 80+160=240).
Second option would be to handle paging yourself, by using methods provided by UIScrollViewDelegate
.
- (void)viewDidLoad
{
[super viewDidLoad];
// pageIndex must be declared as a class member - this is used to prevent skipping pages during scroll
pageIndex = 0;
self.scrollView.frame = CGRectMake(0, 180, 320, 190);
self.scrollView.contentInset = UIEdgeInsetsMake(0, 80, 0, 80);
self.scrollView.pagingEnabled = NO;
self.scrollView.clipsToBounds = YES;
[self.scrollView setContentSize:CGSizeMake(480, 190)];
self.scrollView.delegate = self;
}
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{
int pageWidth = 160;
int pageX = pageIndex*pageWidth-scrollView.contentInset.left;
if (targetContentOffset->x<pageX) {
if (pageIndex>0) {
pageIndex--;
}
}
else if(targetContentOffset->x>pageX){
if (pageIndex<3) {
pageIndex++;
}
}
targetContentOffset->x = pageIndex*pageWidth-scrollView.contentInset.left;
NSLog(@"%d %d", pageIndex, (int)targetContentOffset->x);
}
Upvotes: 15