I am adding a button in UIScrollView in StoryBoard
Below is the code i am using.
-(void)addScrollView
{
for(int i=0;i<[array count];i++)
{
UIScrollView *subScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 400, SUBSCROLLVIEW_WIDTH, SUBSCROLLVIEW_HEIGHT)];
UITextView *txtVwDetail = [[UITextView alloc] initWithFrame:CGRectMake(342, 0, TEXTVIEW_WIDTH, TEXTVIEW_HEIGHT)];
txtVwDetail.text = SAMPLE_STRING;
[self addSubScrollView:subScrollView];
[self.view addSubview:subScrollView];
[self.view addSubview:txtVwDetail];
}
}
-(void)addSubScrollView:(UIScrollView *)aSubScrollView
{
for(int i=0;i<[array count];i++)
{
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeCustom];
aButton.frame = CGRectMake(intBtnX, (aSubScrollView.frame.size.height - 80)/2, 50, 80);
[aButton setImage:[UIImage imageNamed:[self.items objectAtIndex:i]] forState:UIControlStateNormal];
**[aButton addTarget:self action:#selector(btnSubImageClicked) forControlEvents:UIControlEventTouchUpInside];**
aSubScrollView.contentSize = CGSizeMake(intScrollViewWidth, aSubScrollView.frame.size.height);
[aSubScrollView addSubview:aButton];
}
}
In addSubScrollView method I have added Button and its click event which is getting crashed.
-(void)btnSubImageClicked
{
NSLog(#"btnSubImageClicked");
}
I am having scenario as
MyMainViewController is the sourceViewController for my created customSegue which is the UIStoryboardSegue class
MyMainViewController having a UIView as PlaceHolderView in which I am adding MydestinationViewContoller's View which is this Scrollview
-(void)perform
{
BrowseScreenVC *srcObj = (BrowseScreenVC *)[self sourceViewController];
UIViewController *dstObj = (UIViewController *)[self destinationViewController];
for(UIView *vw in srcObj.viewPlaceHolder.subviews)
{
[vw removeFromSuperview];
}
NSLog(#"dest : %#",dstObj.view);
NSLog(#"destobj :%#",dstObj);
srcObj.currentViewController = dstObj;
[srcObj.viewPlaceHolder addSubview:[dstObj.view retain]];
}
UPDATE
With answer I also have to change the line
srcObj.currentViewController = dstObj;
to
srcObj.addChildViewController = dstObj;
to make it working
you have to add target as follow:
[aButton addTarget:self action:#selector(btnSubImageClicked:) forControlEvents:UIControlEventTouchUpInside];
#selector(), within these braces you have to provide the method that you want to perform. the ":" represents that the method has some argument. In this case the argument would be the button itself that is calling the method.
You have to implement your method then its signature would look like this
- (void)btnSubImageClicked:(id)sender{
// sender would be the button that is calling the method. you can use this object according to your requirements if you want.
// your code
}
if you want to call this method from somewhere else as well you can call it by passing sender argument nil. e.g [self btnSubImageClicked:nil];
Your action needs to accept an (id) sender argument, even if you are not using it:
-(void)btnSubImageClicked:(id) sender
{
NSLog(#"btnSubImageClicked");
}
In the addSubScrollView:
[aButton addTarget:self action:#selector(btnSubImageClicked:) forControlEvents:UIControlEventTouchUpInside];
Button target should like
-(void) btnSubImageClicked:(id)sender{}
try this.
Updated:-
Please correct your code,change this line
[aButton addTarget:self action:#selector(btnSubImageClicked:) forControlEvents:UIControlEventTouchUpInside];
Now working i checked.
Instead of
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeCustom];
write this,
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
and for better practice always write this,
-(void) btnSubImageClicked:(id)sender{}
Related
Question may look so stupid, just got problem in some basics of objective C. I'm aware objective C only support pass by value however my requirement needs to pass address. I have a UIButton member variable (iVar) and I'm passing these to a function and trying to alloc init inside the function using parameters like below...
Function Call:
[self create_button : ivar_btn];
Definition:
- (void) create_button : (UIButton*) button
{
// Create button
button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:#"00/00/0000" forState:UIControlStateNormal];
[self.add_scroll_view addSubview:button];
}
So without pass by reference in objective C, how do I handle this case?
Please correct me if I understood anything wrong.
NOTE: Create button is a common code, I have been using this to create buttons at run time depend on req.
Thanx
This is useless implementation and I have not tried it but still.
UIButton *ivar_btn = nil;
[self create_button : &ivar_btn];
- (void) create_button : (UIButton**) button
{
// Create button
*button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[*button setTitle:#"00/00/0000" forState:UIControlStateNormal];
[self.add_scroll_view addSubview:*button];
}
Try this....
- (void) create_button : (UIButton*) button
{
// Create button
UIButton *tmpButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
tmpButton = button;
[self.add_scroll_view addSubview:tmpButton];
}
I tried your code, it is working fine for me. just you missing one thing. Setting its frame.
Here is how I amend your code and works fine for me. Hope it will work for you as well.
UIButton *btn = [[UIButton alloc] init];
[self create_button:btn];
and Function/Method:
- (void) create_button : (UIButton*) button
{
// Create button
button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:#"00/00/0000" forState:UIControlStateNormal];
[button setFrame:CGRectMake(0, 0, 100,100)];
[self.view addSubview:button];
}
works fine
I added 3 buttons programmatically to my view, then I added the buttons to an array so that I can access them at a later time:
for (i = 0; i < 3; i++)
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[view addSubview:button];
[_buttons addObject:button];
}
If I reference the button in my array and change the image of the button, it does not change the button on screen.
UIButton* button = [_buttons objectAtIndex: 0];
[button setImage:thumb forState:UIControlStateNormal];
I've found a way to change the image of the button by looping through all the subviews in my view, but is there a better way?
for (UIView* subView in ((UIView*)[self.view.subviews objectAtIndex:0]).subviews){
if ([subView isKindOfClass:[UIButton class]]){
UIButton *button = (UIButton*)subView;
if (button.tag == self.selected){
[button setImage:thumb forState:UIControlStateNormal];
}
}
}
A common reason for this is that your array has not been initialized. When this happens, Objective C does not complain or throw excetions: instead, it behaves as if the calls to add elements never happened. It also returns nil when you try getting items back.
Add this line to your viewDidLoad method:
_buttons = [NSMutableArray array];
This should solve the problem.
Possible this could help on a click event:
-(void)clickEvent:(id)sender
{
[sender setImage:thumb forState:UIControlStateNormal];
}
If this is how you are picking up the event.
When you do addSubview, view retains subview you are adding. Also addObject retains it. Hence both are different ojbects. Changing properties of object in array will not affect object retained by view.
You can avoid loop by using tags. While adding buttons on view set unique tags to them. And when you want to access them, get it using tag directly.
//set tags for buttons
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setTag:999];
[view addSubview:button];
//access using tag
UIButton *button = (UIButton*)[view viewWithTag:999];
[button setImage:thumb forState:UIControlStateNormal];
Add a tag to the button after creating it. And later use that tag to get that button.
for (i = 0; i < 3; i++)
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.tag = i+1;
[view addSubview:button];
[_buttons addObject:button];
}
Then you can access it like:
UIButton *button1 = (UIButton *)[self.view viewWithTag:1];
UIButton *button2 = (UIButton *)[self.view viewWithTag:2];
UIButton *button3 = (UIButton *)[self.view viewWithTag:3];
While adding UIControl programatically to use reference later add tag to it which should be different like:
yourBtn.tag = 111;
Now get reference of UIButton like this:
UIButton *button = (UIButton*)[yourViewWhereYouAdded viewWithTag:111];
on one viewController of my app there is a long list of 20 or so buttons added programmatically, all which i want to call the same method, but to identify themselves through their button tag, but i ran into a problem that has set me back a few hours of research and attempts.The basic problem is i dont quite know how to access a programmatically created button in any other method than the method that they were initialized in.
My questions summerized:
1) if i were to create the button in the viewDidLoad method, how can I access it in a void method that i create?
2) How can i access those button tags in the created void method?
Here is the code that i have so far, but it is producing errors that ill explain below.
-(void)viewDidLoad{
float itemScrollerXdirection =0;
float itemScrollerYdirection =0;
float ySize =70.0;
float xSize = 70.0;
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(itemScrollerXdirection,itemScrollerYdirection,xSize,ySize);
[button addTarget:self action:#selector(itemSelected) forControlEvents:UIControlEventTouchUpInside];
button.tag =1;
[button setTitle:#"button1" forState:UIControlStateNormal];
[itemScroller addSubview:button];
}
//no errors in the above code
-(void)itemSelected{
if ([sender tag] == 1) { //Gets error "Use of undeclaired identifier 'sender'"
button.hidden = YES; //Gets error "Use of undeclaired identifier 'button1'"
}
}
We aren't working in the mystical relm of ruby, things need to be initialized and stored somewhere inorder for you to call them, try this:
#.h
#interface MyController : UIViewController{
NSMutableArray *buttons;
}
#.m
-(void)init // Or whatever you use for init
{
buttons = [[NSMutableArray alloc] init];
}
-(void)viewDidLoad{
//blah blah (what you already have)
[button addTarget:self action:#selector(itemSelected:) //Add ":"
forControlEvents:UIControlEventTouchUpInside];
button.tag =0;
[buttons addObject:button] //Add button to array of buttons
//blah blah (what you already have)
}
-(IBAction)itemSelected:(id)sender{
UIButton* button = [buttons objectAtIndex:sender.tag]
button.hidden = YES;
}
Note: I'm doing this from memory on, so it might not work perfectly.
#.h
#interface MyController : UIViewController{
UIButton *buttons;
}
#.m
-(void)viewDidLoad{
float itemScrollerXdirection =0;
float itemScrollerYdirection =0;
float ySize =70.0;
float xSize = 70.0;
self.button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.button.frame = CGRectMake(itemScrollerXdirection,itemScrollerYdirection,xSize,ySize);
[self.button addTarget:self action:#selector(itemSelected) forControlEvents:UIControlEventTouchUpInside];
self.button.tag =1;
[self.button setTitle:#"button1" forState:UIControlStateNormal];
[itemScroller addSubview:button];
}
//no errors in the above code
-(void)itemSelected
{
if ([sender tag] == 1)
{
self.button.hidden = YES;
}
}
I have a custom header view in my iphone app. and it have a custom button over that.
But that custom button action is not fire but header tap event is fired which is in custom class .Please help me .How to fire action on button in header view.
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
NSNumber *num=[NSNumber numberWithInt:section];
UIView * customView = [[[UIView alloc] initWithFrame:CGRectMake(0,0,320,50)]autorelease];
customView.tag = section;
[customView setUserInteractionEnabled:YES];
customView.backgroundColor = [UIColor blackColor];
UIButton *button=[UIButton buttonWithType:UIButtonTypeCustom];
button.frame=CGRectMake(260, 7, 25, 25);
button.tag=section;
[button addTarget:self action:#selector(expandCollapsing:) forControlEvents:UIControlEventTouchUpInside];
[button setImage:[UIImage imageNamed:#"add.png"] forState:UIControlEventTouchUpInside];
[button setSelected:YES];
}
You can implement your own callback method to do this.
What i did is I added a TapGesture to the customView. When the event is fired i used a callback method to pass the control to the viewController where my tableView is implemeted
What you can do While loading the header you can assign the tag value to the customView
customHeader.tag = 1;
and you can implement the call back method in your viewController.
In CustomheaderView
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(checkBoxEventHandler:)];
[recognizer setNumberOfTapsRequired:1];
[recognizer setNumberOfTouchesRequired:1];
[self setGestureRecognizers:[NSArray arrayWithObject:recognizer]];
-(IBAction)checkBoxEventHandler:(id)sender
{
if ([self.delegate respondsToSelector:#selector(selectedHeader: atIndex:)])
{
[self.delegate selectedHeader:self atIndex:self.tag];
}
}
In your viewController.m
-(void)selectedHeader:(myCustomHeader *)header atIndex:(int)index
{
//header -> will give you the same instance you created in your viewController while loading this custom header view
// So you can check the tag like this
if(header.tag == 1)
{
//Do Stuff here
}
// index -> we are passing headerViews tag as index ie header.tag is equal to index
// So checking the tag like this is the proper way
if(index == 1)
{
//Do Stuff here
}
}
Just paste this code will solve your problem :
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
UIButton *button=[UIButton buttonWithType:UIButtonTypeCustom];
button.frame=CGRectMake(50.0, 0.0, 25, 25);
[button setImage:[UIImage imageNamed:#"add.png"] forState:UIControlStateNormal];
button.tag=section;
[button addTarget:self action:#selector(expandCollapsing:) forControlEvents:UIControlEventTouchUpInside];
[button setSelected:YES];
return button;
}
-(void)expandCollapsing:(id)sender {
UIButton *btn=(UIButton*)sender;
NSLog(#"Tag:%d",[btn tag]);
}
this is my first post, any help would be greatly appreciated.
I have to create a number of UIButtons programmatically, which I have done, but the code gets quite messy when there are alot of buttons so I have written a method that will take a UIbutton, string and UIcolor as input and set the rest of the UIButton attributes for me. The problem is the buttons don't seem to be created. Is what I'm trying possible or am I going about it the wrong way.
The method
-(void)makeButton:(UIButton *)name titleOfButton:(NSString *)title buttonColor:(UIColor *)color {
name =[[UIButton alloc] initWithFrame:(CGRectMake(400,400,150,100))];
[name setAlpha:(0.5)];
[name setBackgroundColor: color];
[name setTitle:title forState:UIControlStateNormal];
name.titleLabel.font = [UIFont systemFontOfSize:16];
name.titleLabel. numberOfLines = 0; // Dynamic number of lines
name.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
name.titleLabel.textColor = [UIColor blackColor];
[myView addSubview:name];
}
and to call the method
[self makeButton:JDLabel
titleOfButton:#"JD"
buttonColor:[UIColor redColor]];
The method has been declared in the header file and the buttons at the top of the class.
This is some code to get you started. This will work if you paste it to your view controller, generally put it in the view you want but change "self.view" to "self" or any view you want as long as you have the reference to it. Just call "addSomeButtons" on "viewDidLoad" or as some target..
- (void)buttonPressed:(UIButton *)sender {
NSLog(#"button %d pressed", sender.tag+1);
}
- (void)makeButtonWithtitle:(NSString *)title andColor:(UIColor *)color atPositionIndex:(NSInteger)index {
const CGFloat buttonHeight = 60.0f;
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(.0f, buttonHeight*index, 300.0f, buttonHeight)];
button.tag = index;
[button setAlpha:(0.5)];
[button setBackgroundColor: color];
[button setTitle:title forState:UIControlStateNormal];
button.titleLabel.font = [UIFont systemFontOfSize:16];
button.titleLabel. numberOfLines = 0; // Dynamic number of lines
button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
button.titleLabel.textColor = [UIColor blackColor];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
[button release];
}
- (void)addSomeButtons {
for(int i=0; i<10; i++) {
[self makeButtonWithtitle:[NSString stringWithFormat:#"button %d", i+1] andColor:[UIColor greenColor] atPositionIndex:i];
}
}
Anyway what you are trying to do is very common and very possible. For instance I never ever ever use the interface builder.
set the different tag value of to separate the button from another button like:
button.tag = 1;
here you should use variable like
in .h
int i ;
in .m
button.tag = i;
and set the frame size of one button to another button
UIButton *name = [UIButton buttonWithType:UIButtonTypeRoundRectangle];
name.frame = CGRectMake(10*i,10*i,150,100);
i++;
UIButtons are getting created but getting overlapped over each other.. u just need to change the frame with every method call too.. 400,400 will create the button off screen .. i don't think thats what u want .. try something like 160,240
You might want to consider creating the Buttons in Interface Builder, which I find much more convenient for setting the size, colors etc.
You can then reference the buttons in the code via either with an IBOutlet per Button or with an IBOutletCollection, which let's you "group" a number of UIViews in one Outlet:
Simply create your UIButtons in Interfacebuilder and place them next to your main view, so that they won't be displayed initially.
CMD + Click all buttons and CTRL + Drag to your .h file and create an IBOutletCollection which will eventually look like this in your code:
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *allMyButtonsFromIB;
Now you can access the buttons in the implementation via self.allMyButtons, which is an NSArray
-(void)createButtonWithTitle:(NSString*)title andColor:(UIColor*)color andFrame:(CGRect)frame{
UIButton *lButton = [UIButton buttonWithType:UIButtonTypeCustom];
[lButton setFrame:frame];
[lButton setTitle:title forState:UIControlStateNormal];
lButton.titleLabel.font = [UIFont systemFontOfSize:16];
[lButton setBackgroundColor:color];
[self.view addSubview:lButton];
lButton = nil;
}
You can change the frame values to put the buttons at appropriate positions on the view.