Unable to keep UIButton in selected state after TouchUpInside Event - iphone

I have the need for an UIButton to maintain a pressed state. Basically, if a button is in a normal state, I want to touch the button, it highlight to its standard blue color and then stay blue after lifting my finger.
I made the following UIAction and connected the buttons Touch Up Inside event to it.
-(IBAction) emergencyButtonPress:(id) sender
{
if(emergencyButton.highlighted)
{
emergencyButton.selected = NO;
emergencyButton.highlighted = NO;
}
else
{
emergencyButton.selected = YES;
emergencyButton.highlighted = YES;
}
}
But what happens, after I remove my finger, the button goes back to a white background. For a test I added a UISwitch and have it execute the same code:
-(IBAction) emergencySwitchClick:(id) sender
{
if(emergencyButton.highlighted)
{
emergencyButton.selected = NO;
emergencyButton.highlighted = NO;
}
else
{
emergencyButton.selected = YES;
emergencyButton.highlighted = YES;
}
}
In this case the button toggles to a highlighted and non-highlighted state as I would expect.
Is there another event happening after the Touch Up Inside event that is resetting the state back to 'normal'? How do I maintain the highlighted state?

The highlighted state is applied and removed by iOS when you touch / release the button. So don't depend on it in your action method.
As one of the other answers says, set the highlighted image to be the same as the selected image, and then modify your action method:
-(IBAction) emergencyButtonPress:(id) sender
{
emergencyButton.selected = !emergencyButton.selected;
}

If you want something like a toggle button, customize your "selected" state to be your "pressed" state, and then write something like this:
- (IBAction)buttonTapped:(id)sender {
[(UIButton*)sender setSelected:![sender isSelected]];
}

if you want the above code to work, you should set an image for the state selected and one (even the same) for he state highlighted.
[emergencyButton setBackgroundImage:buttonHighlightImage forState:UIControlStateHighlighted];
[emergencyButton setBackgroundImage:buttonHighlightImage forState:UIControlStateSelected];
hope it helps.

I had this same problem, and this is what worked for me:
-(IBAction)buttonPressed:(id)sender {
if (isSelected) {
[_button setSelected:NO];
[_button setImage:[UIImage imageNamed:#"not_selected.png"] forState:UIControlStateSelected];
isSelected=NO;
}
else {
[_button setSelected:YES];
[_button setImage:[UIImage imageNamed:#"selected.png"] forState:UIControlStateSelected];
isSelected=YES;
}
}

This is not possible unfortunately, as soon as you let go Apple changes the state again.
One option I've used before (but not pretty) is that you use a performSelector with delay 0.1 after the button is pressed to put it again in the selected state. This did work in my case.
EDIT: If you don't want to see the blinking effect, just set the delay to 0.0

This worked for me:
- (void)tapButton:(id)sender{
UIButton *button = sender;
if (!button.selected){
[self performSelector:#selector(highlight:) withObject:button afterDelay:0.0];
}else{
[self performSelector:#selector(removeHighlight:) withObject:button afterDelay:0.0];
}
}
- (void)highlight:(UIButton *)button{
button.selected = !button.selected;
button.highlighted = YES;
}
- (void)removeHighlight:(UIButton *)button{
button.selected = !button.selected;
button.highlighted = NO;
}

Try this simple answer....
- (void)mybutton:(id)sender
{
UIButton *button = (UIButton *)sender;
button.selected = ![button isSelected]; // Important line
if (button.selected)
{
NSLog(#"Selected");
NSLog(#"%i",button.tag);
}
else
{
NSLog(#"Un Selected");
NSLog(#"%i",button.tag);
}
}

Related

how to create id sender button inside button in iphone

I am new to iPhone programming.I have taken one button inside that, I have created another button programmatically with id sender ,I want to use multiple buttons inside that id sender button using tags.Now I did some coding but it is showing some Exception.When i am giving [self somemethodname:(id)sender]; here I am getting problem, actually [self playOrPause] this one I have used in another button.How to slove this please any body tell me.
Thanks
- (void)playOrPause
{
UIButton *aa = [UIButton buttonWithType:UIButtonTypeCustom];
[aa addTarget:self action:#selector(play:)forControlEvents:UIControlEventTouchUpInside];
NSLog(#"hi iam 2");
[self play:(id)sender];
}
-(void)play:(id)sender
{
UIButton *instanceButton = (UIButton*)sender;
instanceButton.tag++;
if (instanceButton.tag == 1)
{
NSLog(#"hi");
} else if (instanceButton.tag == 2)
{
NSLog(#"hi2");
}
}

Distinguish if UIsegmentedontrol value change is from user or from system

Hello I have a UISegmentedControl with two segments. The selected segment is modified programmatically in some case and by the user in some other. I only want to trigger the selector when the change is due to a user action(only when user actually press the segmented control and not when the system do segmentedControl.selectedSegmentIndex = ...). Any idea?
If you do
[self.segment setSelectedSegmentIndex:1];
This will not call the action of valueChanged on the segment, so what is your question?
[segmentedControl addTarget:self action:#selector(segmentAction:) forControlEvents: UIControlEventValueChanged];
- (IBAction)segmentAction:(id)sender {
// valuechanged connected function
UISegmentedControl *segControll = (UISegmentedControl *)sender;
if (segControll.tag == 0) {
}
else {
isProgramaticallyChanged = NO; //important
}
}

Changing UIImageView with button

I am wanting to press a button and alternate between two images with one UIImageView.
Right now when I run it, I press the button, the image changes but will not change back. What do I need to change in this action code to make it alternate?
- (IBAction)Change:(id)sender {
image.image = [UIImage imageNamed:#"car.png"];
}
Try following code :
- (IBAction)Change:(id)sender {
if ([sender isSelected])
{
imageView.image = [UIImage imageNamed:#"car.png"];
[sender setSelected:NO];
}
else
{
imageView.image = [UIImage imageNamed:#"bike.png"];
[sender setSelected:YES];
}
}
To Display sequence image on button click.
.h file :
int counter;
.m file :
in viewDidLoad initialize counter = 0
Then
- (IBAction)Change:(id)sender {
counter++;
imgView.image = [UIImage imageNamed:[NSString stringWithFormat:#"%d.png",counter]];
}
And give your image name like 1.png, 2.png, 3.png and so on...
You have to maintain a flag.
In Somewhere before tapping the button, assign the flag
BOOL isFirstImageShown=YES;
Then on your button action
- (IBAction)Change:(id)sender {
if(isFirstImageShown)
{
isFirstImageShown=NO;
yourImageView.image = [UIImage imageNamed:#"yourSecondImage.png"];
}
else
{
isFirstImageShown=YES;
yourImageView.image = [UIImage imageNamed:#"yourFirstImage.png"];
}
}
You want that on button click you need another image you have to first set the image when you load the view and then on button click.

objective-c disable drag in UIButton

I want to disable UIButton dragging in Xcode, is there anyway to do that?
any solution would help
Thanks
You cannot disable touch drag events, but can use alternative of handling them.
You need to handle Touch event handlers. When we swipe left or right TouchCancel event is fired and when you swipe up or down TouchDragExit is fired. Make sure to implement both.
#property (nonatomic) BOOL buttonFullyTouched;
.
.
.
//Touch Down Event
- (IBAction)filterTouchedDown:(id)sender
{
_nameButton.selected = NO;
_codeButton.selected = NO;
_dateButton.selected = NO;
_filterFullyTouched = NO;
}
//Touch Drag Exit Event
- (IBAction)buttonDragExit:(id)sender
{
if (!_buttonFullyTouched)
{
UIButton *randomButton = (UIButton *)[_groupView viewWithTag:_previousButtonSelectedTag + 2000];
randomButton.selected = YES;
}
}
// Touch Cancel Event
- (IBAction)buttonTouchCancel:(id)sender
{
if (!_buttonFullyTouched)
{
UIButton *randomButton = (UIButton *)[_groupView viewWithTag:_previousButtonSelectedTag + 2000];
randomButton.selected = YES;
}
}
// TouchUpInside event
- (IBAction)groupButtonTapped:(id)sender
{
_nameButton.selected = NO;
_codeButton.selected = NO;
_dateButton.selected = NO;
_buttonFullyTouched = YES;
// logic for further code
}
If you're looking to disallow the user to drag-out from a touch, look at the UIControl class. Specifically take note of:
- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents
If you're using InterfaceBuilder, you should look at the options available for Events (in the Inspector window, second tab).

UIButton and UIControlEventState issue

I'm having a very specific "bug" in my iPhone application. I'm setting two images for the highlighted and normal states of a button. It works as expected when you "press" and then "touch up" at a slow pace, but if you click/tap it quickly, there's a noticeable flicker between states. Is this a known bug or am I setting the states incorrectly?
Here's the code that creates the buttons:
UIImage *normalImage = [[UIImage imageNamed:#"btn-small.png"] stretchableImageWithLeftCapWidth:10.0f topCapHeight:0.0f];
UIImage *highlightedImage = [[UIImage imageNamed:#"btn-small-down.png"] stretchableImageWithLeftCapWidth:10.0f topCapHeight:0.0f];
[self setBackgroundColor:[UIColor clearColor]];
[self setBackgroundImage:normalImage forState:UIControlStateNormal];
[self setBackgroundImage:highlightedImage forState:UIControlStateDisabled];
[self setBackgroundImage:highlightedImage forState:UIControlStateHighlighted];
[self setAdjustsImageWhenDisabled:FALSE];
[self setAdjustsImageWhenHighlighted:FALSE];
When a button is tapped it simply disables itself and enables the other button:
- (IBAction)aboutButtonTouched:(id)sender
{
aboutButton.enabled = FALSE;
rulesButton.enabled = TRUE;
}
- (IBAction)rulesButtonTouched:(id)sender
{
rulesButton.enabled = FALSE;
aboutButton.enabled = TRUE;
}
Any thoughts on this quick-click flicker?
Ok, I resolved this. Took a bit of reverse engineering what I was trying to do, but I thought I'd post what I did in case it helps someone else.
The first thing I did was modify the aboutButtonTouched method to log the button's state property which is a bit-mask NSUInteger:
- (IBAction)aboutButtonTouched:(id)sender
{
rulesButton.enabled = TRUE;
[sender setEnabled:FALSE];
NSLog(#"%d", [sender state]);
}
At this point, the button is disabled through setEnabled, and the log reported that the state was "3". Looking at the bit-mask type for UIControlState:
enum {
UIControlStateNormal = 0, // 0
UIControlStateHighlighted = 1 << 0, // 1
UIControlStateDisabled = 1 << 1, // 2
UIControlStateSelected = 1 << 2, // 4
UIControlStateApplication = 0x00FF0000,
UIControlStateReserved = 0xFF000000
};
(Notes added since I can never remember bitwise). We can see that to get "3" (0011) we should use UIControlStateHighlighted | UIControlStateDisabled (0001|0010 or 1|2), something which I did not have as a state in my original button definition. The key here that there's a brief time when the state is both before just being disabled ("A control enters this state when a touch enters and exits during tracking and and when there is a touch up" -- from the docs). So the final state settings for the button where it does not flicker are:
[self setBackgroundImage:normalImage forState:UIControlStateNormal];
[self setBackgroundImage:highlightedImage forState:UIControlStateDisabled];
[self setBackgroundImage:highlightedImage forState:UIControlStateHighlighted];
[self setBackgroundImage:highlightedImage forState:UIControlStateHighlighted|UIControlStateDisabled];
To be noted that, although not documented, all state combinations that contain UIControlStateHighlighted|UIControlStateDisabled aren't valid: these are equivalent to same without UIControlStateDisabled.
In short:
(UIControlStateHighlighted | UIControlStateDisabled) == UIControlStateHighlighted
and
(UIControlStateSelected | UIControlStateHighlighted | UIControlStateDisabled) == (UIControlStateSelected | UIControlStateHighlighted)
I found that the hard way: was setting some attributes for the Highlighted+Disabled state which was overwriting my settings for the Highlighted state. Spent half a day to track down the issue why button wasn't properly highlighting...
Maybe you should reverse the sequence of changing the buttons
- (IBAction)aboutButtonTouched:(id)sender
{
rulesButton.enabled = TRUE;
aboutButton.enabled = FALSE;
}
When you hide the one button first and then show the other, there's maybe a little gap, which creates the flicker. I think it's better to show the other button first.