UIButton not Responsive When placed out of its container UIScrollView - ios

I have a UIScrollView. Inside this UIScrollView is a UIView which contains every other child views (including a UIButton). It has the same bounds as the UIScrollView.
I want:
The bottom of the UIScrollView is not scroll-able (where the UIButton is placed).
The UIButton is responsive.
So I set the bottom of the UIScrollView a little higher than the UIVIew as below image:
This will make the UIButton not responsive (it's responsive in the left layout). Any suggestion? Thanks!
Some part of my code:
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
[self addSubview:self.scrollView];
self.scrollContent = [[UIView alloc] initWithFrame:CGRectZero];
[self.scrollView addSubview:self.scrollContent];
self.button = [UIButton buttonWithType:UIButtonTypeCustom];
[self.scrollContent addSubview:self.button];
[self.button addTarget:self
action:#selector(buttonPressed)
forControlEvents:UIControlEventTouchUpInside];
Update:
Looks like the right way is to keep the bottom of the scroll view and set its contentSize, but since I'm using autolayout, I found that the height of the contentSize is always zero???

You need to place the button in a view that is outside of the scroll views view hierarchy.
Currently the hit testing is failing because the button is outside of the scroll views bounds but within its hierarchy.

Add the button into scroll view after that try the below code:
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
[self addSubview:self.scrollView];
self.scrollContent = [[UIView alloc] initWithFrame:CGRectZero];
[self.scrollView addSubview:self.scrollContent];
self.scrollView.delaysContentTouches = NO; //Add this line
self.button = [UIButton buttonWithType:UIButtonTypeCustom];
[self.scrollContent addSubview:self.button];
[self.button addTarget:self
action:#selector(buttonPressed)
forControlEvents:UIControlEventTouchUpInside];

Related

Is it possible to dim a UIView but allow touch of elements behind it?

How would you have a grey overlay on top, but allow to touch buttons beneath it?
You can set userInteraction of overlay to false.
As mentioned, you can set userInteractionEnabled to NO.
But pay attention: when you create a full screen transparent view, and set its userInteractionEnabled to NO, all the subviews of that view will not be responsive to user actions. If you add a button on your view, it will not respond to user taps! and another problem: if you set the alpha value of that view to be transparent, e.g. 0.4, then all its subviews will be transparent too!
The solution is simple: don't put any subview on your transparent view, but instead, add your other elements as siblings of your view. Here is Objective-C code to show what I mean: (notice the comments which say it all):
//Create a full screen transparent view:
UIView *vw = [[UIView alloc] initWithFrame:self.view.bounds];
vw.backgroundColor = [UIColor greenColor];
vw.alpha = 0.4;
vw.userInteractionEnabled = NO;
//Create a button to appear on top of the transparent view:
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 80, 44)];
btn.backgroundColor = [UIColor redColor];
[btn setTitle:#"Test" forState:UIControlStateNormal];
[btn setTitle:#"Pressed" forState:UIControlStateHighlighted];
//(*) Bad idea: [vw addSubview:btn];
//(**) Correct way to have the button respond to user interaction:
// Add it as a sibling of the full screen view
[self.view addSubview:vw];
[self.view addSubview:btn];

Creating UIScrollView In Interface Builder Using Dynamic Content

I am a newcomer to the realm of iOS development.
I am trying to get the UIScrollView control to work and ran across the following question:
steps for creating UIScrollView with Interface Builder
I followed the steps outlined in the answer for this question and everything works as I want. However, this appears to create a statically-sized view that is scrolled. What I am really after is a dynamically sized view that may or may not be scrolled. For example, instead of the view with buttons, I put a single label for which I set the text and number of lines in the viewDidLoad method. The view that contains the label is set to a static size so the scroll viewer does not attempt to scroll and the content of the label spills off of the page.
What am I missing?
you need to set te content size of the scroll
CGPoint controlsCenter = ViewBottom.center;
if(Pointsvalue > 5)
{
controlsCenter.y += txtFldFrame1.frame.origin.y+20;
ViewBottom.center = controlsCenter;
[ScrollLag addSubview:ViewBottom];
}
[ScrollLag setContentSize:(CGSizeMake(0, controlsCenter.y+100))];
make sure your label height changes on entering text.......
The URL in my comment to the original question provides a solution to the issue I raised.
I have a dynamically sized UIScrollView in a project I am working on right now. This is what I did:
self.myScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 250, 748)];
[self.myScrollView setBackgroundColor:[UIColor blackColor]];
int heightCounter = 10;
UIButton *newButton = [UIButton buttonWithType:UIButtonTypeCustom];
newButton.frame = CGRectMake(10, heightCounter, 200, 40);
[newButton setBackgroundColor:[UIColor clearColor]];
[newButton addTarget:self action:#selector(someMethod:) forControlEvents:UIControlEventTouchUpInside];
[newButton setTitle:#"ButtonTitle" forState:UIControlStateNormal];
[newButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[self.myScrollView addSubview:newButton];
heightCounter += 50;
// add additional items to the myScrollView and remember to increase the heightCounter
self.myScrollView.contentSize = CGSizeMake(250, heightCounter);
self.myScrollView.scrollEnabled = YES;
[self.view addSubview:self.myScrollView];

Strange UIButton behaviour on iOS5

I create a UIButton and place it on top of the UIImageView which I place on UIScrollView. I add the button to the image like this:
backgroundImage.frame = CGRectMake(0, 0, backgroundImage.frame.size.width, mainTextView.frame.origin.y + mainTextView.frame.size.height + bottomMargin + attachBlockHeight);
[self insertSubview:backgroundImage atIndex:0];
UIButton *tmpButton = [[UIButton alloc] initWithFrame:CGRectMake(0, imgGreyLine.frame.origin.y + imgGreyLine.frame.size.height, backgroundImage.frame.size.width, attachBlockHeight)];
[tmpButton addTarget:self action:#selector(btnAttachClicked) forControlEvents:(UIControlEventTouchUpInside)];
//tmpButton.backgroundColor = [UIColor redColor];
[backgroundImage addSubview:tmpButton];
And the button works great on iOS6 and up - it's there, it receives touch events and does what it has to do.
However, on iOS5 I encounter an enormously strange behaviour - the frame of the button stays exactly the same and the button is clearly present on the view, but it only receives touch events when I slide my finger left or right on it. Moreover, there are no other UIViews on top of the button anywhere near!
What can be the reason for it? I'm totally confused in finding the bug here.
EDIT: It turns out that sliding UIButton works on iOS6 as well, but the thing is that the touch events are also registered.
You need to enable user interaction on the UIImageView parent
eg:
UIImageView *backgroundImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
[backgroundImage setBackgroundColor:[UIColor yellowColor]];
[backgroundImage setUserInteractionEnabled:YES];
[self.view addSubview:backgroundImage];
UIButton *tmpButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0,50,50)];
[tmpButton addTarget:self action:#selector(btnAttachClicked) forControlEvents:(UIControlEventTouchUpInside)];
tmpButton.backgroundColor = [UIColor redColor];
[backgroundImage addSubview:tmpButton];
You can not add UIbutton as a subview of UIImageview. Add it to the scrollview or the superview of UIimageview for that matter
I think the proper way to do what you want is to have a UIView with the imageview and button as siblings/children. make sure to disable user interaction on the imageview and you should be good.

How to add a button to a UIScrollView as a subView from outside the same method?

So I am trying to get a simple UIScrollView working with a bunch of buttons. I was successfully able to accomplish this task with the following code:
- (void)viewDidLoad
{
[super viewDidLoad];
[_scroller setScrollEnabled:YES];
[_scroller setContentSize:CGSizeMake(320, 1487)];
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, -500, 320, 2800)];
[imgView setBackgroundColor:[UIColor blackColor]];
[_scroller addSubview:imgView];
UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn1 setTitle:#"Cool title" forState:UIControlStateNormal];
[btn1 setFrame:CGRectMake(7, 7, 150, 160)];
[btn1 setImage:[UIImage imageNamed:#"small.png"] forState:UIControlStateNormal];
[btn1 addTarget:self action:#selector(btn1_m) forControlEvents:UIControlEventTouchUpInside];
[_scroller addSubview:btn1];
However, what if I to add buttons through interface builder instead of programmatically adding them? Whenever I do this, the scroller no longer scrolls!
For example, if I use the following code after control-dragging a button:
- (IBAction)theButton:(UIButton *)sender {
[_scroller addSubview:sender];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[_scroller setScrollEnabled:YES];
[_scroller setContentSize:CGSizeMake(320, 1487)];
}
...The scroll doesn't work, I see the button but nothing scrolls anymore. Basically, I just want to use interface builder to add buttons to my app and have them scroll too, but can't seem to get this to work!
When you create your UI programmatically, the subviews of your scrollview are like this:
ImageView
Button
Button
...
When you use IB to add your buttons, you end up with this:
Button
Button
...
ImageView
Place a breakpoint after your image view is added to the scroll view. In the LLDB console type:
(lldb) po _scroller.subviews
I suspect you will see your image view at the bottom of the list. It is covering your buttons, but it is scrolling, it just doesn't look like it as it is a large black image view.
Send your image view to the back of the subview list:
[_scroller sendSubviewToBack:imgView];
Then you will see your buttons again.
Also, after you have done this, confirm your scrollview content size in lldb:
(lldb) p _scroller.contentSize
If it all looks correct, it should be scrolling.

UIView in UIScrollView does not appear

I'm trying to create a horizontally scrollable menu similar to that in this video.
For some reason the UIView doesn't appear after adding a bunch of UIButtons to it and adding it to the UIScrollView. Here's my code (it's called in -viewDidLoad of a subclass of UIViewController):
//set up scrollview
UIScrollView *designPicker = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 431, 320, 49)];
//set up a view to drop into the scroll view
UIView * buttonsView = [[UIView alloc] initWithFrame:CGRectMake(0, 431, 640, 49)];
//add buttons to scrollview
// load all the images from our bundle and add them to the scroll view
NSUInteger i;
float runningX = designPicker.frame.origin.x;
for (i = 1; i <= 10; i++)
{
UIButton *tempBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[tempBtn setBackgroundImage:[UIImage imageNamed:#"button.png"] forState:UIControlStateNormal];
CGRect rect = CGRectMake(runningX, designPicker.frame.origin.y, 30.0, 30.0);
tempBtn.frame = rect;
[buttonsView addSubview:tempBtn];
runningX = runningX + 35;
[tempBtn release];
}
[designPicker setContentSize:buttonsView.frame.size];
[designPicker addSubview:buttonsView];
[self.view addSubview:designPicker];
You should not add the buttons using the frame of the UIScrollView. The origin of the frame is in the superview's (superview of the UIScrollView) coordinates. You should make the buttons' frame relative to the UIView. So if you want the buttons to appear at the top of the view that you should start at (0,0).
Instead of adding scrollview as subview to your view, add view as subview of scrollview. As-
[self.scrollView addSubview:self.view];
// release scrollView as self.view retains it
self.view=self.scrollView;
[self.scrollView release];
And make sure your view should have large content size than content size of your scrollview.It worked for me.

Resources