Evening All
I have the following code to fill in a grid of buttons, but how do I detect which button has been selected and pass the button image on another controller
i =0;
int i1=0;
while(i<n){
int yy = 4 +i1*79;
for(int j=0; j<4;j++){
if (i>=n) break;
CGRect rect;
rect = CGRectMake(4+79*j, yy, 75, 75);
UIButton *button=[[UIButton alloc] initWithFrame:rect];
[button setFrame:rect];
id item = [items objectAtIndex:i];
NSString *imageLink = [item objectForKey:#"link"];
UIImage *buttonImageNormal=[UIImage imageWithData: [NSData dataWithContentsOfURL: [NSURLURLWithString: imageLink]]];
[button setBackgroundImage:buttonImageNormal forState:UIControlStateNormal];
button.tag =i;
NSLog(#"index: %i", i);
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside ];
Thanks in advance
You will obtain pressed button as an argument to the callback method (buttonPressed:).
Just implement it in such manner:
- (void)buttonPressed:(UIButton *)senderButton {
UIImage *image = [senderButton backgroundImageForState:UIControlStateNormal];
//use image:)
}
You could give each button a tag, and then use the -(void)buttonPressed: posted earlier. With that function, you could do something like:
- (void)buttonPressed:(UIButton *)senderButton
{
if (senderButton.tag == 0) {
// perform segue
} else if (senderButton.tag == 1) {
// perform other segue
}
}
And so on, and so forth.
I hope that helps!
Related
I have an array of UIButtons in the following code. Problem I'm having is that I need a unique method associated with each button. At the moment any button that's pressed all use the action:#selector(buttonPressed:)
I'm stuck on how to have a method hooked up to each button.
// Create buttons
NSMutableArray* buttonArray = [NSMutableArray array];
NSArray * myImages = [NSArray arrayWithObjects:#"category-cafe-unsel.png", #"category-food-unsel.png", #"category-clothing-unsel.png", #"category-health-unsel.png", #"category-tech-unsel_phone.png" , #"category-tech2-unsel.png", #"catefory-theatre-unsel.png", #"category-travel-unsel.png", nil];
// only create the amount of buttons based on the image array count
for(int i = 0;i < [myImages count]; i++)
{
// Custom UIButton
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setFrame:CGRectMake(0.0f, 20.0f, 52.0f, 52.0f)];
[btn setTitle:[NSString stringWithFormat:#"Button %d", i] forState:UIControlStateNormal];
[btn setImage:[UIImage imageNamed:[myImages objectAtIndex:i]] forState:UIControlStateNormal];
[btn addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[buttonArray addObject:btn];
}
thanks for any help
:)
Best option is to use same method for all buttons.For that you should use tags. So each button has its own tag.
btn.tag = i;
Here tag number will be used for differentiating which button was called.
And then in the method you can get the tags, this can also be done with a switch-statement:
-(void)buttonPressed:(UIButton*)sender
{
if( sender.tag == 1 ){
} else {
}
}
Use following code:
-(void)buttonPressed:(UIButton*)sender
{
UIButton *btn = sender;
for(int i = 0;i < [myImages count]; i++)
{
if (i == [btn tag]) {
//Your code
break;
}
}
}
It's completly working fine. When you'll get Tag value, you can perform operations as per tag value.
Thanks,
Hemang.
[btn addTarget:self action:#selector(NSSelectorFromString([NSString stringWithFormat:#"button%d", i])) forControlEvents:UIControlEventTouchUpInside];
And the corresponding actions would be:
-(void)button1:(UIButton*)sender
-(void)button2:(UIButton*)sender
-(void)button3:(UIButton*)sender
-(void)button4:(UIButton*)sender
and so forth.
However, alternatively consider having one action method only and using tags to separate the buttons within the action method.
I Follow the comment and try to fix my problem,but still not working.
when i run the test demo on the simulator,i get this:
run the demo project view
and i click the test2, i want to change button title before clear the button title, but i
get this :
after i click test2 button
i can not clear the button title when click another button.
anyone can help ??
Here is my code
-(void)addbutton
{
for (int i=0; i<3; i++)
{
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake((i*100), 0, 100, 100)];
button.titleLabel.text = #"";
[button setTag:i];
[button setTitle:[self.demoDataArray objectAtIndex:i] forState:UIControlStateNormal];
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
button.backgroundColor = [UIColor clearColor];
[button addTarget:self action:#selector(setButtonTitle:) forControlEvents:UIControlEventTouchUpInside];
[self.demoView addSubview:button];
}
}
-(IBAction)setButtonTitle:(id)sender
{
if ([sender tag] == 0)
{
self.demoDataArray = [[NSArray alloc] initWithObjects:#"test5", #"test6", #"test7", #"test8", nil];
[self addbutton];
}
else if([sender tag] == 1)
{
self.demoDataArray = [[NSArray alloc] initWithObjects:#"test9", #"test10", #"test11", #"test12", nil];
[self addbutton];
}
else if([sender tag] == 3)
{
self.demoDataArray = [[NSArray alloc]initWithObjects:#"test13", #"test14", #"test15", #"test16", nil];
[self addbutton];
}
}
Every time any button is pressed, you instantiate new buttons and add them on top of the other ones. You probably want to just update the existing buttons. Try this for your -addButton method instead:
-(void)addbutton
{
for (int i=0;i<3;i++)
{
NSInteger tag = i+1;
UIButton *button = (UIButton *)[self.view viewWithTag:tag];
if (!button)
{
button = [[UIButton alloc] initWithFrame:CGRectMake((i*100), 0, 100, 100)];
[button addTarget:self action:#selector(setButtonTitle:) forControlEvents:UIControlEventTouchUpInside];
[button setTag:tag];
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
button.backgroundColor = [UIColor clearColor];
[self.demoView addSubview:button];
}
button.titleLabel.text = #""; // Not actually sure you need this...
NSString *titleText = nil;
if (i < self.demoDataArray.count)
titleText = [self.demoDataArray objectAtIndex:i];
[button setTitle:titleText forState:UIControlStateNormal];
}
}
Now the button is instantiated, given a target and action, tagged, and added into the button hierarchy only when it doesn't already exist. Every time a button is tapped after that, only the titles will be updated.
Also, very important:: in order for -viewWithTag: to work, you have to use a tag for your buttons that is not equal to 0, the default tag - otherwise the button's superview will be returned. This means you'll need to make the following changes in your button handler, which already had a bug with checking the tags (checking against 3 rather than 2). Increment the tags to start at 1 and end with 3 like so:
-(IBAction)setButtonTitle:(id)sender
{
if ([sender tag] == 1)
{
self.demoDataArray = [[NSArray alloc] initWithObjects:#"test5",#"test6",#"test7",#"test8", nil];
[self addbutton];
}
else if([sender tag] == 2)
{
self.demoDataArray = [[NSArray alloc] initWithObjects:#"test9",#"test10",#"test11",#"test12", nil];
[self addbutton];
}
else if([sender tag] == 3)
{
self.demoDataArray = [[NSArray alloc]initWithObjects:#"test13",#"test14",#"test15",#"test16", nil];
[self addbutton];
}
}
That method could use some cleanup as well to eliminate duplicated code and it's probably more appropriate to use a switch statement here anyways. But that's neither here nor there.
OK, this should probably get you up and running. I didn't test or compile this so if you do have some problem with the compiler that you're not able to work through on your own please let me know and I'll see if I can spot the issue.
try this
- (IBAction)firstbtn:(UIButton *)sender {
[secondbtn setTitle:#"" forState:UIControlStateNormal];
}
I have a custom ImagePicker. A UIScrollView with images from my NSDocumentDirectory then I added the button as my images' frame, Like a thumbnail View. What I added is when It is selected then dismissed, the next time the view loads/appears/shows it will have an image checkmark already. It was okay. But what I need is, when I tap an image it will be selected already or the image "checkmark" will be shown, then when I tap the same image the checkmark will be gone.
Here is an explanation of the codes I have:
// The UISCrollView
- (void)viewDidLoad {
// Create view
UIScrollView *view = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0f,0.0f,1024.0f,768.0f)];
int row = 0;
int column = 0;
for(int i = 0; i < _thumbs.count; ++i) {
UIImage *thumb = [_thumbs objectAtIndex:i];
myButton = [UIButton buttonWithType:UIButtonTypeCustom];
myButton.frame = CGRectMake(column*140+24, row*150+10, 100, 100);
[myButton setImage:thumb forState:UIControlStateNormal];
[myButton addTarget:self
action:#selector(buttonClicked:)
forControlEvents:UIControlEventTouchUpInside];
myButton.tag = i;
NSLog(#"%i",i);
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSInteger selectedImageSlot1 = [prefs integerForKey:#"selected1"];
if ( selectedImageSlot1 == i){
[self turnButtonToSelected];
}
}
// When button is tapped
- (IBAction)buttonClicked:(id)sender {
myButton = (UIButton *)sender;
self.selectedImage = [_images objectAtIndex:myButton.tag];
[[NSUserDefaults standardUserDefaults] setInteger:myButton.tag forKey:#"selected1"];
[self dismissModalViewControllerAnimated:NO];
}
// method when button is selected
- (void)turnButtonToSelected
{
UIImage *bgImage = [UIImage imageNamed:#"Checkmark.png"];
[myButton setBackgroundImage:bgImage forState:UIControlStateNormal];
[myButton setBackgroundImage:bgImage forState:UIControlStateHighlighted];
[myButton setBackgroundImage:bgImage forState:UIControlStateDisabled];
[myButton setEnabled:NO];
}
First u need to keep the selected image index around, so create a selectedImageIndex instance variable.
Then in viewDidLoad there is no need to call
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSInteger selectedImageSlot1 = [prefs integerForKey:#"selected1"];
in the for loop...
Put it before the for loop and store the selected image index in selectedImageIndex.
- (void)viewDidLoad {
// Create view
UIScrollView *view = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0f,0.0f,1024.0f,768.0f)];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
self.selectedImageIndex = [prefs integerForKey:#"selected1"];
int row = 0;
int column = 0;
for(int i = 0; i < _thumbs.count+1; ++i) {
UIImage *thumb = [_thumbs objectAtIndex:i];
myButton = [UIButton buttonWithType:UIButtonTypeCustom];
myButton.frame = CGRectMake(column*140+24, row*150+10, 100, 100);
[myButton setImage:thumb forState:UIControlStateNormal];
[myButton addTarget:self
action:#selector(buttonClicked:)
forControlEvents:UIControlEventTouchUpInside];
myButton.tag = i+1;
NSLog(#"%i",i);
if (self.selectedImageIndex == myButton.tag){
[self turnButtonToSelected:myButton];
}
}
Remove the line [myButton setEnabled:NO]; from turnButtonToSelected so that the user can re-tap on the button to deselect it. change turnButtonToSelected to:
- (void)turnButtonToSelected:(UIButton *)button
{
UIImage *bgImage = [UIImage imageNamed:#"Checkmark.png"];
[button setBackgroundImage:bgImage forState:UIControlStateNormal];
[button setBackgroundImage:bgImage forState:UIControlStateHighlighted];
[button setBackgroundImage:bgImage forState:UIControlStateDisabled];
}
- (void)turnButtonToDeselected:(UIButton *)button
{
UIImage *bgImage = [UIImage imageNamed:#"Not-Checkmark.png"];
[button setBackgroundImage:bgImage forState:UIControlStateNormal];
[button setBackgroundImage:bgImage forState:UIControlStateHighlighted];
[button setBackgroundImage:bgImage forState:UIControlStateDisabled];
}
Then when user tap on an image, u check if this image is currently selected.
If yes - u call turnButtonToDeselected.
If no - u call turnButtonToSelected
- (IBAction)buttonClicked:(id)sender {
myButton = (UIButton *)sender;
self.selectedImage = [_images objectAtIndex:myButton.tag - 1];
[[NSUserDefaults standardUserDefaults] setInteger:myButton.tag forKey:#"selected1"];
if (myButton.tag == self.selectedImageIndex) {
// user tap on a button that was selected, so we need to deselect it
[self turnButtonToDeselected:myButton];
}
else {
// user tap on a button that wasn't selected
// first we check if there is a selected button, if yes we need to deselect it
if (self.selectedImageIndex > 0) {
// get the selected button
UIButton *selectedButton = (UIButton *)[self.view viewWithTag:self.selectedImageIndex];
// deselect it
[self turnButtonToDeselected:selectedButton];
}
// now we can select the button the user tapped on
[self turnButtonToSelected:myButton];
// save the selected index
self.selectedImageIndex = myButton.tag;
}
}
One more thing, in viewDidLoad set the button tag to i+1
Keep a Boolean value for if the button is selected or not. In your interface keep a boolean variable named BOOL selected; Keep track of the value, and manage to save it. Then in your turnButtonToSelected method add this:
- (void)turnButtonToSelected
{
selected = !selected;
if (selected)
{
UIImage *bgImage = [UIImage imageNamed:#"Checkmark.png"];
[myButton setBackgroundImage:bgImage forState:UIControlStateNormal];
[myButton setBackgroundImage:bgImage forState:UIControlStateHighlighted];
[myButton setBackgroundImage:bgImage forState:UIControlStateDisabled];
}
else
{
// set button image without the check mark
}
}
This will make sure, if the button was selected previously and now tapped again the checkmark
will be gone.
you need to create button array.And when button click event you need to check button have set checkmark image or not.
-(IBAction)buttonclickevent:(id)sender{
UIButton *btn=sender;
UIButton *currentbutton=[ButtonArray objectAtIndex:btn.tag];
if([currentbutton.currentImage isEqual:[UIImage imageNamed:#"Checkmark.png"]])
[currentbutton setImage:[UIImage imageNamed:#"normal.png"]forState:UIControlStateNormal];
}
else {
[currentbutton setImage:[UIImage imageNamed:#"Checkmark.png"]forState:UIControlStateNormal];
}
}
-(void)setButtons_AsPerTheMatrixSelection
{
for(UIView *subview in [viewWithButtons subviews])
{
if ([subview isKindOfClass:[UIButton class]])
{
[subview removeFromSuperview];
}
}
viewWithButtons = [[UIView alloc] init];
width = 48;
height = 48;
pw = 49;
ph = 49;
arrButton = [[NSMutableArray alloc] init];
UIImage *imgDefaultBG = [UIImage imageNamed:#"bg.jpg"];
viewWithButtons.frame = CGRectMake(50, 40, 200, 260);
ch = 4;
cv = 4;
for ( i = 0 ; i < cv ; ++i )
{
for ( j = 0 ; j < ch ; ++j )
{
btnMatrix = [[[UIButton alloc] initWithFrame:CGRectMake(10+pw*j, 51+ph*i, width, height)] autorelease];
btnMatrix.tag = i*ch+j;
btnMatrix.userInteractionEnabled = TRUE;
bulImageStatus = FALSE;
[btnMatrix addTarget:self action:#selector(changeImage:) forControlEvents:UIControlEventTouchDown];
[btnMatrix setBackgroundImage:imgDefaultBG forState:UIControlStateNormal];
[viewWithButtons addSubview:btnMatrix];
[arrButton addObject:btnMatrix];
}
}
NSLog(#"arrButton object count is:--> %d",[arrButton count]);
[self.view addSubview:viewWithButtons];
}
-(void)AddImageToArray
{
arr_FirstSet = [[NSMutableArray alloc] init];
NSString *strImageName;
if(appDelegate.intCategoryBtnTag == 0)
{
for (intimg = 1; intimg <= 28; intimg++)
{
strImageName = [NSString stringWithFormat:#"%d_1.png",intimg];
NSLog(#"strImageName is :--> %#",strImageName);
[arr_FirstSet addObject:strImageName];
}
NSLog(#"arr_FirstSet objects are...%#",arr_FirstSet);
}
}
-(void)changeImage:(id)sender
{
UIImage *img;
NSString *strImageName;
strImageName = [arr_FirstSet objectAtIndex:arc4random() % [arr_FirstSet count]/2];
NSLog(#"btnMatrix is:--> %#",strImageName);
img = [UIImage imageNamed:strImageName];
//[btnMatrix setImage:img forState:UIControlEventTouchDown];
NSLog(#"sender detail is:--> %#",sender);
[sender setBackgroundImage:img forState:UIControlStateHighlighted];
}
This is my code to set the dynamic buttons in "setButtons_AsPerTheMatrixSelection" method,
"AddImageToArray" method is used to add images from bundle to NSMutableArray (arr_FirstSet) one by one.
"changeImage" method is used to set the background of particular button.
I am able to set the images as background to the buttons randomly,
But the main problem is that i have to set fixed dynamic image to particular button.
right now on each click of particular button i am getting changed random image when i press it once, twice, thrice etc...
I have to set any particular image which is generated randomly in the "changeImage" to single button & rest to the other buttons single-single.
Then i have to check if two buttons have same background then these two buttons will be removed from the matrix.
Please guide me for the mistake i am doing & help me.
//Please replace this method
-(void)changeImage:(UIButton *)sender
{
UIImage *img;
NSString *strImageName;
strImageName = [arr_FirstSet objectAtIndex:arc4random() % [arr_FirstSet count]/2];
img = [UIImage imageNamed:strImageName];
//for the first time sender.imageView.image property will be null then only we set image to the button.
//For second click this condition fails and does not set the other image.
if(!sender.imageView.image)
{
[sender setImage:img forState:UIControlStateHighlighted];
[sender setImage:img forState:UIControlStateSelected];
}
// Calling a method to check if two images of buttons are same.
[self checkIfTwoImagesAreSame:sender];
}
//And Add this method
- (void)checkIfTwoImagesAreSameImageMaching:(UIButton *)sender
{
for(UIView *subview in [viewWithButtons subviews])
{
if ([subview isKindOfClass:[UIButton class]])
{
UIButton *btn = (UIButton *)subview;
// This condition is comparing clicked button image with all the buttons images of the viewWithButtons view if it isEqual:
if(sender.imageView.image && btn.imageView.image && [sender.imageView.image isEqual:btn.imageView.image])
{
// this is checking if the clicked button is not comparing with itself
if(btn.tag != sender.tag)
{
[btn removeFromSuperview];
[sender removeFromSuperview];
// OR
// btn.selected = YES;
// sender.selected = YES;
// OR
// btn.hidden = YES;
// sender.hidden = YES;
}
}
}
}
}
I have a problem with adding a set of UIButtons to a UIScrollView. With the buttons added it seems that the scroll command is not being passed to the scroll view as the buttons cover the whole surface. I've read various posts on this but still can't figure it out. I'm pretty new to iPhone programming so there's probably something obvious I've missed. I've tried things like canCancelContentTouches and delaysContentTouches to TRUE and FALSE.
Here is the code I use to add the buttons to the UIScrollView. The UIScrollView was created in IB and is passed in to the function:
-(void)drawCharacters:(NSMutableArray *)chars:(UIScrollView *)target_view {
//NSLog(#"CLEARING PREVIOUS BUTTONS");
//clear previous buttons for parts/kanji
if(target_view == viewParts){
for (UIButton *btn in parts_buttons) {
[btn removeFromSuperview];
}
[parts_buttons removeAllObjects];
} else if(target_view == viewKanji){
for (UIButton *btn in kanji_buttons) {
[btn removeFromSuperview];
}
[kanji_buttons removeAllObjects];
}
//display options
int chars_per_line = 9; //change this to change the number of chars displayed on each line
if(target_view == viewKanji){
chars_per_line = 8;
}
int char_gap = 0; //change this to change the margin between chars
int char_dimensions = (320/chars_per_line)-(char_gap*2);
//set starting x, y coords
int x = 0, y = 0;
//increment y coord
y += char_gap;
//NSLog(#"ABOUT TO DRAW FIRST BUTTON");
for(NSMutableArray *char_arr in chars){
//increment x coord
x += char_gap;
//draw at x and y
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
myButton.frame = CGRectMake(x, y, char_dimensions, char_dimensions); // position in the parent view and set the size of the button
[myButton setTitle:[char_arr objectAtIndex:0] forState:UIControlStateNormal];
[myButton setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];
[myButton setTitleColor:[UIColor colorWithRed:0.8 green:0.8 blue:0.8 alpha:1.0] forState:UIControlStateDisabled];
myButton.titleLabel.font = [UIFont boldSystemFontOfSize:22];
if(target_view == viewKanji){
myButton.titleLabel.font = [UIFont boldSystemFontOfSize:30];
}
// add targets and actions
if(target_view == viewParts){
[myButton addTarget:self action:#selector(partSelected:) forControlEvents:UIControlEventTouchUpInside];
} else if(target_view == viewKanji){
[myButton addTarget:self action:#selector(kanjiSelected:) forControlEvents:UIControlEventTouchUpInside];
[myButton setTag:(int)[char_arr objectAtIndex:1]];
}
//if the part isnt in the current list of kanji, disable and dim it
if(target_view == viewParts){
if([kanji count] > 0){
[myButton setEnabled:NO];
}
bool do_break = NO;
for(NSMutableArray *arr in kanji){
//NSLog([NSString stringWithFormat:#"CHECKING PARTS AGAINST %d KANJI", [kanji count]]);
for(NSString *str in [[arr objectAtIndex:2] componentsSeparatedByString:#" "]){
if(([myButton.titleLabel.text isEqualToString:str])){
//NSLog(#"--------------MATCH!!!-----------------");
[myButton setEnabled:YES];
for(NSString *str1 in parts_selected){
if(([myButton.titleLabel.text isEqualToString:str1])){
[myButton setEnabled:NO];
break;
}
}
do_break = YES;
break;
}
if(do_break) break;
}
if(do_break) break;
}
}
// add to a view
[target_view addSubview:myButton];
//update coords of next button
x += char_dimensions+ char_gap;
if (x > (320-char_dimensions)) {
x = 0;
y += char_dimensions + (char_gap*2);
}
//add button to global array to be removed from view next update
if(target_view == viewParts){
[parts_buttons addObject:myButton];
} else if(target_view == viewKanji){
[kanji_buttons addObject:myButton];
}
}
//NSLog(#"FINISHED DRAWING ALL BUTTONS");
}
Any help on this would be greatly appreciated. I just need to fix this to finish my app.
You cannot expect the scrollview to receive events if the buttons cover the whole surface.(They are going to be first in the responder chain). The quick fix would be to make the buttons slightly smaller than the scrollview.
On first read of this problem I was thinking that you wanted to add buttons to the scrollview's superview -- but then I realized you actually want the buttons in the scrollview.