How to trigger UIButton target event before parent TapGestureRecognizer - ios

It's a simple question,
I have a UIButton with a target action
addTarget(self, action: "buttonPressed", forControlEvents: UIControlEvents.TouchUpInside)
func buttonPressed()
{
self.selected = !self.selected
}
This button is the child of a parent UIView
containerView.addSubview(button)
I add a UITapGestureRecognizer to the container
let tapG = UITapGestureRecognizer(target: self, action: "toggleView:")
containerView.addGestureRecognizer(tapG)
in func toggleView(gest:UIGestureRecognizer) I check the status of my button.
The problem is that in toggleView(), the status of the button has not been set... YET!
EDIT
if I do
print(button.selected)
I only get the button value BEFORE the touch event, not the new one.
any idea?

Try to change
func toggleView(gest:UIGestureRecognizer)
to
func toggleView(gest:UITapGestureRecognizer)
Hope it helps!

I don't exactly get what you are trying to accomplish, If you want to perform certain action on button click and another action when tapped outside in containerView then you can do
-(void)toggleView:(UITapGestureRecognizer *) gest{
CGPoint tapLocation = [gest loactionInView:containerView];
if(CGRectContainsPoint(button.frame, tapLocation)){
// Tapped on Button
}
else{
// tapped outside in containerView
}
}
Note: As am not learning swift, i gave snippet in Objective-C. you should be able to translate it into swift easily :)

Related

iOS - Replace a label by a button

I've added a label in a view controller via the interface builder, and I've added a lot of constraints to it, but I want to replace it by a button. Can I accomplish this without losing all the constraints ? Thanks a lot in advance
I'm not sure if you can save your constraints inside interface builder. However, you can add a tap gesture recognizer to make the label perform an action when it is tapped (act like a button).
This code can help you get started:
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap(_ :)))
myLabel.isUserInteractionEnabled = true
myLabel.addGestureRecognizer(tapGestureRecognizer)
func handleTap(_ sender: UITapGestureRecognizer) {
// perform some action when the label is tapped
}
You can look at this question for more information.
Don’t replace by button
Add tap gesture for click action
you don't need to remove that label. Just addGestureRecognizer a tap gesture on label.
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap(_ :)))
myLabel.isUserInteractionEnabled = true
myLabel.addGestureRecognizer(tapGestureRecognizer)
func handleTap(_ sender: UITapGestureRecognizer) {
// perform some action when the label is tapped
}

Add single, double and triple tap gestures to all "buttons" in custom keyboard in swift

I'm trying to create a keyboard the allows single tap, double tap, and triple tap. So I want to add a UITapGestureRecognizer() to each button in my keyboard. I know how to do this manually from the xib file (add each letter it's own gesture, which would take ages) but not quite sure how to do it in the Controller.
I wrote this for double tap in the viewDidLoad() method:
let doubleTap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "doubleTapCharacter:")
doubleTap.numberOfTapsRequired = 2
for button in self.view.subviews{
button.addGestureRecognizer(doubleTap)
}
and created a doubleTapCharacter() method but it's still not working. I also want to be able to send information to the doubleTapCharacter method.
Any help would be much appreciated. Also, I'm very new to swift so if the instructions are complicated, I'd highly appreciate it if you can break it down a little.
create and add the gesture recognizers:
for button in view.subviews {
// create the gesture recognizer
let doubleTapRecognizer = UITapGestureRecognizer(target: self, action: "doubleTapCharacter:")
doubleTapRecognizer.numberOfTapsRequired = 2
// add gesture recognizer to button
button.addGestureRecognizer(doubleTapRecognizer)
}
then implement the target method:
func doubleTapCharacter(doubleTapRecognizer: UITapGestureRecognizer) {
let tappedButton = doubleTapRecognizer.view as! UIButton
print(tappedButton.titleForState(UIControlState.Normal))
}

Swift: Change colour of button when tapped

I'm new to Swift and I'm trying to change the button colour on tap. When the button is tapped, it should change colour and when released it should go back to the original button colour.
An example of this is the calculator. When you tap a button, it changes from light grey to dark grey and when the user removes their finger off the button, it goes back to the original light grey colour. How do I go about doing that?
So far, I've only got this..
#IBAction func changeButtonColourOnTouch(sender: UIButton) {
zeroButton.backgroundColor = UIColor.blueColor()
}
The above code changes the button colour to blue but stays blue.
The problem is, after releasing the button, you should return the color to the original state.
You can link direct from storyboard, in the action TouchUpInside (release) and TouchDown (press) , to change the button color to the correct state in each event.
Or you can add a Target in the button by code, linking to the functions, as the code bellow shows it.
zeroButton.addTarget(self, action: Selector("holdRelease:"), forControlEvents: UIControlEvents.TouchUpInside);
zeroButton.addTarget(self, action: Selector("HoldDown:"), forControlEvents: UIControlEvents.TouchDown)
//target functions
func HoldDown(sender:UIButton)
{
zeroButton.backgroundColor = UIColor.blueColor()
}
func holdRelease(sender:UIButton)
{
zeroButton.backgroundColor = UIColor.whiteColor()
}
Code adapted by the present in the link UIButton with hold down action and release action
The checked answer above works, but if the user holds down on the button, then drags out, the background color won't return to normal. It's a tiny UI bug, but a simple fix. This includes the code of the checked answer.
zeroButton.addTarget(self, action: #selector(holdRelease), for: .touchUpInside);
zeroButton.addTarget(self, action: #selector(heldDown), for: .touchDown)
zeroButton.addTarget(self, action: #selector(buttonHeldAndReleased), for: .touchDragExit)
//target functions
#objc func heldDown()
{
zeroButton.backgroundColor = .blue
}
#objc func holdRelease()
{
zeroButton.backgroundColor = .white
}
#objc func buttonHeldAndReleased(){
zeroButton.backgroundColor = .blue
}
you could also use a tap gesture and change the color of the button as the user is tapping on the button
you could see apple documentation regarding UIGestureRecognizer in here
it is a little bit advanced, but you will learn a lot from it.
You can also use setbackgroundImageForState to define color image as button background for all UIControlState you are interested in e.g. Normal, Highlighted, Disabled, Selected.
let cx = UIGraphicsGetCurrentContext()
let color = UIColor.redColor()
let state = UIControlState.Selected
UIGraphicsBeginImageContext(CGSize(width:1, height:1))
CGContextSetFillColorWithColor(cx, color.CGColor)
CGContextFillRect(cx, CGRect(x:0, y:0, width:1, height:1))
let colorImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.zeroButton.setBackgroundImage(colorImage, forState: state)
Now color changes automatically and you don't have to handle it manually.
If you want that for a programmatically defined button, just declare the button of type system during its initialisation:
let button = UIButton(type: .system)

iOS UITableView : clear section button

I need to add clear button in table view section header. It is exactly same like the one in notification center. So when user clicks it, 'x' will change to 'Clear'. If s/he clicks it again, app will perform action. But any click outside this button, 'Clear' will be back to 'x'
How can I make this? Thanks in advance
Unfortunately this does not come out of the box. You have to create your own custom section header view. That custom header view contains a UILabel on the left side. On the right side you put a UIButton that has the title "X". When the user taps on the button, change its title to "Clear" and its state to .Selected. Only clear your table view section when the button is tapped and its state is .Selected:
func setupButton() {
let button = UIButton()
button.setTitle("X", forState: .Normal)
button.addTarget(self, action: Selector("didPressButton:"), forControlEvents: .TouchUpInside)
addSubview(button)
}
func didPressButton(button: UIButton) {
if button.selected {
// clear your table view section
}
button.setTitle("Clear", forState: .Normal)
button.selected = true
}
To put the button back in its unselected state add a background UIView to your section header view and add a UITapGestureRecognizer to it:
func setupBackground() {
let background = UIView()
let recognizer = UITapGestureRecognizer(target: self, action: Selector("didTapOutside:"))
background.addGestureRecognizer(recognizer)
insertSubview(background, belowSubview: button)
}
func didTapOutside(recognizer: UITapGestureRecognizer) {
button.selected = false
button.setTitle("X", forState: .Normal)
}
To use your custom section header in your table view you implement the following UITableViewDelegate method:
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
// create your custom section header and return it
}

Having trouble targeting a DesignableView in a UITableViewCell upon tapping it in order to change

and thanks in advance for taking the time to help.
Inside my CellForRowAtIndexPath, I have the following line:
cell.timeView.addTarget(self, action: "ButtonDidPress:", forControlEvents: UIControlEvents.TouchUpInside)
and my selector function is:
func ButtonDidPress (sender: DesignableView!){
let view:DesignableView = sender
cell.timeView.shadowColor = UIColor.yellowColor()
table.reloadData()
}
and the error i get is:
unrecognized selector sent to instance
I'm thinking that perhaps one can't send a View as a selector (am I using the correct terminology?), but how else can I target that particular view in that cell?
UPDATE:
I also tried using gestureRecognizer instead:
var tap = UIGestureRecognizer(target: self, action: Selector( "viewDidTap:"))
cell.timeView.addGestureRecognizer(tap)
and
func viewDidTap (sender: DesignableView!){
but I got the same error here.
Thanks!
There's a couple of strange things happening in your code. It seems you want to change the shadowColor property of timeView when a user touch it, right?
Two possible solutions are:
(This one is IMO the better one) Change DesignableView to inherit from UIButton. Then you can set:
timeView.addTarget(self, action: "ButtonDidPress:", forControlEvents: .TouchUpInside). Make sure you set it just once for each cell. Otherwise you will get multiple calls on one tap.
Use UITapGestureRecognizer, but you should put it in your UITableViewCell subclass, not to the view controller. Also, the sender in viewDidTap is not the view itself, but the recognizer. So the method will go like this:
func viewDidTap(sender: UITapGestureRecognizer) {
let location = sender.locationInView(sender.view)
if timeView.hitTest(location, withEvent: nil) == timeView {
timeView.shadowColor = UIColor.yellowColor()
// table.reloadData() - you don't need to reload the table
}
}

Resources