Using UiButtons populated with letters to make words - ios

I am creating a small game with an interface that is quite similar to 4 Pictures 1 word. The current setup so far is as follows:
The user gets a 7 letter word generated at random.
There is an array which takes the 7 letters and then randomly populates them with other letters in 12 programatically created UIButtons:
for (int i=0; i< buttonCount; i++) {
int xpositiong = x + 37;
x = xpositiong;
isSeven ++;
restAt7 ++;
NSString *stringFromInt = [NSString stringWithFormat:#"%#",[arrayForRound objectAtIndex:i]];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self
action:#selector(buttonSelected:)
forControlEvents:UIControlEventTouchDown];
[button setTitle:stringFromInt forState:UIControlStateNormal];
button.titleLabel.font = [UIFont fontWithName:#"helvetica" size:19];
button.tag = i+10;
_letterButton = button;
if (restAt7 == 7) {
x = 47;
}
if (isSeven <= 6) {
button.frame = CGRectMake(x,333,40,40);
}
else
{
button.frame = CGRectMake(x,370,40,40);
}
[self.view addSubview:button];
}
There is also a second area of Buttons however these are static and constitute as "the word". When one of the 12 letters are selected it takes the tag of the selected button and populates one of the corresponding "word" buttons.
-(void)buttonSelected : (UIButton *)sender
{
NSLog(#"sender %i", sender.tag);
UIButton *button = (UIButton *)[self.view viewWithTag:sender.tag];
button.hidden = YES;
if ([_buttonOne.titleLabel.text isEqualToString: #" "]) {
// NSLog(#"button is nil");
[_buttonOne setTitle:sender.titleLabel.text forState:UIControlStateNormal];
[_buttonOne setTag:button.tag];
}
else if ([_buttonTwo.titleLabel.text isEqualToString:#" "])
{
[_buttonTwo setTitle:sender.titleLabel.text forState:UIControlStateNormal];
}
else if ([_buttonThree.titleLabel.text isEqualToString:#" "])
{
[_buttonThree setTitle:sender.titleLabel.text forState:UIControlStateNormal];
}
else if ([_buttonFour.titleLabel.text isEqualToString:#" "])
{
[_buttonFour setTitle:sender.titleLabel.text forState:UIControlStateNormal];
}
else if ([_buttonFive.titleLabel.text isEqualToString:#" "])
{
[_buttonFive setTitle:sender.titleLabel.text forState:UIControlStateNormal];
}
else if ([_buttonSix.titleLabel.text isEqualToString:#" "])
{
[_buttonSix setTitle:sender.titleLabel.text forState:UIControlStateNormal];
}
else if ([_buttonSeven.titleLabel.text isEqualToString:#" "])
{
[_buttonSeven setTitle:sender.titleLabel.text forState:UIControlStateNormal];
}
}
Right! So here is my question. If the user decides they have selected the wrong letter and wish to remove that letter they can press one of the 7 buttons to delete that letter. However I dont know how to un-hide the corresponding button which was originally populated with the letter...
I am confident it has something to do with retaining the Tag of the selected button however because each of the 7 buttons is assigned with Tag's I am not sure how to go about doing it.
EDIT:
I'll post up the solution that has worked. Also all functions have been rewritten with loops.
-(void)buttonSelected : (UIButton *)sender
{
NSLog(#"sender %i", sender.tag);
UIButton *button = (UIButton *)[self.view viewWithTag:sender.tag];
button.hidden = YES;
for (int i = 0; i < _wordButtonsArray.count; i ++) {
UIButton *selectedButton = [_wordButtonsArray objectAtIndex:i];
if ([selectedButton.titleLabel.text isEqualToString:#" "]) {
[selectedButton setTitle:sender.titleLabel.text forState:UIControlStateNormal];
[selectedButton setTag:button.tag];
return;
}
}
[self checkIfAnswerIsFinished:sender];
}
- (IBAction)clearButton:(id)sender
{
UIButton *button = (UIButton *)[self.view viewWithTag:[sender tag]];
button.hidden = NO;
for (int i = 0; i < _wordButtonsArray.count; i ++) {
if (button == [_wordButtonsArray objectAtIndex:i]) {
[button setTitle:#" " forState:UIControlStateNormal];
for (int letterButtonsIndex = 0; letterButtonsIndex < _letterButtonsArray.count; letterButtonsIndex++) {
UIButton *letterButton = [_letterButtonsArray objectAtIndex:letterButtonsIndex];
if (button.tag == letterButton.tag) {
button.tag = i;
letterButton.hidden = NO;
}
}
}
}
}
Works like a charm!

It seems like one way to do this is to make an NSArray that has 7 spaces, each filled with either the tag of the source button or -1. If a user taps on a -1, do nothing. If it is a number, set that tagged item to visible.
Also, your code is terribly not DRY (Don't Repeat Yourself) - you should spend some time thinking about programming and how you could use data structures more nicely. If you want more definite advice, just ask in the comments and I'll edit. :)

I can think of a couple of ways to accomplish this.
Solution 1:
Add your 12 buttons (bottom section) to an NSArray so when the user presses one of the 7 buttons (top section) you can iterate through that array and compare the titles. Something like this:
for (UIButton *button in buttonsArray) {
NSString *buttonTitle = [button titleForState:UIControlStateNormal];
// I'm assuming here that you already have the touched button tile
if ([buttonTitle isEqualToString:touchedButtonTitle]) {
button.hidden = NO;
}
}
Solution 2:
Create an array of 7 elements where you can match the "word" buttons with the tags of your letter buttons. Something like this:
-(void)buttonSelected : (UIButton *)sender
{
NSLog(#"sender %i", sender.tag);
UIButton *button = (UIButton *)[self.view viewWithTag:sender.tag];
button.hidden = YES;
if ([_buttonOne.titleLabel.text isEqualToString: #" "]) {
// NSLog(#"button is nil");
[_buttonOne setTitle:sender.titleLabel.text forState:UIControlStateNormal];
[_buttonOne setTag:button.tag];
// you know this is object One. Insert tag at position zero (arrays are zero-based)
self.topButtonsArray insertObject:[NSNumber numberWithInt:sender.tag] atIndex:0];
}
.
.
.
Hope this helps!

Related

Change Button Text Color Programmatically for n number of buttons without changing Text Color of other button

I have n number of buttons in the scrollView. If click on a button its text color is changing but if I click another button the text color of the previous button remain unchanged. I want to change the previous button text color as default color while clicking another button. The behavior will be just like a segmented control. Please help me regarding this, I've providing my code below:
-(void) loadScrollView:(CGRect)scrollViewFrame withButtonArray:(NSArray*)buttonArray withCase: (int)ButtonCase
{
scrollView=[[UIScrollView alloc]initWithFrame:scrollViewFrame];
[scrollView setScrollEnabled:YES];
[scrollView setBackgroundColor:[UIColor blackColor]];
[scrollView setContentSize:CGSizeMake(100 * 768, 40)];
for (int i = 0; i < [buttonArray count]; i++)
{
adButtonOutLet = [[UIButton alloc] initWithFrame:CGRectMake(140*i, 0, 135, 40)];
if (ButtonCase==0) {
[adButtonOutLet setBackgroundColor:UIColorFromRGB(0X272c2f)];
[adButtonOutLet setTitleColor:UIColorFromRGB(0x969696) forState:UIControlStateNormal];
}
else
{
if (i==0) {
adButtonOutLet.backgroundColor=UIColorFromRGB(0x000000) ;
[adButtonOutLet setTitleColor:UIColorFromRGB(0x179d95) forState:UIControlStateNormal];
}
}
adButtonOutLet.titleLabel.font=[UIFont fontWithName:#"MyriadPro" size:14.0];
[adButtonOutLet setTitle:[buttonArray objectAtIndex:i] forState:UIControlStateNormal];
adButtonOutLet.userInteractionEnabled= YES;
[adButtonOutLet setTag:i];
[adButtonOutLet addTarget:self action:#selector(adButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[scrollView addSubview:adButtonOutLet];
[self.view addSubview:scrollView];
}
}
Here is my action method:
-(void)adButtonAction:(UIButton*)sender
{
for (int i = 0; i < [menuArray count]; i++)
{
int prevTag = 0;
if (sender.tag == i && Case==0)
{
[self reloadScrollViewwithButtonTag:i];
// [sender setSelected:YES];
sender.backgroundColor=UIColorFromRGB(0x000000) ;
[sender setTitleColor:UIColorFromRGB(0x179d95) forState:UIControlStateNormal];
prevTag=i;
}
if (Case==1) {
sender.backgroundColor=UIColorFromRGB(0x000000) ;
[sender setTitleColor:UIColorFromRGB(0x179d95) forState:UIControlStateNormal];
if (sender.tag==prevTag-1) {
[sender setBackgroundColor:UIColorFromRGB(0X272c2f)];
[sender setTitleColor:UIColorFromRGB(0x969696) forState:UIControlStateNormal];
}
}
}
}
Why don't you try changing all buttons style to no selected except the one that is on the sender parameter (selected button)?
-(void)adButtonAction:(UIButton*)sender{
for (int i = 0; i < [menuArray count]; i++)
{
if (sender == menuArray[i])
{
//Selected code style
}
else{
//No selected code style
}
}
}
Considering menuArray is an array with all buttons.
This way you check and modify all styles when a button is pressed.
Hope this could help you or at last give you a clue for resolve your problem.
I don' understand everything in your adButtonAction (what is menuArray?) method but I think what you need is simple, just adapt it to your method.
First create a NSMutableArray to keep reference on your button list:
for (int i = 0; i < [buttonArray count]; i++)
{
adButtonOutLet = [[UIButton alloc] initWithFrame:CGRectMake(140*i, 0, 135, 40)];
[myButtonArray addObject:adButtonOutlet];
....
Then in you action method, set the right color:
for (UIButton* b in myButtonArray){
if(b.tag == sender.tag){
[self setSelectedColor:YES forButton:b];
// Do what you want here
}
else{
[self setSelectedColor:NO forButton:b];
}
}
With:
-(void)setSelectedColor:(BOOL)selected forButton:(UIButton)button{
if(selected){
sender.backgroundColor=UIColorFromRGB(0x000000) ;
[sender setTitleColor:UIColorFromRGB(0x179d95) forState:UIControlStateNormal];
}
else{
[sender setBackgroundColor:UIColorFromRGB(0X272c2f)];
[sender setTitleColor:UIColorFromRGB(0x969696)forState:UIControlStateNormal];
}
}
Apply state vise( Normal,Selected ) title color of button.
Just persist a selected button reference as weak.
while user clicked on button set that button state as selected instead normal.
Change last selected button state Normal instead Selected.
Check out below code that will be help you
UIButton *selectedButton;
-(void)adButtonAction:(UIButton*)sender
{
UIButton *tempButton = sender;
if (selectedButton && selectedButton!=tempButton)
{
[selectedButton setSelected:NO];
}
[tempButton setSelected:YES];
selectedButton = tempButton;
}

Detect Selected State of UIButton iOS

How can I detect the selected state of a uibutton?
I have 7 buttons and I have made them to be able to toggle or select multiple buttons at a time.
I want to be able to tell which buttons are in a selected state when I push the done button.
So if M, T and W are selected then I want to be able to detect that when pushing done.
I currently put a tag on the button and then call a method to unselect or select multiple buttons.
self.repeatOccurrenceFrequencyWeeklyTF = [[UITextField alloc]init];
self.repeatOccurrenceFrequencyWeeklyTF.frame = CGRectMake(80, 80, 32, 32);
self.repeatOccurrenceFrequencyWeeklyTF.delegate = self;
self.repeatOccurrenceFrequencyWeeklyTF.background = [UIImage imageNamed:#"repeatWeekly"];
self.repeatOccurrenceFrequencyWeeklyTF.font = [UIFont fontWithName:#"SegoeWP" size:15];
self.repeatOccurrenceFrequencyWeeklyTF.textColor = [UIColor appGreyText];
[self.repeatOccurrenceFrequencyWeeklyTF setValue:[UIColor colorWithRed:153/255.0 green:153/255.0 blue:153/255.0 alpha:1.0] forKeyPath:#"_placeholderLabel.textColor"];
self.repeatOccurrenceFrequencyWeeklyTF.placeholder = #"1";
UIView *leftView1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 12, self.repeatOccurrenceFrequencyWeeklyTF.frame.size.height)];
self.repeatOccurrenceFrequencyWeeklyTF.leftView = leftView1;
self.repeatOccurrenceFrequencyWeeklyTF.leftViewMode = UITextFieldViewModeAlways;
self.repeatOccurrenceFrequencyWeeklyTF.rightViewMode = UITextFieldViewModeAlways;
self.keyboardToolbar = [self createInputToolbar];
self.repeatOccurrenceFrequencyWeeklyTF.inputAccessoryView = self.keyboardToolbar;
self.repeatOccurrenceFrequencyWeeklyTF.delegate = self;
self.repeatOccurrenceFrequencyWeeklyTF.keyboardType = UIKeyboardTypeNumberPad;
self.repeatOccurrenceFrequencyWeeklyTF.enabled = NO;
[self.view addSubview:self.repeatOccurrenceFrequencyWeeklyTF];
// Now, in your button action handler, you can do something like this:
- (void)mondayButtonTouch:(UIButton *)aButton withEvent:(UIEvent *)event
{
aButton.selected = !aButton.selected;
if(aButton.tag == 111) {
}
if(aButton.tag == 222) {
}
if(aButton.tag == 333) {
}
if(aButton.tag == 444) {
}
if(aButton.tag == 555) {
}
if(aButton.tag == 666) {
}
NSLog(#"dsfdfdfsdfs %ld", (long)aButton.tag);
[aButton setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected];
}
I would use a NS_ENUM (which helps to keep a nice and readable code) and a NSMutableArray to keep track of your selected buttons.
Declare a enum that looks something like this:
typedef NS_ENUM(NSInteger, Weekday) {
WeekdayMonday,
WeekdayTuesday,
WeekdayWednesday,
WeekdayThursday,
WeekdayFriday,
WeekdaySaturday,
WeekdaySunday
};
Then tag your buttons with the correct enum:
tuesdayButton.tag = WeekdayTuesday;
And check when you tap button if your enum exists in your array:
- (void)buttonTouch:(UIButton *)aButton withEvent:(UIEvent *)event
{
if ([array containsObject:#(aButton.tag)]){ //exists, remove it from array
[array removeObjectIdenticalTo:#(aButton.tag)];
}
}else{
[array addObject:#(aButton.tag)];
}
}
A possibility is to create an NSMutableArray named selectedButton. Do like this:
- (void)mondayButtonTouch:(UIButton *)aButton withEvent:(UIEvent *)event
{
aButton.selected = !aButton.selected;
if(!aButton.selected && selectedButton.containsObject(aButton.Tag)) {
[selectedButton removeObject:aButton.tag];
}
else if(aButton.selected && !selectedButton.containsObject(aButton.Tag)) {
[selectedButton addObject:aButton.tag];
}
// do your stuff here
}
Now on done button click you have all the button thats tags are selected will be trackable with selectedButton array.
You can use:
[self.view viewWithTag:yourTagHere]
you can use this :
for (UIButton *btn in [self.view subviews]) { // self.view (change it with your button superview)
if ([btn isKindOfClass:[UIButton class]] && [btn isSelected] == YES) {
// here you found the button which is selected
}
}
[self.view viewWithTag:yourTagHere] replace

how to pass multiple tags to addTarget:action:forControlEvents?

I know the code i have written is wrong. but i want something like this. How to do it?
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
int totalcout = 0;
int passValue ;
for(int j=0; j<5; j++{
for(int i=0; i<5; i++)
{
totalcout++;
if(totalcount >1){
break;
}else{
passValue = i;
}
}
button.tag = j;
[button addTarget:self action:#selector(button:) forControlEvents:UIControlEventTouchUpInside];
}
- (IBAction) button:(UIButton *)sender {
NSLog(#"tag numbers are %d", sender.tag);
detailViewController.mutableArray1 = [oneMutableArray objectAtIndex:sender.tag];
detailViewController.mutableArray2 = [twoMutableArray objectAtIndex:passValue];
}
I hope the question is clear.
Thank you in advance
i got your question.. you can't directly assign two tags to any UIView or any subclass directly. but you can achieve indirectly
may this code helps to achieve your intension to get two tags at the end
#define First_Tag 100
#define Second_Tag 200
-(void)createButton
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.tag = ((First_Tag*10000)+30000)+(Second_Tag*10);
[button addTarget:self action:#selector(button:) forControlEvents:UIControlEventTouchUpInside];
}
- (void) button:(UIButton *)sender
{
int intTag2 = ((sender.tag-30000)%10000)/10;
int intTag1 = ((sender.tag-(intTag2*10))-30000)/10000;
NSLog(#"tag numbers are %d and %d", intTag1, intTag2);
}
I've used several big numbers to encode the tag .. hope it solves your problem to assign two tags

NSDictionary store the objects from the last array

I have created 3 buttons at my top.take the offset of them and giving them same IBAction.
I want to change images at below according to the which button is pressed.
Further i have to pass these images to the another ViewControler, Here
i have got 3 arrays named bundle1 , bundle2 , bundle3 . in each array i have set of 5 images, in my Viewdidload as below,
bundle1 = #[#"1.png",#"2.png", #"3.png", #"4.png" ,#"5.png"];
bundle2 = #[#"6.png", #"7.png", #"8.gif",#"9.jpeg", #"10.jpeg" ];
bundle3 = #[#"11.jpg", #"12.jpg" ,#"13.jpeg", #"14.jpeg", #"15.jpeg"];
now i had take mutabledictionary, which had upper 3 arrays and i had give them a specific key
as below.
mutdict = [[NSMutableDictionary alloc] initWithObjectsAndKeys: bundle1 , #"key1" , bundle2 , #"key2" , bundle3 , #"key3" ,nil];
Now below is the code for IBAction of Upper 3 buttons, (Which is the same for all 3 buttons).
-(IBAction)morebtn:(id)sender
{
for (UIView *subview in [scroll subviews])
{
[subview removeFromSuperview];
}
arraydata = [[NSMutableArray alloc] init];
if ([sender tag] == 1) {
NSLog(#"hey btn1 clicked");
for (UIImage *b in arraydata)
{
[arraydata removeAllObjects];
}
arraydata = [mutdict valueForKey:#"key1"];
}
if ([sender tag] == 2) {
NSLog(#"hey btn2 clicked");
for (UIImage*b in arraydata)
{
[arraydata removeAllObjects];
}
arraydata = [mutdict valueForKey:#"key2"];
}
if ([sender tag] == 3) {
NSLog(#"hey btn3 clicked");
for (UIImage*b in arraydata)
{
[arraydata removeAllObjects];
}
arraydata = [mutdict valueForKey:#"key3"];
}
int x=10,y=300;
for (int k=0; k<arraydata.count; k++) {
NSLog(#"main called");
UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom];
[btn setImage:[UIImage imageNamed:[arraydata objectAtIndex:k]] forState:UIControlStateNormal];
btn.tag=k;
btn.frame=CGRectMake(x, y, 100, 100);
[btn addTarget:self action:#selector(btn4images1:) forControlEvents:UIControlEventTouchUpInside];
x+=100;
scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 300, self.view.frame.size.width, 200)];
scroll.contentSize = CGSizeMake(self.view.frame.size.width , 200);
[scroll addSubview:btn];
[self.view addSubview:scroll];
}
}
in upper code i trace which button is pressed and according to it i wil give inages in my NSArray named arraydata.
when i first time click on the all 3 upper buttons they show me image related to their array, but when i second time click on button1 (placed on the top), The images related to button3 are also shown in the Buttonbackground (palced at below part).
so on clicking button1 in below part button background images are overlaped. Seems like my NSMutableDictionary stores the data of last array. don't know what exactly happen.

How to remove duplicate buttons

I created five buttons using for loop, it works well. Whenever i click restart button duplicate buttons created
-(void)buttonCreate {
for( int i = 0; i < 5; i++ )
{
oneBtn1 = [UIButton buttonWithType:UIButtonTypeCustom];
oneBtn1.frame = CGRectMake(316,i*-5+474,51,50);
[oneBtn1 setTag:i];
[oneBtn1 addTarget:self action:#selector(oneButton:) forControlEvents:UIControlEventTouchUpInside];
[oneBtn1 setImage:[UIImage imageNamed:#"1c.png"] forState:UIControlStateNormal];
[self.view addSubview:oneBtn1];
}
}
Restart button function:
-(void)restart {
[self buttonCreate];
}
I tried this one but it will remove only one button out of 5.
if(oneBtn1 != NULL) {
[oneBtn1 removeFromSuperview];
oneBtn1 = nil;
}
Problem is: How to remove duplicate buttons?
Create an array(NSMutableArray *buttonHolderArray) to hold outlets for all five buttons.
[buttonHolderArray addObject:oneBtn1];
Then you can remove/update the buttons as and when you need.
And once you dont want any button, empty the array itself. On top of this, if you wish to clear the view then simply call removeFromSuperView for all the buttons
I tried this one but it will remove only one button out of 5.
if(oneBtn1 != NULL) {
[oneBtn1 removeFromSuperview];
oneBtn1 = nil;
}
You are removing only one button, if you want to remove all then use
for ( UIButton *button in buttonHolderArray){
button removeFromSuperView];
}
You can remove by checking if the button is already created.
-(void)buttonCreate {
int tag_start = 500;
for( int i = 0; i < 5; i++ )
{
UIView * prevbtn = [self.view viewWithTag:tag_start + i];
if(prevbtn) {
[prevbtn removeFromSuperview];
}
oneBtn1 = [UIButton buttonWithType:UIButtonTypeCustom];
oneBtn1.frame = CGRectMake(316,i*-5+474,51,50);
[oneBtn1 setTag:tag_start + i];
[oneBtn1 addTarget:self action:#selector(oneButton:) forControlEvents:UIControlEventTouchUpInside];
[oneBtn1 setImage:[UIImage imageNamed:#"1c.png"] forState:UIControlStateNormal];
[self.view addSubview:oneBtn1];
}
}
use this before calling again restart method
for (UIButton *btn in self.view.subviews ) {
[btn removeFromSuperview];
}
Before the restart button clicked you can remove all the buttons from you view calling the method removeChildViewsWithKindOfClass
-(void)restart {
[self.view removeChildViewsWithKindOfClass:[UIButton class]];
[self buttonCreate];
}
-(void)removeChildViewsWithKindOfClass:(Class)classToRemove{
if (classToRemove==nil) return;
for (UIView *v in [self subviews]) {
if ([v isKindOfClass:classToRemove]) {
[v removeFromSuperview];
}
}
}
If you want to remove a specific button you can use the property tag that you have to set beforehand when you create your button and it allows you removing the button with a specific tag.

Resources