I have a simple code to add tapgestureRecognizer to dismis ViewController when tap in screen, but it not working only in iPhone X 12.1.
addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(closeSharing(_:))))
Note: magicaly, when i add tap gesturecognizer to a new view that constraint equal to view that also not working, but if i constraint the new view not equal to view, that working. Does any one know why?.
You might need to check a couple of things here:
First step make sure that your main view is not covered for example of another top view which will break your tap gesture, so add the gesture to your top view.
Second step Make sure your view that will have the gesture should have the property view.isUserInteractionEnabled = true, otherwise the gesture will not work.
Third step Make sure your view appears when your testing, you might have a problem with constraints, so the view is out of screen bounds, so try giving the view a backgroundColor = .red to see if it exists or not, or you can use View Debugger from xCode.
Example of a working gesture:
let viewToDismiss = UIView(frame:UIScreen.main.bounds)
viewToDismiss.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(closeSharing(_:)))
tap.numberOfTapsRequired = 1
viewToDismiss.addGestureRecognizer(tap)
Related
So I have a view with a carousel that has two views in it. I have two buttons that navigate from the two views inside the carousel. When the user is on the right view, the right button is disabled and left is enabled. When the user is on the left view, the left button is disabled and right is enabled.
However, I have a Pan gesture that allows the user to also swipe in between the two pages without using the buttons.
When I use the gesture to move in between the two views, I also need the buttons to reflect the change (either be enabled or disabled), however, when I put it on my pan gesture function it doesn't work 100% of the time as a half swipe or short swipe not strong enough to shift the pages but is strong enough to disable/enable my buttons as if the view has changed even though it hasn't.
I tried incorporating a Handle Swipe but I couldn't get the function to work.
Can anyone take a look at this code and let me know if anything is missing? Or better yet, if there is an easier solution to accomplish my goal
#objc func yesswiped (recognizer: UISwipeGestureRecognizer){
print("swipe pls")
}
override func viewDidLoad() {
super.viewDidLoad()
setNavigationBar()
let leftSwipe = UISwipeGestureRecognizer(target: self, action: #selector(yesswiped))
let rightSwipe = UISwipeGestureRecognizer(target: self, action: #selector(yesswiped))
leftSwipe.direction = .left
rightSwipe.direction = .right
self.view.addGestureRecognizer(leftSwipe)
self.view.addGestureRecognizer(rightSwipe)
}
To build context, my app has a stack of cards (similar to Tinder) that flip and each could contain a lot of text on one side that require a UITextView for scrolling. It's basically a flashcard app, so once the user is done looking at the card, they swipe it away to view the next one.
I'm trying to make it so the user can tap anywhere on the card to flip it, so I added a clear button that fills up the card. My problem is that when the button is at the front, it blocks the text view from being scrollable, and when the button is at the back, the text view blocks it from being pressed.
Is there a way around this somehow to allow for both functionalities?
You can create a UITapGestureRecognizer, like so:
let gesture = UITapGestureRecognizer(target: self, action: #selector(tap(gesture:)))
addGestureRecognizer(gesture)
And the function to trigger:
#objc func tap(gesture: UITapGestureRecognizer) {
print("Tap!")
}
Maybe you can add a UITapGestureRecognizer to the text view itself. Something like:
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.didTap(_:)))
textView.addGestureRecognizer(tapGesture)
#objc func didTap(_ gesture: UITapGestureRecognizer) {
// Handle the tap
}
did you try a tableView or a collectionView, you can customize your cell to look like a card then when a user clicks the cell it will flip or present a popup view, thats easier.
In one of my controllers I'm using UICollectionView with two-sided cells (there is a button on the face side of the cell, and if user is tapping it cell should show him/her the other side of the cell).
so I have this in my cell class:
firstView = UIView()
...
self.addSubview(firstView)
infoView = UIView()
...
self.insertSubview(infoView, belowSubview: firstView)
Both views have a lot of elements in them, for structuring these elements I'm using mostly Visual Format constraints and anchors.
i.e.
let topFirstViewConstraint = firstView.topAnchor.constraint(equalTo: self.topAnchor, constant: 4)
allConstraints.append(topFirstViewConstraint)
...
let goButtonCenter = goButton.centerXAnchor.constraint(equalTo: firstView.centerXAnchor, constant: 0)
allConstraints.append(goButtonCenter)
For switching between face and rear views I'm using UIView.transition:
UIView.transition(from: firstView, to: infoView, duration: 0.2, options: .transitionFlipFromLeft) { (success) in
}
It works like a charm, I don't have any autoLayout errors at all.
But if I'm trying to switch from firstView to infoView firstView constraints goes wild and vice versa (I still don't have any errors but I know how these views should look, and it's a mess). I've tried to use self.updateConstraints() in transition closure but it doesn't work.
Did anyone experience something like that?
https://developer.apple.com/documentation/uikit/uiview/1622562-transition says:
fromView: The starting view for the transition. By default, this view is removed from its superview as part of the transition.
What happens with constraints when one party of a constraint gets removed from superview? It definitely doesnât work anymore.
What you can try
Discussion:
This method provides a simple way to transition from the view in the fromView parameter to the view in the toView parameter. By default, the view in fromView is replaced in the view hierarchy by the view in toView. If both views are already part of your view hierarchy, you can include the showHideTransitionViews option in the options parameter to simply hide or show them.
I have a UILabel on both sides of a UIPageControl, as pictured below:
I found that tapping on the sides of the UIPageControl the dot would progress, ie not on my arrows and not triggering a method of mine. But nothing else would change, so I set isUserInteractionEnabled to false on the UIPageControl.
I connected (via UITapGestureRecognizer) another UILabel above and it launches a method fine.
However the UILabels, beside the UIPageControl, will not work. NOTE: I do have isUserInteractionEnabled set to true on this element. (I even temporarily changed the element to a UIButton and it wouldn't work either - so I reverted back to my UILabel.)
So, is there a way to add a UILabel to the side of a UIPageControl that gets triggered? Alternately, can the invisible objects (while tapping on the left or right of the UIPageControl - like in my second sentence) be connected to a custom method?
UPDATE:
I've added another separate modal (same title label, buttons, but no collection view and no page control). Again it won't respond when I press the label in the centre, but I temporarily am using the title label which responses and launches my method fine.
Can anyone say why?
I solved the issue!
I was declaring most variables - as well as the UILabel - in closures blocks, at the top of the class, like below:
let myLabel: UILabel = {
{
let view = UILabel()
view.translatesAutoresizingMaskIntoConstraints = false
view.isUserInteractionEnabled = true
view.textColor = UIColor.blue
return view
}
Within this closure I had view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(doMyLabelMethod(_:)))) and view.isUserInteractionEnabled = true, when I moved them out of the closure and placed them directly above addSubview(myLabel) it fired fine.
So variable-closures are good to contain many dressing, but not gesture recognizers!
I have created a double tap gesture for my Collection View. When a cell in the Collection View is double tapped i disable user interaction to the cell. This stops me being able to single tap that cell while a process runs. However i can still double tap that cell which runs the process again. I still want double tap to be available for other cells in the collection, i just want to disable it for the cell that is running process. When the process is finished user interaction is turned back on, and hopefully double tap also.
So this is how i define double tap, in viewDidLoad of the View Controller holding the Collection View:
// add gesture recogniser
let doubleTap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didDoubleTap))
doubleTap.numberOfTapsRequired = 2
doubleTap.delaysTouchesBegan = true
self.collectionView.addGestureRecognizer(doubleTap)
And I'm just switching userInteraction as usual when needed depending on state of process.
cell.isUserInteractionEnabled = false
cell.isUserInteractionEnabled = true
Im not sure how to approach this as if i disable the double tap gesture for the Collection View i cant double tap other cells. And i don't even know how to set it up so that double tap is only available in the cell and not the Collection View.
Disabling isUserInteractionEnabled on any subview of your collectionView will still pass events to the collectionView (superview). So isUserInteractionEnabled disables touch events on all subviews but not on superviews, which in this case is the collectionView.
You have a few options to proceed:
Create a custom UICollectionViewCell and add a UITapGestureRecognizer to handle the double tap internally and then delegate the double tap event.
Within the didDoubleTap method check to see if the cell that you just double tapped is enabled/disabled. You can do this by using indexPathForItemAtPoint: and then cellForItemAtIndexPath:.
You could set isEnabled to false on the gesture recognizer.
You could implement UIGestureRecognizerDelegate and return false from gestureRecognizerShouldBegin.