Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIScrollview with UIButtons - how to recreate springboard?

I'm trying to create a springboard-like interface within my app. I'm trying to use UIButtons added to a UIScrollView. The problem I'm running in to is with the buttons not passing any touches to the UIScrollView - if I try to flick/slide and happen to press on the button it doesn't register for the UIScrollView, but if I flick the space between buttons it will work. The buttons do click/work if I touch them.

Is there a property or setting that forces the button to send the touch events up to its parent (superview)? Do the buttons need to be added to something else before being added the UIScrollView?

Here is my code:

//init scrolling area UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 480, 480)]; scrollView.contentSize = CGSizeMake(480, 1000); scrollView.bounces = NO; scrollView.delaysContentTouches = NO;  //create background image UIImageView *rowsBackground = [[UIImageView alloc] initWithImage:[self scaleAndRotateImage:[UIImage imageNamed:@"mylongbackground.png"]]]; rowsBackground.userInteractionEnabled = YES;  //create button UIButton *btn = [[UIButton buttonWithType:UIButtonTypeCustom] retain]; btn.frame = CGRectMake(100, 850, 150, 150); btn.bounds = CGRectMake(0, 0, 150.0, 150.0); [btn setImage:[self scaleAndRotateImage:[UIImage imageNamed:@"basicbutton.png"]] forState:UIControlStateNormal]; [btn addTarget:self action:@selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];  //add "stuff" to scrolling area [scrollView addSubview:rowsBackground]; [scrollView addSubview:btn];  //add scrolling area to cocos2d //this is just a UIWindow [[[Director sharedDirector] openGLView] addSubview:scrollView];  //mem-mgmt [rowsBackground release]; [btn release]; [scrollView release]; 
like image 511
Patrick Avatar asked Mar 16 '09 13:03

Patrick


2 Answers

Solution that worked for me included:

  1. Setting canCancelContentTouches in UIScrollView to YES.
  2. Extending UIScrollView to override touchesShouldCancelInContentView:(UIView *)view to return YES when view is a UIButton.

According to documentation touchesShouldCancelInContentView returns "YES to cancel further touch messages to view, NO to have view continue to receive those messages. The default returned value is YES if view is not a UIControl object; otherwise, it returns NO."

Since UIButton is a UIControl the extension is necessary to get canCancelContentTouches to take effect which enables scrolling.

like image 97
Roman Kishchenko Avatar answered Nov 11 '22 02:11

Roman Kishchenko


In order for UIScrollView to determine the difference between a click that passes through to its content view(s) and a touch that turns into a swipe or pinch, it needs to delay the touch and see if your finger has moved during that delay. By setting delaysContentTouches to NO in your above example, you're preventing this from happening. Therefore, the scroll view is always passing the touch to the button, instead of canceling it when it turns out that the user is performing a swipe gesture. Try setting delaysContentTouches to YES.

It might also be a good idea, structurally, to add all the views to be hosted in your scroll view to a common content view and only use that one view as the scroll view's subview.

like image 44
Brad Larson Avatar answered Nov 11 '22 01:11

Brad Larson