Using InterfaceBuilder ONLY for positioning objects on the view - iphone

Have created a UIButton programmatically, all works as expected but how can I use the IB ONLY for positioning the objects on the view?
To be more precise I like to use the IB for this line only (see: setViaIB)
self.searchBtn.frame = CGRectMake(setViaIB, setViaIB, 36, 36);
Full code for UIButton creation:
self.searchBtn = [UIButton buttonWithType:UIButtonTypeCustom];
self.searchBtn.frame = CGRectMake(100, 0, 36, 36);
[self.searchBtn setBackgroundImage:[UIImage imageNamed:#"search.png"] forState:UIControlStateNormal];
[self.searchBtn addTarget:self action:#selector(searchBtnTapped::) forControlEvents:UIControlEventTouchUpInside];
[self.searchBtn setNeedsDisplay];
[self.view addSubview:self.searchBtn];

I'm pretty sure you can't, why don't you use initWithNibName: bundle: to create the whole view in an nib (Interface Builder) file?

You can only position the button in IB if you created it in IB. You can change searchBtnTapped method to an IBAction and link it up to your button via files owner in IB. You can then move the button wherever you want in IB. If not you will just have to reposition the button via coordinates until you are happy.

Related

In iOS, can a UIButton be added by alloc and initWithFrame?

A button can be added by:
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
myButton.frame = CGRectMake(100, 100, 160, 50);
[myButton setTitle:#"click me" forState:UIControlStateNormal];
[self.view addSubview:myButton];
but can we go with the initWithFrame method:
UIButton *myButton2 = [[UIButton alloc] initWithFrame:CGRectMake(100, 300, 160, 50)];
//myButton2.buttonType = UIButtonTypeRoundedRect;
myButton2.titleLabel.text = #"click me";
[self.view addSubview:myButton2];
but line 2 above is commented out because it causes an error for a "read only" property, and with that line commented out, still no button shows up at all... can a UIButton be added if using initWithFrame to begin with?
(update: I set a yellow background to see the view's area, and found that the label text of button 2 actually shows up as "click me" in white... but touching it has no visual effect... so I wonder how to change code sample 2 to make it work...)
Yes of course it can. I got into a little bit of a discussion as to that readonly buttonType property a while back. The general concensus is that there is neither a safe way, nor a good reason, for anyone to switch the type of a button. And besides, +buttonWithType returns an instance of UIButton just as well as +Alloc and -init do, so it isn't a problem.

Add subview to UIButton

I'm trying to add subviews to a UIButton. This is working fine right now. But the button isn't clickable anymore as soon as I add the subviews.
I use the following code:
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(column*100+24, row*80+10, 64, 64);
[button addSubview:asyncImage];
[button addSubview:price];
[button addTarget:self
action:#selector(buttonClicked:)
forControlEvents:UIControlEventTouchUpInside];
The button works again if I remove the 2 addSubview: methods. If anyone knows how to fix this it would be great!
I found a quick solutions. I needed to set the asyncImageView to the following:
asyncImage.userInteractionEnabled = NO;
asyncImage.exclusiveTouch = NO;
After this, it worked!
try:
[UIButton buttonWithType:UIButtonTypeCustom];
instead of:
[UIButton buttonWithType:UIButtonControlType];
The important thing here is to make sure that userInteractionEnabled will be set to NO. Fortunately it works immediately for UIImageView and UILabel (maybe for other subclasses of a UIView but those are the most popular subviews added to button) because by default for this classes it is set to NO by default. Unfortunately it is set to YES in UIView so make sure to change it in that case. Messing around with any other flags shouldn't be necessary. The nature of problem is that many people do not know that default value of this flag is different in subclasses.
Have you tried to put:
[asyncImage setUserInteractionEnabled:YES];
in the same sitiation i make this action:
inherit from UIButton and add all labels and imageview's of button to self, finally put new button to view as last subview and add targets of self button to this last button(also set backgroundColor to clearColor for transparent). now it will be clickable and works fine.
In Swift, test that is you have your UIButton blocked
uibtn.userInteractionEnabled = false
uibtn.exclusiveTouch = false
I added a label to the subview button.
For a very long time I was looking for why my text in the button is not clickable. Solution in this thread:
myLable.isUserInteractionEnabled = false

Where to insert code that creates buttons programmatically?

I receive some JSON from the net and based on that data, I must create 2 or 3 buttons. Part of my gui is static and created in NIB (won't change), only the number of buttons will change. I found this code for making buttons in code:
//create the button
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
//set the position of the button
button.frame = CGRectMake(100, 170, 100, 30);
//set the button's title
[button setTitle:#"Click Me!" forState:UIControlStateNormal];
Is this the right way? In which method of my viewcontroller should I put this code?
You can add the button whenever you want, as long as the view has been loaded already. The one thing you'd need to add to the above code is
[[self view] addSubview:button];
Using this code, you have a button on the screen, but it won't be able to trigger any actions. You'll probably also want to add:
[button addTarget:self action:#selector(someMethod:) forControlState:UIControlEventTouchUpInside];
You should add the buttons in the delegate/method that parses the JSON data.
Don't forget to add the created buttons to your view:
[containerView addSubview:button];

UIButton does not respond to touch events after changing its position using setFrame

I have a view controller class (child) which extends from view controller class (parent). In the parent class's loadView() method I create a sub-view (named myButtonView) with two buttons (buttons are horizontally laid out in the subview) and add it to the main view. In the subclass I need to shift these two buttons up by 50pixels.
So, I am shifting the buttonView by calling the setFrame method. This makes the buttons shift and render properly but they do not respond to touch events after this. Buttons work properly in the views of Parent class type. In the child class type view also, if I comment out the setFrame() call the buttons work properly.
How can I shift the buttons and still make them respond to touch events?
Any help is appreciated.
Following is snippets of the code.
In the parent class:
- (void)loadView {
// Some code...
CGRect buttonFrameRect = CGRectMake(0,yOffset+1,screenRect.size.width,KButtonViewHeight);
myButtonView = [[UIView alloc]initWithFrame:buttonFrameRect];
myButtonView.backgroundColor = [UIColor clearColor];
[self.view addSubview:myButtonView];
// some code...
CGRect nxtButtonRect = CGRectMake(screenRect.size.width - 110, 5, 100, 40);
myNxtButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myNxtButton setTitle:#"Submit" forState:UIControlStateNormal];
myNxtButton.frame = nxtButtonRect;
myNxtButton.backgroundColor = [UIColor clearColor];
[myNxtButton addTarget:self action:#selector(nextButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[myButtonView addSubview:myNxtButton];
CGRect backButtonRect = CGRectMake(10, 5, 100, 40);
myBackButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myBackButton setTitle:#"Back" forState:UIControlStateNormal];
myBackButton.frame = backButtonRect;
myBackButton.backgroundColor = [UIColor clearColor];
[myBackButton addTarget:self action:#selector(backButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[myButtonView addSubview:myBackButton];
// Some code...
}
In the child class:
- (void)loadView {
[super loadView];
//Some code ..
CGRect buttonViewRect = myButtonView.frame;
buttonViewRect.origin.y = yOffset; // This is basically original yOffset + 50
[myButtonView setFrame:buttonViewRect];
yOffset += KButtonViewHeight;
// Add some other view below myButtonView ..
}
Button may have overlapped with another view after changing the frame... Just try by setting the background color to the views which are transparent so you can get clear idea which view is overlapping on button.
Make sure your UIButton’s container view can be interacted with. This is the one that gets me. If your UIButton is a subview of another view (not your view controller’s main view), it may not be configured to allow user interaction (the default). Try: containerView.userInteractionEnabled = YES;
Thanks for the help guys, you were right. I forgot to resize the scrollView that I added above the buttons, in the parent view. So, it was overlapping with the shifted buttonView. Changing the background color helped me see it. Thanks for the tip, Chandan.
This should work, my guess and this is just off the top of my head, is that you've got something intercepting your touch events. Basically, there's another view on top of your button.
Good luck.

Hit target on UIToolbar with custom-image buttons is not correct

I have a UIToolbar that I've customized with my own background image. Consequently, the built-in UIBarButtonItem appearance doesn't work for me, so I'm using images that are already prepared to show in the bar. I create a custom button item with this method:
+ (UIBarButtonItem *)customWithImage:(UIImage *)image enabled:(BOOL)enabled target:(id)target action:(SEL)selector {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
//I've tried different values for the frame here, but no luck
button.frame = CGRectMake(0, 0, 44, 44);
button.enabled = enabled;
button.showsTouchWhenHighlighted = YES;
[button addTarget:target action:selector forControlEvents:UIControlEventTouchUpInside];
[button setImage:image forState:UIControlStateNormal];
UIBarButtonItem *it = [[[UIBarButtonItem alloc] initWithCustomView:button] autorelease];
//Tried changing this, to no avail
it.width = 32.f;
return it;
I have one button on the left and one on the right and I'm trying to make it so that if you tap on the far left or far right of the UIToolbar, the corresponding button is tapped. However, with these custom buttons, the hit targets do not extend all the way to the edges of the UIToolbar, but are inset from the sides:
http://skitch.com/andpoul/d1p8g/hit-targets
Any help greatly appreciated!
UIBarButtonItem.width might be ignored if you're using a custom view (it probably just uses the width of the view).
A lame hack is to make the toolbar wider (so it sticks outside the screen) and add transparent edges to the background image to compensate. This brings the buttons closer to the edge of the screen.
An alternative is just to use a UIImageView with UIButton subviews.
I think the only way you will have to go is to make buttons wider (change image by adding some from left for one and right for another) and adjust size...