UIButtons not clickable in UIScrollView after being added programatically - ios

I have some UIButtons inside a UIScrollView. When the view first loads there are about 8 buttons showing in the UIScrollView, all these buttons are visible and clickable.
However, once I scroll, any button that wasn't there when the view initially loaded isn't clickable.
Given I have a function that creates every button programatically on view load, is it possible that the addTarget function isn't working? I create about 280 buttons at the start and add the UITouchUpInside event programatically.
--Edit--
This is more or less the code, called inside viewDidLoad function
for (int i = 0; i < numberOfButtons; i++){
//Display stuff here
MyButton *aButton = [[MyButton alloc] initWithFrame:CGRectMake(x,y,w,h)];
[aButton.titleLabel setFont:[UIFont fontWithName:#"QuicksandBook-Regular" size: 17.0]];
[aButton setTitle:[currentDisplayArray objectAtIndex:i] forState:UIControlStateNormal];
[aButton addTarget:self
action:#selector(didPressButton:)
forControlEvents:UIControlEventTouchUpInside];
[aButton setUserInteractionEnabled:TRUE];
NSLog(#"width of button = %f height = %f", [aButton frame].size.height, [aButton frame].size.width);
//I printed this to check the height and width were generated correctly.
[btnContainerView addSubview:aButton]; //UIView hooked up to storyboard
[buttonArray addObject:aButton]; //Array to maintain reference to all buttons
}
Remember, they all display correctly, its just the ones that aren't rendered in the initial frame don't trigger the "didPressButton" selector.
-- Edit --
After playing around, I think its some kind of issue with the UIScrollView it is in. Is this some kind of apple bug? I even tried adding the gesture recognizers in the scrollViewDidScroll function.
-- Edit --
Another interesting hint, If I make the UIScrollView bigger, I can click more of the buttons, if I make it smaller I can click less. It definitely has something to do with the first rendered buttons.
Maybe iOS says its initialising the buttons, but doesn't keep the selectors of all 200+ buttons in memory. Or has an inbuilt number of possible selectors/gesture recognisers per class.

Yay, I worked it out.
There was a UIView sitting in front of the UIScrollView that the buttons were being added to.
The views were the same size, but only the buttons that were inside the initial bounds (the UIView size) were clickable.
There was a UIView that I think was called btnContainerView or something. What was happening was the buttons were being added to this UIView instead of the UIScrollView.
I think the UIView was set as the delegate for the buttons because thats were they were rendered. So when the UIScrollView received an input the buck stopped there. Calling addTarget:self on the buttons would mean their target was added to the scrollView, but they were rendered onto the UIView. A confusing bug because you would expect the UIScrollView not to scroll and render properly but it did, its just the delegates for the selectors were getting confused.
Thanks everyone for the help, this was quite tricky because the buttons scrolled correctly (UIScrollView got touch input) but the UIButtons didn't get the touch input.
TL;DR; The solution was removing the intermeditary UIView as it was interfering

I hope that you are using gestures int the view controller, if so you can use the below code
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if (([touch.view isKindOfClass:[UIButton class]] && touch.view.tag==<Btn_Tag>)) {
return NO;
}
return YES;
}
When using the gestures, gestures will respond first rather than the button action.So, this code will help to move the responder the button's action.

Related

Is it possible to format text in a scroll view in a storyboard which is longer than one screen? [duplicate]

I want to have several buttons and other objects in a long UIScrollView in my app. In storyboard, I added a UIScrollView to fill the entre view, and then created an IBOutlet in my .h file. I synthesized the scroller in my .m file, and then used the following code to start the scroller:
#synthesize scroller = _scroller;
- (void)viewDidLoad
{
[super viewDidLoad];
[_scroller setScrollEnabled:YES];
[_scroller setContentSize:CGSizeMake(640, 3000)];
}
So now I need to know how to actually add things, such as buttons, to the area of the scroller that extends below what you can see in the view. My problem is that as I add butons to my view in storyboard, I can only add things to what you can see in the view, and therefore need to know how to add buttons to part that I will scroll to!
Hopefully this is clear. Thanks for all your help!
UPDATE
I have posted a screencast that walks through this technique step-by-step.
ORIGINAL
The easiest way to handle this is simply to make the view in your storyboard taller. When the app runs, any of the normal container view controllers (UINavigationController, UITabBarController, UISplitViewController, or even UIViewController when it's the root view controller of its window) will resize the view to fit on the screen and scroll.
Here's an example of how to set it up in Xcode:
I changed the view controller's size from “Inferred” to “Freeform”. Then I changed its view's height from 460 to 800. (By the way, control-shift-click gives you a menu of all objects under the cursor.)
Here's what happens when I run it in the simulator:
As you can see, the view hierarchy was resized to fit the screen, but the subviews of the UIScrollView weren't repositioned, and the scroll view set its content size appropriately. (That may only work properly with autolayout, though...)
So, an example to you how to add a Button:
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setTitle:#"Cool title" forState:UIControlStateNormal];
[btn setFrame:CGRectMake(50, 700, 100, 100)];
[btn addTarget:self action:#selector(action:) forControlEvents:UIControlEventTouchUpInside];
[_scroller addSubview:btn];
You just need to set the frame of the view that you want to add and after that add it as a subview in your scroll.
You can you use the Size inspector(Left part of xcode) in order to position it. or reposition it programmatically.
Cheers,
Kel

How to increase size of view controller with working scroll in Swift 3 and Xcode 8? [duplicate]

I want to have several buttons and other objects in a long UIScrollView in my app. In storyboard, I added a UIScrollView to fill the entre view, and then created an IBOutlet in my .h file. I synthesized the scroller in my .m file, and then used the following code to start the scroller:
#synthesize scroller = _scroller;
- (void)viewDidLoad
{
[super viewDidLoad];
[_scroller setScrollEnabled:YES];
[_scroller setContentSize:CGSizeMake(640, 3000)];
}
So now I need to know how to actually add things, such as buttons, to the area of the scroller that extends below what you can see in the view. My problem is that as I add butons to my view in storyboard, I can only add things to what you can see in the view, and therefore need to know how to add buttons to part that I will scroll to!
Hopefully this is clear. Thanks for all your help!
UPDATE
I have posted a screencast that walks through this technique step-by-step.
ORIGINAL
The easiest way to handle this is simply to make the view in your storyboard taller. When the app runs, any of the normal container view controllers (UINavigationController, UITabBarController, UISplitViewController, or even UIViewController when it's the root view controller of its window) will resize the view to fit on the screen and scroll.
Here's an example of how to set it up in Xcode:
I changed the view controller's size from “Inferred” to “Freeform”. Then I changed its view's height from 460 to 800. (By the way, control-shift-click gives you a menu of all objects under the cursor.)
Here's what happens when I run it in the simulator:
As you can see, the view hierarchy was resized to fit the screen, but the subviews of the UIScrollView weren't repositioned, and the scroll view set its content size appropriately. (That may only work properly with autolayout, though...)
So, an example to you how to add a Button:
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setTitle:#"Cool title" forState:UIControlStateNormal];
[btn setFrame:CGRectMake(50, 700, 100, 100)];
[btn addTarget:self action:#selector(action:) forControlEvents:UIControlEventTouchUpInside];
[_scroller addSubview:btn];
You just need to set the frame of the view that you want to add and after that add it as a subview in your scroll.
You can you use the Size inspector(Left part of xcode) in order to position it. or reposition it programmatically.
Cheers,
Kel

Suggestions on how i can add 40 more "Round Rect Buttons" to my ScrollView [duplicate]

I want to have several buttons and other objects in a long UIScrollView in my app. In storyboard, I added a UIScrollView to fill the entre view, and then created an IBOutlet in my .h file. I synthesized the scroller in my .m file, and then used the following code to start the scroller:
#synthesize scroller = _scroller;
- (void)viewDidLoad
{
[super viewDidLoad];
[_scroller setScrollEnabled:YES];
[_scroller setContentSize:CGSizeMake(640, 3000)];
}
So now I need to know how to actually add things, such as buttons, to the area of the scroller that extends below what you can see in the view. My problem is that as I add butons to my view in storyboard, I can only add things to what you can see in the view, and therefore need to know how to add buttons to part that I will scroll to!
Hopefully this is clear. Thanks for all your help!
UPDATE
I have posted a screencast that walks through this technique step-by-step.
ORIGINAL
The easiest way to handle this is simply to make the view in your storyboard taller. When the app runs, any of the normal container view controllers (UINavigationController, UITabBarController, UISplitViewController, or even UIViewController when it's the root view controller of its window) will resize the view to fit on the screen and scroll.
Here's an example of how to set it up in Xcode:
I changed the view controller's size from “Inferred” to “Freeform”. Then I changed its view's height from 460 to 800. (By the way, control-shift-click gives you a menu of all objects under the cursor.)
Here's what happens when I run it in the simulator:
As you can see, the view hierarchy was resized to fit the screen, but the subviews of the UIScrollView weren't repositioned, and the scroll view set its content size appropriately. (That may only work properly with autolayout, though...)
So, an example to you how to add a Button:
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setTitle:#"Cool title" forState:UIControlStateNormal];
[btn setFrame:CGRectMake(50, 700, 100, 100)];
[btn addTarget:self action:#selector(action:) forControlEvents:UIControlEventTouchUpInside];
[_scroller addSubview:btn];
You just need to set the frame of the view that you want to add and after that add it as a subview in your scroll.
You can you use the Size inspector(Left part of xcode) in order to position it. or reposition it programmatically.
Cheers,
Kel

How to add objects to a UIScrollView that extend beyond UIView from Storyboard?

I want to have several buttons and other objects in a long UIScrollView in my app. In storyboard, I added a UIScrollView to fill the entre view, and then created an IBOutlet in my .h file. I synthesized the scroller in my .m file, and then used the following code to start the scroller:
#synthesize scroller = _scroller;
- (void)viewDidLoad
{
[super viewDidLoad];
[_scroller setScrollEnabled:YES];
[_scroller setContentSize:CGSizeMake(640, 3000)];
}
So now I need to know how to actually add things, such as buttons, to the area of the scroller that extends below what you can see in the view. My problem is that as I add butons to my view in storyboard, I can only add things to what you can see in the view, and therefore need to know how to add buttons to part that I will scroll to!
Hopefully this is clear. Thanks for all your help!
UPDATE
I have posted a screencast that walks through this technique step-by-step.
ORIGINAL
The easiest way to handle this is simply to make the view in your storyboard taller. When the app runs, any of the normal container view controllers (UINavigationController, UITabBarController, UISplitViewController, or even UIViewController when it's the root view controller of its window) will resize the view to fit on the screen and scroll.
Here's an example of how to set it up in Xcode:
I changed the view controller's size from “Inferred” to “Freeform”. Then I changed its view's height from 460 to 800. (By the way, control-shift-click gives you a menu of all objects under the cursor.)
Here's what happens when I run it in the simulator:
As you can see, the view hierarchy was resized to fit the screen, but the subviews of the UIScrollView weren't repositioned, and the scroll view set its content size appropriately. (That may only work properly with autolayout, though...)
So, an example to you how to add a Button:
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setTitle:#"Cool title" forState:UIControlStateNormal];
[btn setFrame:CGRectMake(50, 700, 100, 100)];
[btn addTarget:self action:#selector(action:) forControlEvents:UIControlEventTouchUpInside];
[_scroller addSubview:btn];
You just need to set the frame of the view that you want to add and after that add it as a subview in your scroll.
You can you use the Size inspector(Left part of xcode) in order to position it. or reposition it programmatically.
Cheers,
Kel

Enlarge UIButton's hitest area for button with background image, imageView and label in it

It may seem like duplicate, but I can't actually find any good answer to my concrete situation.
I have some button with background image (1pt-wide, streched), icon-like image inside along with the text label. It's height is 33pt, I need to make it's hittest area 44pt-high.
I saw two solutions, but neither of them works for me.
First solution is to enlarge frame and adjust image so it would have some padding. But that is not acceptable for me, because I have both background image and image inside the button.
Second solution is to subclass UIButton (which is absolutely acceptable) and override - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event. I did that, when I put some breakpoints in this method and tried to tap in desired area nothing happened (breakpoints worked when tapped inside the button frame).
Are there any other solutions? What could be possibly wrong with the second solution?
If you create the view programmatically, you can instantiate a UIView that is 44px high, add a tap gesture recognizer to it, and add your UIButton as a subview inside this view:
CGRect bigFrame = CGRectMake(0,0,100,44);
UIView *big = [[UIView alloc] initWithFrame:bigFrame];
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doPress)];
[big addGestureRecognizer:tapRecognizer];
UIButton *yourButton = ...
[big addSubview:yourButton];
[self.view addSubview:big];
Then implement the selector as:
- (void)doPress {
[yourButton sendActionsForControlEvents:UIControlEventTouchUpInside];
}
In that way, the outer view taps will be interpreted as button presses for your button.

Resources