I have a custom UIButton. To create a custom background color when highlighted I the button (self) as an observer to three events:
[self addTarget:self action:#selector(didTapButtonForHighlight) forControlEvents:UIControlEventTouchDown];
[self addTarget:self action:#selector(didUnTapButtonForHighlight) forControlEvents:UIControlEventTouchUpInside];
[self addTarget:self action:#selector(didUnTapButtonForHighlight) forControlEvents:UIControlEventTouchUpOutside];
The first two work beautifully, and as long as I touch up inside the button the background gets set back to normal. However if I touch up outside the button the method didUnTapButtonForHighlight never gets called and the background remains the highlighted color. My code is a modified version of the code in Ondrej's answer to this question. Why is it not working? Thanks in advance.
You should also test for UIControlEventTouchCancel in case you touch up way outside.
Related
I have a simple UITableView that I've added a UIButton to the Footer.
Similar to this:
self.btn =[UIButton buttonWithType:UIButtonTypeCustom];
self.btn.backgroundColor = darkPurple;
[self.btn setTitle:#"Submit" forState:UIControlStateNormal];
[self.btn addTarget:self action:#selector(btnTapped:) forControlEvents:UIControlEventTouchUpInside];
[self.btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
self.btn.frame=CGRectMake(0, 0, self.tableView.frame.size.width, 100);
self.btn.showsTouchWhenHighlighted = true;
self.tableView.tableFooterView = self.btn;
Sometimes when I get scrolled to the bottom of the TableView if it isn't completely settled the Button won't perform the action. Sometimes it will flash (showsTouchWhenHighlighted) but I'll need to tap it again.
What am I missing here? I've tried solutions like this but it doesn't appear to work.
UIButton touch is delayed when in UIScrollView
I want to it process always, even if the scroll isn't settled and not delay.
What am I missing here?
Nothing. That's just how touches work on iOS. You can see the same thing in Mobile Safari: if the page is still scrolling, tapping a link doesn't work. You have to wait until the page is completely stopped ("settled", as you rightly say).
I have an app with this code
_pushButton = [UIButton buttonWithType:UIButtonTypeCustom];
_pushButton.frame = CGRectMake(15, 2, 74, 74);
[_pushButton addTarget:self
action:#selector(buttonPushed:)
forControlEvents:UIControlEventTouchDown];
[_pushButton addTarget:self
action:#selector(buttonReleased:)
forControlEvents:UIControlEventTouchUpInside];
[_pushButton setBackgroundImage:[UIImage imageNamed:#"1.png"] forState:UIControlStateNormal];
[_pushButton setBackgroundImage:[UIImage imageNamed:#"2.png"] forState:UIControlStateSelected];
The behavior is that when the button is pressed the image gets darker and the button stays in that state until the button is released. The buttonPushed is called when the button is pressed and the buttonReleased is called when it is released.
That is what I expected.
I have another application with exactly the same code, that I have copied from the first.
The behavior is different: when the button is pushed, the image gets darker but about a second later the button gets to its original state even if it is still pressed. Only the buttonPushed is called.
This is not what I need.
1) Why the two apps has a different behavior?
2) How can configure the button in the second application to have the same behavior of the first?
UPDATE
In the first app the button is created in a class which subclass
UIView
In the second app the button is created in a class which
subclass UIViewController
UPDATE 2
The button which doesn't stay pressed is in a subview of a UICollectionViewCell. Apparently, buttons have a different behaviour when in a cell of a collection view.
I have one button and one search field in navigation bar and i added a new button by code from one class for all view.
The problem is: with the button view the other button and the search field added with storyboard are not more touchable and not working.
UIImage * buttonImage = [UIImage imageNamed:#"chat-notify.png"];
button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self
action:#selector(goChat)
forControlEvents:UIControlEventTouchDown];
//[button setTitle:#"1" forState:UIControlStateNormal];
button.frame = CGRectMake(280.0, 25.0, 30.0, 30.0);
[button setBackgroundImage:buttonImage forState:UIControlStateNormal];
[self.view addSubview:button];
and then in the controller:
notificationViewController* notification = [[notificationViewController alloc]init];
//[notification methodA];
[notification makeButtonNotification];
[self.view addSubview:notification.view];
Does anyone know where is my mistake?
Thanks
Why are you adding the button surely having it there and changing it's hidden state would be easier then you can keep it all in the storyboard
UIControlEventTouchUpInside
is what you should use not "UIControlEventTouchDown"
TouchUpInside is usually the event where you trigger the action from a button. It's when the user is lifting up from the button after pressing it. You don't want to trigger the action on Touch Down as the use may move his finger off the button to cancel the press, which is standard and expected behaviour on iOS
UPDATE: Base on your comment to this answer perhaps you need to add the button to a specific point in your view heir achy. As in your storyboard views will be added as they are listed in that stroyboard starting from the top down, with the one on the bottom being the top view.
Try obviously making sure that views that you want to receive touches are not directly on top of each and that they do not overlap. Also try adding the programatically generated button above or below a specific view, rather than just making it the top subview in your main view which by the sounds of it isn't what you want.
As you're adding a button like this
[self.view addSubview:button];
it may be better to do it more like this
[self.view insertSubview:button aboveSubview:someOtherView]
To do this you'll probably need to hook up your "someOtherView" to an IBOutlet so you can reference it in your code. As it looks like you're most likely sticking your button over everything else, when you need to be more precise.
The UIButton has a normal/default, highlighted, and selected image. I then have a IBAction method that is called on Touch Down. The method changes the highlighted image depending if it's selected. But when the button is selected, the method is called and so the highlight image is changed, however what is displayed is the normal/default image with a tint. I have tested that image used is in not nil. What happens is when the UIButton in a selected state is pressed displays the normal state with a tint. Why is it not using the highlight image and is there another way of showing a selected highlight image?
Why do you set the highlighted state in the IBAction method? You only need to set the highlighted image for you button when you create it. It will switch automatically. Adding a tint when selected is the default behavior of 'selection' when no highlighted image is assigned.
if your using Interface Builder, just assign the highlighted image there.
Im assuming your looking for normal button selection behavior with your IBAction method set to the touchUpInside event.
I got around this problem by using the selected state and notifications (not via the UI). When a notification is called I change image for the default state, change the selected state and then change the image for selected state.
Update:
I came up with a much better idea from another question that was doing something similar to me. The way to do it is to things in setSelected
- (void)setSelected:(BOOL)selected
{
if ( selected )
{
[self setImage:[CFCHStyleSheet imageForTickButtonChecked] forState:UIControlStateNormal];
[self setImage:[CFCHStyleSheet imageForTickButtonChecked] forState:UIControlStateSelected];
[self setImage:[CFCHStyleSheet imageForTickButtonCheckedDisabled] forState:UIControlStateDisabled];
}
else
{
[self setImage:[CFCHStyleSheet imageForTickButtonUnchecked] forState:UIControlStateNormal];
[self setImage:[CFCHStyleSheet imageForTickButtonUnchecked] forState:UIControlStateSelected];
[self setImage:[CFCHStyleSheet imageForTickButtonUncheckedDisabled] forState:UIControlStateDisabled];
}
[super setSelected:selected];
}
board[i] is an array of UIButtons that I have created programmmatically, and I can't change their image for UIControlStateHighlighted:
[board[i] setImage:[UIImage imageNamed:#"block"] forState:UIControlStateNormal];
[board[i] setImage:[UIImage imageNamed:#"blockPressed"] forState:UIControlStateHighlighted];
When I press the button with the mouse in the simulator the image doesn't change. I think this is a very noob question, but I don't what the code doesn't work.
when adding button programatically do this:
add target of each same.
provide tag all button from 0 to count.
set UserInteraction to true
setBackgroundImage:[UIImage imageNamed:#"blockPressed.png"] forState:UIControlStateHighlighted if u want button to be highlited
Now button is pressed same method is called for all button: For example
-(void)ButtonTouched:(id)sender
{
UIButton *btntouched = sender;
NSLog(#"%#", btntouched);
[btntouched setBackgroundImage:[UIImage imageNamed:#"blockPressed.png"] forState:UIControlStateHighlighted];// it can be forState:UIControlStateNormal also
}
I don't think you are triggering the highlighted state. This could be because they are not set to have interaction enabled. Or there is something else missing from the way you set up your buttons.
The other thing you can try is to add a selector to each of the buttons for when they are touched, and then change the image by referencing sender for the selector function.
Assuming you've made sure your image doesn't return nil, this code should work:
[myUIButton setImage:[UIImage imageNamed:#"myHighlightedButtonImage.png"] forState:UIControlStateHighlighted];
It should work find if you call that line in your viewDidLoad().