Can't set UIButton.highlighted to NO - objective-c

I have a UITableViewCell with UIButton in each cell. When the button is pressed I set its state to highlighted like in this answer:
[self performSelector:#selector(doHighlight:) withObject:[cell.subviews objectAtIndex:2] afterDelay:0.0];
Then I do this:
- (void)doHighlight:(UIButton *)sender {
if (sender.highlighted) {
[sender setHighlighted:NO];
} else {
[sender setHighlighted:YES];
}
}
But the button not only is just not highlighted at all, not speaking about the fact that I should be able to UNhighlight it.
Any ideas on what is wrong?

I ended up using UIButton's selected property. It does not require any delay and it works brilliantly with this type of things:
if (!sender.selected) {
[sender setSelected:YES];
[cell addSubview:hiddenButton];
[self performSelector:#selector(doHighlight:) withObject:sender];
} else {
[sender setSelected:NO];
[self performSelector:#selector(doUnHighlight:) withObject:sender];
}

Here is a possible solution you are looking for. I have modified my answer
UIButton *button=[cell.subviews objectAtIndex:2];
//I am adding these five lines to ensure the different
//states of the button to achieve your highlighted state goal.
UIImage *highlightImage = [UIImage imageNamed:#"highlight.png"];//Also used when button is selected
UIImage *normalImage = [UIImage imageNamed:#"normal.png"];
[button setBackgroundImage:normalImage forState:(UIControlStateHighlighted)];
[button setBackgroundImage:highlightImage forState:(UIControlStateSelected)];
[button setBackgroundImage:normalImage forState:UIControlStateNormal];
[self performSelector:#selector(doHighlight:) withObject:[cell.subviews objectAtIndex:2]];
-(IBAction) doHighlight:(id)sender
{
if ([sender isKindOfClass:[UIButton class]])
{
UIButton *btn=(UIButton*)sender;
if (btn.isSelected) {
[btn setSelected:NO];
}
else
{
[btn setSelected:YES];
}
}
}

Related

UICollectionViewCell with UIButton radio button - one radioButton selected at time

I have UICollectionView with UIButton as a radio Button in UICollectionViewCell.xib.
I need one radioButton selected at time, if next was pressed, previous should be deselected. I will appreciate help.
//Loading radio button when view loads
-(void)setRadioButton{
if (!self.product.isSelectedCell) {
[self.radioBtn setBackgroundImage:[UIImage imageNamed:#"radio-button"] forState:UIControlStateNormal];
}
else
{
[self.radioBtn setBackgroundImage:[UIImage imageNamed:#"radio-button-select"] forState:UIControlStateNormal];
}
}
//Action for radio button
- (IBAction)radioBtnAction:(UIButton*)sender {
if([self.radioBtn isSelected]==YES)
{
[self.radioBtn setBackgroundImage:[UIImage imageNamed:#"radio-button-select"] forState:UIControlStateNormal];
}
else{
//always calls else
[self.radioBtn setBackgroundImage:[UIImage imageNamed:#"radio-button"] forState:UIControlStateNormal];
}
}
Use this code in cellForRowAtIndexPath
UIButton *radioButton = (UIButton *) [cell.contentView viewWithTag:kRadioButtonTag]; // Radio button
[radioButton setImage:[UIImage imageNamed:#"radio_unselected"] forState:UIControlStateNormal];
[radioButton setImage:[UIImage imageNamed:#"RadioSelected"] forState:UIControlStateSelected];
[radioButton addTarget:self action:#selector(radioButtonPressed:) forControlEvents:UIControlEventTouchDown];
if(indexPath == selectedIndexPath)
[radioButton setImage:[UIImage imageNamed:#"RadioSelected"] forState:UIControlStateSelected];
else
[radioButton setImage:[UIImage imageNamed:#"radio_unselected"] forState:UIControlStateNormal];
Radio button taped from table cell and get index path of that button
Take on class Lebel NSIndexPath variable and store selected index path.
- (void)radioButtonPressed:(UIButton *)sender {
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:tableView];
NSIndexPath *indexPath = [tableView indexPathForRowAtPoint:buttonPosition];
if (indexPath != nil) {
selectedIndexPath = indexPath
[tableView reloadData];
}
}
Hope this will help

Remove Buttons Dynamically with an Array

I have a view that has labels being dynamically added by the user. If the use would like to edit any of the labels, they press a button and all the labels get highlighted with a delete button and move button. (Editing is another bridge I’ll cross later).
My issue is: What is the best way to turn the buttons on and off? I have a method that turns the buttons on… but I am at a loss as to how I turn them off when done editing. Do I need to tag my buttons and then just ‘hide them’? Or do I just remove them all totally? How do I parse all the buttons that are turned on then, turn them off. Do I need to put them in an array as well? The labels are tagged with unique numbers so I know which label is which.
Any thoughts? Guidance? If I am doing it all wrong please tell me.
Here is a couple methods I have:
- (void) showEditableText {
// Parse the array of labels
if(textArray.count > 0){
for(UILabel *label in textArray){
//Add Delete Button
UIImage * delButtonImage = [UIImage imageNamed:#"GUI_Delete.png"];
UIButton * delThisButton = [[UIButton alloc] initWithFrame:CGRectMake(label.frame.origin.x - delButtonImage.size.width, label.frame.origin.y - delButtonImage.size.height, delButtonImage.size.width, delButtonImage.size.height)];
[delThisButton setBackgroundImage:delButtonImage forState:UIControlStateNormal];
[delThisButton addTarget:self action:#selector(deleteThisLabel:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:delThisButton];
//Add a move button
UIImage * moveButtonImage = [UIImage imageNamed:#"GUI_Move.png"];
UIButton * moveThisButton = [[UIButton alloc] initWithFrame:CGRectMake((label.frame.origin.x + label.frame.size.width + moveButtonImage.size.width), label.frame.origin.y - moveButtonImage.size.height, moveButtonImage.size.width, moveButtonImage.size.height)];
[moveThisButton setBackgroundImage:moveButtonImage forState:UIControlStateNormal];
[moveThisButton addTarget:self action:#selector(moveThisLabel:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:moveThisButton];
//Make the text highlighed
label.highlighted = YES;
label.backgroundColor = [UIColor colorWithRed:203/255.0f green:230/255.0f blue:239/255.0f alpha:1];
label.highlightedTextColor = [UIColor redColor];
}
}
}
- (void) doneEditingText {
if(textArray.count > 0){
for(UILabel *label in textArray){
//THIS IS WHERE I AM STUCK? WHAT DO I DO?
label.highlighted = NO;
label.backgroundColor = [UIColor clearColor];
}
}
}
//inside your first method set the same tag to your all buttons
-(void) showEditableText {
........
.......
.......
delThisButton.tag = 10;
moveThisButton.tag = 10;
}
//inside your second method delete all the subviews using this tag as shown below..
-(void) doneEditingText {
if(textArray.count > 0){
for(UILabel *label in textArray){
..............................
//THIS IS WHERE I AM STUCK? WHAT DO I DO?
for (UIView *subview in [self.view subviews]) {
if (subview.tag == 10) {
[subview removeFromSuperview];
}
}
...............................
label.highlighted = NO;
label.backgroundColor = [UIColor clearColor];
}
}
}
Move all your buttons code to viewDidLoad, hide them (button.hidden = YES). When you start/finish editing your text, unhide and hide your buttons. You need to have an ivar to contain the buttons too. So add them in your .h file.
Try This
UIView * seletetButton = nil;
for (UIView * btn in self.view.subviews){
if ([btn isKindOfClass:[UIButton class]])
{
if (seletetButton.tag != btn.tag)
{
[btn removeFromSuperview];
}
}
}

Page redirection depending on the answer chosen using Objective-C

I probably deserve to get shot by good programmers and great minds alike right now because of how my current code looks like even if I'm a total noob at Objective-C. Anyway, I'm making a logo quiz wherein the questions are in random order, then for each question the choices are also in random order. Anyway, I already have this code below to check where the page should redirect when an answer is selected:
- (IBAction)answerA:(UIButton *)sender {
if(imgView.image == [UIImage imageNamed:#"1.png"])
{
if([btnA.titleLabel.text isEqualToString:#"1"])
{
[btnA addTarget:self action:#selector(correctView) forControlEvents:UIControlEventTouchUpInside];
}
else
{
[btnA addTarget:self action:#selector(wrongView) forControlEvents:UIControlEventTouchUpInside];
}
}
else if(imgView.image == [UIImage imageNamed:#"2.png"])
{
if([btnA.titleLabel.text isEqualToString:#"2"])
{
[btnA addTarget:self action:#selector(correctView) forControlEvents:UIControlEventTouchUpInside];
}
else
{
[btnA addTarget:self action:#selector(wrongView) forControlEvents:UIControlEventTouchUpInside];
}
}
- (IBAction)answerB:(UIButton *)sender {
if(imgView.image == [UIImage imageNamed:#"1.png"])
{
if([btnB.titleLabel.text isEqualToString:#"1"])
{
[btnB addTarget:self action:#selector(correctView) forControlEvents:UIControlEventTouchUpInside];
}
else
{
[btnB addTarget:self action:#selector(wrongView) forControlEvents:UIControlEventTouchUpInside];
}
}
else if(imgView.image == [UIImage imageNamed:#"2.png"])
{
if([btnB.titleLabel.text isEqualToString:#"2"])
{
[btnB addTarget:self action:#selector(correctView) forControlEvents:UIControlEventTouchUpInside];
}
else
{
[btnB addTarget:self action:#selector(wrongView) forControlEvents:UIControlEventTouchUpInside];
}
}
}
This works but the problem is, you have to click on the button twice for it to go to the corresponding page. I know that the problem is IBAction itself is already an event that triggers once the button is clicked, then I have the code inside the condition statements that would be only triggered if the button is clicked again. My question is, how can I modify this so that if the button is clicked once, it immediately checks for the current question then the correct answer?
Use following Code. I am writing one method only, you can write second.
- (IBAction)answerA:(UIButton *)sender {
if(imgView.image == [UIImage imageNamed:#"1.png"])
{
if([btnA.titleLabel.text isEqualToString:#"1"])
{
[self correctView];
}
else
{
[self wrongView];
}
}
else if(imgView.image == [UIImage imageNamed:#"2.png"])
{
if([btnA.titleLabel.text isEqualToString:#"2"])
{
[self correctView];
}
else
{
[self wrongView];
}
}
Instead of setting the button target/action:
[btnA addTarget:self action:#selector(correctView) forControlEvents:UIControlEventTouchUpInside];
which requires another button tap before correctView is invoked, why not call the method directly?
[self correctView];

iOS: Control two CheckBoxes

I have this code to control two check boxes (buttons customized):
- (IBAction) setCheckBox: (id) sender{
UIImage *selected = [UIImage imageNamed:#"checkbox_checked.png"];
UIImage *notSelected = [UIImage imageNamed:#"checkbox_unchecked.png"];
if ([sender isSelected])
{
[sender setImage:notSelected forState:UIControlStateNormal];
[sender setSelected:NO];
if ([sender tag] == 10) boolOne = FALSE;
if ([sender tag] == 11) boolTwo = FALSE;
}
else
{
[sender setImage:selected forState:UIControlStateSelected];
[sender setSelected:YES];
if ([sender tag] == 10) boolOne = TRUE;
if ([sender tag] == 11) boolTwo = TRUE;
}
}
You can see that this code control two checkboxes, when I press one it become checked and when I press another time it become unchecked.
Now I want change this code in this way:
In default checkbox with tag 10 is checked and when I press it, I haven't effects, but when I press checkbox with tag 11 it should be checked and checkbox 10 should be unchecked.
The checkbox should toggle the selection and also the bool value
if([sender isSelected])
return;
if([sender tag] == 11){
[sender setSelected:YES];
[checkbox10 setSelected:NO];
}
if ([sender tag] == 10) {
[sender setSelected:YES];
[checkbox11 setSelected:NO];
}
you can get checkbox by tag value like I assume checkbox are instance of uibutton so
UIButton *checkBox10 = (UIButton*)[self.view viewWithTag:10];
I hope you understand. Also set the images according to code.
If you want the behavior of radio buttons, you should probably use radio buttons instead of check boxes.
Assuming that you store your check boxes as instance variables named checkbox10 and checkbox11, this should solve your problem:
- (IBAction) setCheckBox: (id) sender{
UIImage *selected = [UIImage imageNamed:#"checkbox_checked.png"];
UIImage *notSelected = [UIImage imageNamed:#"checkbox_unchecked.png"];
if (![sender isSelected])
{
[sender setImage:notSelected forState:UIControlStateNormal];
[sender setSelected:YES];
if ([sender tag] == 10)
{
boolOne = YES;
boolTwo = NO;
[checkbox11 setImage:notSelected forState:UIControlStateNormal];
[checkbox11 setSelected:NO];
}
if ([sender tag] == 11)
{
boolTwo = YES;
boolOne = NO;
[checkbox10 setImage:notSelected forState:UIControlStateNormal];
[checkbox10 setSelected:NO];
}
}
}

Implementing toggle feature in a UIButton

I want to know how to add the toggling feature to a UIButton, something like the user taps a unselected button the button becomes selected and stays selected till the user taps it again there by making unselected like it was before.
I was thinking of making an IBAction which changes it from unselected to selected, how can I do that?
Heres what I tried:
-(IBAction)toggle {
//Toggle on implementation.
button.selected = YES;
button.highlighted = NO;
button.enabled = YES;
//Toggle off implementation.
if (button.highlighted == YES) {
button.selected = NO;
button.highlighted = YES;
button.enabled = NO;
}
}
Problem...
-(IBAction)toggleFav {
if (favButton == nil) {
UIImage *unselectedImage = [UIImage imageNamed:#"favUntapped.png"];
UIImage *selectedImage = [UIImage imageNamed:#"favTapped.png"];
[favButton setImage:unselectedImage forState:UIControlStateNormal];
[favButton setImage:selectedImage forState:UIControlStateSelected];
[favButton setFrame:CGRectMake(0, 0, 40, 40)];
}
if([favButton isSelected]){
//Add to menu.
[favButton setSelected:NO];
} else {
//Remove from menu.
[favButton setSelected:YES];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
UIImage *unselectedImage = [UIImage imageNamed:#"unselected.png"];
UIImage *selectedImage = [UIImage imageNamed:#"selected.png"];
UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom];
[b setBackgroundImage:unselectedImage forState:UIControlStateNormal];
[b setBackgroundImage:selectedImage forState:UIControlStateSelected];
[b addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[b setFrame:CGRectMake(0, 0, 40, 40)];
[cell.contentView addSubview:b];
}
return cell;
}
-(void) buttonPressed:(UIButton *)sender
{
if([sender isSelected]){
//...
[sender setSelected:NO];
} else {
//...
[sender setSelected:YES];
}
}
Your toggleFav code doesn't make much sense.
if (favButton == nil) { checks, if favButton is present. But if you are wiring it up with IB, it should always been there at that point. And if it wasn't how could the button call this method? So do it like this:
-(void)viewDidLoad
{
//....
UIImage *unselectedImage = [UIImage imageNamed:#"favUntapped.png"];
UIImage *selectedImage = [UIImage imageNamed:#"favTapped.png"];
[favButton setImage:unselectedImage forState:UIControlStateNormal];
[favButton setImage:selectedImage forState:UIControlStateSelected];
[favButton setFrame:CGRectMake(0, 0, 40, 40)];
//....
}
-(IBAction)toggleFav:(UIButton *)sender {
if([sender isSelected]){
//...
[sender setSelected:NO];
} else {
//...
[sender setSelected:YES];
}
}
Here you'll find an example project, with a DetaiView, that holds a Button with the 2 states.
Note: I am saving the information of what button was selected in the NSUserDefaults. You should not do that. Instead you'll want to save it in the model. But as I dont have informations on your model, I am just using NSUserDefaults.
-(void)hitButton:(UIButton*)button
{
buttonOnFlag = !buttonOnFlag;
if( buttonFlag )
[self performSelector:#selector(setHighlight:) withObject:button afterDelay:0];
}
- (void)setHighlight:(UIButton*)button
{
button.highlighted = true;
}
Use button.highlighted property
You should code like this:
-(IBAction)toggle:(id)sender {
//Toggle on implementation.
if (sender.highlighted == NO)
{
sender.selected = YES;
sender.highlighted = NO;
sender.enabled = YES;
}
//Toggle off implementation.
else{
sender.selected = NO;
sender.highlighted = YES;
sender.enabled = NO;
}
}