Google login iOS - "My GIDSignInButton only works in long press" - ios

The google login button provided by google (GIDSignInButton), is not working in normal press but in long press. Otherwise evrything is normal.
Any idea guys?

That was due to a tap recognizer I had in the same viewcontroller. Issue got solved.

Google sign in default button not works in single tap, it works after 1
long press because of the Tap Gesture included in same
viewcontroller...
So the Solution is Handle touch event in sameViewcontroller:
override func viewDidLoad() {
super.viewDidLoad()
let touchRecognizer = UITapGestureRecognizer(target: self, action:
#selector(onBaseTapOnly))
touchRecognizer.numberOfTouchesRequired = 1
touchRecognizer.delegate = self
self.view.addGestureRecognizer(touchRecognizer)
}
func onBaseTapOnly(sender: UITapGestureRecognizer) {
if sender.state == .ended {
//react to tap
self.view.endEditing(true)
}
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
shouldReceive touch: UITouch) -> Bool {
return touch.view == gestureRecognizer.view
}

Related

Pinch gesture does not work if view registers pan gesture

I have an app that manipulates view with gestures. View is connected to pan, pinch and rotate gestures. If I start interacting with the view with two fingers all gestures are working simultaneously (expected behavior). But if you start with one finger pan, pinch and rotate gestures do not work. None of the methods in the delegate are called when I am trying to start pinch or rotate while panning.
shouldRecognizeSimultaneouslyWith
is always true.
Expected behavior,
one finger pan on the view
add second finger and start pinch/rotate interaction
(similar to instagram stories editor)
From a clean project I added the following:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.addGestureRecognizer({
let gesture = UIPanGestureRecognizer(target: self, action: #selector(onPan))
gesture.delegate = self
return gesture
}())
view.addGestureRecognizer({
let gesture = UIPinchGestureRecognizer(target: self, action: #selector(onPinch))
gesture.delegate = self
return gesture
}())
view.addGestureRecognizer({
let gesture = UIRotationGestureRecognizer(target: self, action: #selector(onRotate))
gesture.delegate = self
return gesture
}())
}
#objc private func onPan(_ sender: UIPanGestureRecognizer) {
print("Did pan to \(sender.translation(in: sender.view))")
}
#objc private func onPinch(_ sender: UIPinchGestureRecognizer) {
print("Did pinch to \(sender.scale)")
}
#objc private func onRotate(_ sender: UIRotationGestureRecognizer) {
print("Did rotate to: \(sender.rotation)")
}
}
extension ViewController: UIGestureRecognizerDelegate {
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { true }
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { true }
}
All 3 methods report changes after the scenario you described:
I started with single touch drag gesture
I pressed another finger and started rotating gesture and pinching gesture
Does already this example not work for you? What is the behavior you are experiencing and what is expected behavior?

Resolve UITapGestureRecognizer and UILongPressGestureRecognizer simultaneously and fire UIGestureRecognizer.State.began on finger touch down

First of all, none of the already answered questions didn't help me
Swift: Long Press Gesture Recognizer - Detect taps and Long Press
Using tap gesture and long press at the same time in Table View
Long Press Gesture Recognizer Only Fired When Finger is Lifted
And so on
The code working almost fine except one thing: the long press gesture only called when I lift my finger up from the screen. But I need to get behaviour like in Instagram Stories (when you can switch between stories and hold your finger to pause pause some story).
My question is more about how to force UILongPressGesture to fire when user touch finger down, but not up.
Here's my code:
private func setupTapGestures() {
tapRecognizer = UITapGestureRecognizer()
tapRecognizer?.addTarget(self, action: #selector(handleTapGesture(_:)))
tapRecognizer?.delegate = self
view.addGestureRecognizer(tapRecognizer!)
longPressRecognizer = UILongPressGestureRecognizer()
longPressRecognizer?.addTarget(self, action: #selector(handleLongPressGesture(_:)))
longPressRecognizer?.minimumPressDuration = 0.1
longPressRecognizer?.delegate = self
view.addGestureRecognizer(longPressRecognizer!)
}
#objc func handleTapGesture(_ gestureRecognizer: UIGestureRecognizer) {
let width = view.frame.width
let point = gestureRecognizer.location(in: view)
viewModel?.tapAction(viewWidth: width, tapPoint: point)
Swift.print("Tap gesture")
}
#objc func handleLongPressGesture(_ gestureRecognizer: UILongPressGestureRecognizer) {
if gestureRecognizer.state == .began {
Swift.print("Began")
} else if gestureRecognizer.state == .ended {
Swift.print("Ended")
}
}
UIGestureRecognizerDelegate:
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
// Don't recognize a single tap until a long-press fails
if gestureRecognizer == tapRecognizer && otherGestureRecognizer == longPressRecognizer {
return true
}
return false
}
shouldRequireFailureOf docs
Any suggestions or ideas?
I wonder if your implementation of shouldRequireFailureOf is causing an issue?
This works just fine for me (note: I used .minimumPressDuration = 0.25 because it's a little difficult to tap in under 0.1 seconds):
class GestureTestViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setupTapGestures()
}
private func setupTapGestures() -> Void {
let singleTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(_:)))
view.addGestureRecognizer(singleTapGesture)
let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPressGesture(_:)))
longPressGesture.minimumPressDuration = 0.25
view.addGestureRecognizer(longPressGesture)
}
#objc func handleLongPressGesture(_ gesture: UILongPressGestureRecognizer) -> Void {
if gesture.state == .began {
print("Did Long Press (began)")
}
if gesture.state == .ended {
print("Did Long Press (ended)")
}
}
#objc func handleTapGesture(_ gesture: UITapGestureRecognizer) -> Void {
print("Did Single Tap")
}
}
When I tap, I get "Did Single Tap" in the debug console.
When I tap and hold, I quickly get "Did Long Press (began)", and on finger-lift I get "Did Long Press (ended)"

How to dismiss modal form sheet when clicking outside of view?

I don't know how exactly to achieve the following in Swift:
I am displaying a modal form sheet popup in my iPad app. In order to dismiss this view I have added a button that dismisses it. But what I really want is for it to dismiss when you click outside of the view. Almost the same behaviour as the popover. I have tried achieving this by adding tap gestures, making it a popover, any of the presentation styles, nothing works.
Has someone maybe done this so that you can point me in the right direction?
I had to display some screens like a popup in my app, so I've made a
base class that looks like this:
class MyBasePopUp: UIViewController, UIGestureRecognizerDelegate {
var tap: UITapGestureRecognizer!
override func viewDidAppear(_ animated: Bool) {
tap = UITapGestureRecognizer(target: self, action: #selector(onTap(sender:)))
tap.numberOfTapsRequired = 1
tap.numberOfTouchesRequired = 1
tap.cancelsTouchesInView = false
tap.delegate = self
self.view.window?.addGestureRecognizer(tap)
}
internal func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
internal func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
let location = touch.location(in: self.view)
if self.view.point(inside: location, with: nil) {
return false
}
else {
return true
}
}
#objc private func onTap(sender: UITapGestureRecognizer) {
self.view.window?.removeGestureRecognizer(sender)
self.dismiss(animated: true, completion: nil)
}
This is just to dismiss the popup, be careful if you have multiple gestures.

UITapGestureRecognizer not working when clicking on a DatePicker

I am using this code to dismiss keyboard when user click's outside the TextField
override func viewDidLoad() {
...
let tapGesture = UITapGestureRecognizer(target: self, action: "tap:")
view.addGestureRecognizer(tapGesture)
...
}
func tap(gesture: UITapGestureRecognizer) {
txtName.resignFirstResponder()
}
It is working when the user click's anywhere outside the textfield but the datepicker. When he put's a name and then click on the DatePicker (just click, not roll) the tap is not recognized.
What should I do to make it work?
It's possible the gesture recogniser on the DatePicker is interfering with yours. See if modifying this function helps your case.
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true //Obviously think about the logic of what to return in various cases
}

UITextView focused, but user touches UICollectionViewCell. Hide keyboard and run didSelectItemAtIndexPath

I have a "search" UITextField at the top of my view.
Below this, I have a UICollectionView which is populated with the search results as the user types.
When a user is typing into the UITextView, the keyboard is displayed. At first, I wanted to hide the keyboard if the user touched anywhere outside the UITextField. I accomplished this with the following:
func textFieldDidBeginEditing(textField: UITextField) {
if (textField == self.textFieldSearch) {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "textFieldSearchDidChange:", name: UITextFieldTextDidChangeNotification, object: textField)
}
var tapGesture = UITapGestureRecognizer(target: self, action: "dismissKeyboard:")
self.view.addGestureRecognizer(tapGesture)
}
func dismissKeyboard(gesture: UIGestureRecognizer) {
self.textFieldSearch.resignFirstResponder()
self.view.removeGestureRecognizer(gesture)
}
However, if the user taps on a UICollectionViewCell, the dismissKeyboard func runs, and hides the keyboard, but the user has to tap on the cell again to run the func:
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
How do I do this all in one step? So if the user touches anywhere outside the UITextField, hide the keyboard...but if the user happens to touch a UICollectionViewCell, run the didSelectItemAtIndexPath function on the first touch as well as hide the keyboard and end editing on the UITextField?
Any help is appreciated!
Thanks
Please try this one
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
if touch.view == self.textFieldSearch{
return false;
}
else{
return true;
}
}
and add this line in your code
var tapGesture = UITapGestureRecognizer(target: self, action: "dismissKeyboard:")
tapGesture.delegate = self // add gesture delegate here
self.view.addGestureRecognizer(tapGesture)
You can implement the delegate method of UIGestureRecognizerDelegate
optional func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
shouldReceiveTouch touch: UITouch) -> Bool
Above method returns NO for the views on which gesture recognizer should not be called and in your case it should be collection view else for other things return YES.
example implementation-
/**
Disallow recognition of tap gestures on the collection view.
*/
func gestureRecognizer(recognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool
{
if touch.view == collectionView && recognizer == tapRecognizer {
return false
}
return true
}
Here's a solution. A little janky but it should do the trick. You might have to tinker with it a little. Also my Swift isn't top notch so excuse any syntax errors.
func dismissKeyboard(gesture: UIGestureRecognizer) {
let point : CGPoint = gesture.locationInView(self.collectionView)
let indexPath : NSIndexPath = self.collectionView.indexPathForItemAtPoint(point)
self.textFieldSearch.resignFirstResponder()
self.view.removeGestureRecognizer(gesture)
self.collectionView.selectItemAtIndexPath(indexPath, animated:YES, scrollPosition:UICollectionViewScrollPosition.Top)
}
I am providing here a Objective-C code to dismiss keyBoard on any touch performed outside. Kindly write it in Swift for yourself. The problem is you are adding A tap Gesture which is hiding the touch events of your collection cell.
So instead of tap gesture use the Swift-translated code of the following code.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.view endEditing:YES];
}
Dont use your tap gesture. And I think things should get going for you...
EDIT
Some efforts to write the above code in swift for you...
override func touchesBegan(touches: NSSet, withEvent event: UIEvent){
self.view.endEditing(true)
}
This is the code that ended up finally working, with the help of #Sanjay above.
I still wanted to hide the keyboard if the user touched on the part of the collectionView that wasn't occupied by cells. I will still have to implement code for hiding the keyboard if a user 'swipes/scrolls/drags' on the UICollectionView instead of taps.
For now:
func gestureRecognizer(recognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
for cell:AnyObject in self.collectionView.visibleCells() {
if (touch.view.isDescendantOfView(cell as UIView)) {
self.resignAllResponders()
return false
}
}
return true
}

Resources