I have a UITapGestureReconizer set up with my view but I only want the selector to be called when the view tapped is this picture I have. I tried adding the recognizer to the imageView both programmatically and via the storyboard but neither worked. It only works for my view. Here is the code.
var tapGestureRecognizer:UITapGestureRecognizer?
and in my viewDidLoad I have
tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "handleTap:")
self.view.addGestureRecognizer(tapGestureRecognizer!)
my image is a variable as well
#IBOutlet weak var mainImage: UIImageView!
Set the userInteractionEnabled property of the UIImageView to true and then modify your code for that
self.mainImage.addGestureRecognizer(tapGestureRecognizer!)
Related
Proof that gesture is being added but not detected
import UIKit
class PlaybackSpeedController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(tapDetected(_:)))
view.addGestureRecognizer(tap)
}
#objc func tapDetected(_ tap : UITapGestureRecognizer){
print("hello")
}
}
This hello never gets triggered. what am I missing? Funny how I used to play with gestures but don't understand why this happens
What I do is I add a transparent view that has the same frame as the superview.
let transparentView = UIView(frame: view.frame)
transparentView.backgroundColor = .clear
And just adding the gesture recognizer on that view
Please make sure view is having userInteraction enabled & is tappable directly on screen, for that make sure your new view controller frame is correct.
Setting the UIViewController's view.backgroundColor property to be some colour instead of default one solved the issue for me
Goal of code is that on each tap of a view containing 2 UIImageview, to have the bottom image go on top of the to image, and so on each time I tap.
I have a view container with 2 UIImageview on top of each other:
#IBOutlet weak var imagesContainer: UIView!
#IBOutlet weak var imageZero: UIImageView!
#IBOutlet weak var imageOne: UIImageView!
I add a tap gesture in ViewDidLoad:
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTapImagesContainer(_:)))
self.imagesContainer.addGestureRecognizer(tapGestureRecognizer
Also a top level variable, to control which image to bring on top, and which to push down:
var imageOnTopIsImageZero = true
so that when I tap on the container, the under image comes on top.
While developing I implemented a transition without animation:
#objc func didTapImagesContainer(_ sender: UITapGestureRecognizer) {
let imageToBringOnTop: UIImageView? = imageOnTopIsImageZero ? self.imageOne : self.imageZero
let ImagetoBringDown: UIImageView? = imageOnTopIsImageZero ? self.imageZero : self.imageOne
imageToBringOnTop?.layer.zPosition = 1.0
ImagetoBringDown?.layer.zPosition = 0.0
self.imageOnTopIsImageZero.toggle()
}
This works fine. Now I tried to implement the same transition with animation:
#objc func didTapImagesContainer(_ sender: UITapGestureRecognizer) {
let imageToBringOnTop: UIImageView? = imageOnTopIsImageZero ? self.imageOne : self.imageZero
let ImagetoBringDown: UIImageView? = imageOnTopIsImageZero ? self.imageZero : self.imageOne
UIView.transition(from: ImagetoBringDown!, to: imageToBringOnTop!, duration: 1.0, options: .transitionCrossDissolve, completion: nil)
self.imageOnTopIsImageZero.toggle()
}
The first time I tap on the image, the transition happens correctly, underimage is cross disolved into the on top image.
But on the second tap, imageToBringOnTop is nil!
I really don't understand why the animation has an effect on the view content. What is the cause, and how to resolve this issue?
The docs say:
fromView
The starting view for the transition. By default, this view is removed from its superview as part of the transition.
Detail:
The idea of a transition animation is that you're changing the view hierarchy by replacing one view with another in an animated way. If you are not doing such a 'transition', you can use other (non-transition) animation API like animateWithDuration:delay:options:animations:completion:
Or there is support for keeping two views in the hierarchy, one shown, one hidden, using the transition animation API, if you include UIViewAnimationOptionShowHideTransitionViews in the option set:
UIView.transition(from: ImagetoBringDown!, to: imageToBringOnTop!,
duration: 1.0,
options: [.transitionCrossDissolve, .showHideTransitionViews],
completion: nil)
So "showHideTransitionViews" means 'show/hide the from/to instead of add/remove'
Rather than setting the z positions, transition actually removes the from view from the view hierarchy, and adds the to view to the view hierarchy (documentation):
Parameters
fromView
The starting view for the transition. By default, this view is
removed from its superview as part of the transition.
toView The ending view for the transition. By default, this view is
added to the superview of fromView as part of the transition.
Also note that since your VC is holding a weak reference to the images, their superviews are the only objects holding a strong reference to them. Once one of them is removed from its superview, your VC's weak reference becomes nil.
To fix this, simply use strong references, remove the word weak:
#IBOutlet var imageZero: UIImageView!
#IBOutlet var imageOne: UIImageView!
I want to add animation to these two views.
Red UIView
Green UIView
My storyboard look like this
From the picture I want to add an animation when click on these two views.
First start with hide red UIView.
Action : 1
when i click on green view i want green uiview silde to the right side until it disappear
and the red UIView will slide out from the right side immediately.
red uiview slide from right side
and stopp when it is at that point in the storyboard and hide green UIView.
Action : 2
and when i click on red view i want it to slide right until it disappears. Show green UIView and comes out from the right corner as well and hide red UIView.
red UIView slide out
My Code
import UIKit
class TestViewCell: UICollectionViewCell {
#IBOutlet weak var bgView: UIView!
#IBOutlet weak var bgAlertView: UIView!
#IBOutlet weak var imgAlert: UIImageView!
#IBOutlet weak var bgAlreadyAlertView: UIView!
#IBOutlet weak var imgAlreadyAlert: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
//Make an action when tap on bgAlertView
let actionBgAlert : Selector = #selector(self.actionBgAlert)
let viewPostsViewGesture = UITapGestureRecognizer(target: self, action: actionBgAlert)
bgAlertView.isUserInteractionEnabled = true
bgAlertView.addGestureRecognizer(viewPostsViewGesture)
//Make an action when tap on bgAlreadyAlertView
let actionBgAlreadyAlert : Selector = #selector(self.actionBgAlreadyAlert)
let viewAlreadyViewGesture = UITapGestureRecognizer(target: self, action: actionBgAlreadyAlert)
bgAlreadyAlertView.isUserInteractionEnabled = true
bgAlreadyAlertView.addGestureRecognizer(viewAlreadyViewGesture)
}
//action1
#objc func actionBgAlert(sender: UITapGestureRecognizer){
if imgAlert.image == #imageLiteral(resourceName: "alarm") {
self.bgAlertView.isHidden = true
self.bgAlreadyAlertView.isHidden = false
}
//action2
#objc func actionBgAlreadyAlert(sender: UITapGestureRecognizer){
if imgAlreadyAlert.image == #imageLiteral(resourceName: "alarmedMain") {
self.bgAlertView.isHidden = false
self.bgAlreadyAlertView.isHidden = true
}
}
In the storyboard set constraints on the size of the views. Set constraints from the right side of the red view and green view from the right side of the superview they share. Define some constants for the values needed for both positions for both views.
Then something like this:
#IBOutlet weak var greenConstraint : NSLayoutConstraint
#IBOutlet weak var redConstraint : NSLayoutConstraint
let greenSlideOutValue = -2000.0 // big enough to get green view offscreen
let redSlideInValue = 0.0 // aligns red view right edge to superview
let greenSlideInValue = 100.0 // puts green view onscreen offset from right edge
let redSlideOutValue = -2500.0 // big enough to get red view offscreen.
UIView.animate(withDuration: 0.75, delay: 1.0, options: .curveEaseOut, animations: {
greenConstraint.constant = greenSlideOutValue
redConstraint.constant = redSlideInValue
self.view.layoutIfNeeded()
}, completion: { finished in
print(“slide green out, red in”)
})
Do this in the event handler for say a tap or gesture recognizer associated with the views. Do similar for the red view event(s)
Code isn’t compiled and is just typed in but should get you started.
I want to create a login page in which the image I have fills up the entire page. I was able to accomplish this by doing
let imageView = UIImageView(frame: self.view.bounds)
imageView.image = UIImage(named: "background")
self.view.addSubview(imageView)
However, I also have textfields and buttons on my storyboard which I created outlets for on my swift file. When I insert that code into the viewDidLoad() function, the textfields and login button go underneath the image rather than appear over the image. I'm not exactly sure how to get the login page text fields/buttons to appear over the UIImageView rather than be hidden underneath. The code I have for that is written outside the viewDidLoad
(example)
#IBOutlet var usernameTextField: UITextField!
#IBOutlet var passwordTextField: UITextField!
#IBAction func loginPressed() {
let username = usernameTextField.text
let password = passwordTextField.text
Try this:
self.view.addSubview(imageView)
self.view.sendSubviewToBack(imageView)
This method moves the specified view to the beginning of the array of views in the subviews property.
In my app I have a big UIImageView and other 5 smaller.
My intention is to copy the content of the selected small Image to the biggest one. Also to get the name of the chosen image and show with a UILabel.
Will be maybe easier to replace the small images by UIButtons and display the image as a background?
I would add a gestureRecognizer to each imageView. The function called by the gestureRecognizer would then change the image on the "big picker view". There is no built-in way to get the image name that the user chose. If you really needed this, then you could sublcass UIImageView and add a fileName property.
#IBOutlet var imageView: UIImageView!
#IBOutlet var bigPickerImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// create tap gesture recognizer
let tapGesture = UITapGestureRecognizer(target: self, action: "tapGesture:")
// add it to the image view;
imageView.addGestureRecognizer(tapGesture)
// make sure imageView can be interacted with by user
imageView.userInteractionEnabled = true
}
func tapGesture(gesture: UIGestureRecognizer) {
// if the tapped view is a UIImageView then set it to imageview
if let imageView = gesture.view as? UIImageView { // if you subclass UIImageView, then change "UIImageView" to your subclass
// change the image on the bigPickerImageView
bigPickerImageView.image = imageView.image
// if you subclass UIImageView, then you could get the filename here.
}
}