Wait until the user touches the screen. Swift - ios

After something happens I make a view appear with a label,
let myView = UIView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
let label = UILabel(frame: CGRect(x:0,y:0,width: 100, height: 100))
myView.addSubview(lebel)
self.view.addSubview(myView)
myView.alpha = 0
UIView.animate(withDuration: 0.5, animations: {
myView.alpha = 1
})
Now I want you to wait until a tap is made on the screen, and then
UIView.animate(withDuration: 0.5, animations: {
muView.alpha = 0
}, completion: { (bool) in
myView.removeFromSuperview()
})
How can I wait until I touch the screen?

Just add tapGesture to Your View
At viewDidload
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(_:)))
self.view.addGestureRecognizer(tapGesture)
handleTapGesture
#IBAction func handleTapGesture(_ recognizer: UITapGestureRecognizer) {
UIView.animate(withDuration: 0.5, animations: {
muView.alpha = 0
}, completion: { (bool) in
myView.removeFromSuperview()
})
}

In addtion to Abdelahad's answer, you should declare let myView as a property to use it within #IBAction func handleTapGesture(_ recognizer: UITapGestureRecognizer) {}. So, the new code is the following:
#IBAction func handleTapGesture(_ recognizer: UITapGestureRecognizer) {
UIView.animate(withDuration: 0.5, animations: {
self.myView.alpha = 0
}, completion: { (bool) in
self.myView.removeFromSuperview()
})
}
Finally adding, I found your slight mistake in your code. muView is wrong and myView is correct.

Related

Animate (Rotate) UIBarButtonItem custom buttons

All I want to do is rotating the UIBarButtonItem when it is clicked.
I followed this post Rotate UIBarButtonItem Swift, but it is not working.
The difference is:
1- I set the image on runtime when view is loaded:
showHideBtn.image = showHeaderimage
2- I have two buttons in my right Bar button items:
Here is my code:
#IBAction func rotateAction(_ sender: Any) {
if(!self.isVertical)
{
UIView.animate(withDuration: 0.2, animations: {
self.navigationItem.rightBarButtonItem?.customView?.transform = CGAffineTransform(rotationAngle: 90 * .pi / 180)
}, completion: { (finished) in
self.isVertical = true
})
}else{
UIView.animate(withDuration: 0.2, animations: {
self.navigationItem.rightBarButtonItem?.customView?.transform = CGAffineTransform.identity
}, completion: { (finished) in
self.isVertical = false
})
}
}
What am I doing wrong?
Updated code:
DispatchQueue.main.async {
if(!self.isVertical) {
UIView.animate(withDuration: 0.2, animations: {
self.navigationItem.rightBarButtonItem?.customView?.transform = CGAffineTransform(rotationAngle: 90 * .pi / 180)
}, completion: { (finished) in
self.isVertical = true
})
}else {
UIView.animate(withDuration: 0.2, animations: {
self.navigationItem.rightBarButtonItem?.customView?.transform = CGAffineTransform(rotationAngle: 90 * .pi / 180)
}, completion: { (finished) in
self.isVertical = false
})
} }
Show button property:
It could be how you've set the custom view in the bar item. Maybe this self.navigationItem.rightBarButtonItem?.customView?. is returning nil. Anyway, here is a working version:
Creating the custom UIBarButtonItem:
let button1: UIButton = UIButton(frame: CGRect(x: 0, y: 0, width: 60, height: 30))
let button2: UIButton = UIButton(frame: CGRect(x: 70, y: 0, width: 60, height: 30))
override func viewDidLoad(_ animated: Bool) {
super.viewDidLoad(animated)
button1.backgroundColor = .gray
button1.setTitle("CustomButton", for: .normal)
button1.addTarget(self, action: #selector(rotateAction(_:)), for: .touchUpInside)
let barItem1: UIBarButtonItem = UIBarButtonItem(customView: button1)
button2.backgroundColor = .gray
button2.setTitle("CustomButton", for: .normal)
button2.addTarget(self, action: #selector(rotateAction(_:)), for: .touchUpInside)
let barItem2: UIBarButtonItem = UIBarButtonItem(customView: button1)
navigationItem.setRightBarButtonItems([barItem1, barItem2], animated: true)
}
Animate the tapped button:
#objc func rotateAction(_ sender: UIButton) {
let customView = sender
let transform: CGAffineTransform = isVertical ? .identity : CGAffineTransform(rotationAngle: 90 * .pi / 180)
UIView.animate(withDuration: 0.2, animations: {
customView.transform = transform
}, completion: { (finished) in
self.isVertical = !self.isVertical
})
}
To avoid replacing the bar button item/items set from storyboard, get those button items and create an array of bar button item including those with the ones you created in code:
let existingBarItems: [UIBarButtonItem] = navigationItem.rightBarButtonItems ?? []
let rightBarItems = existingBarItems = [yourCustomButtonItem]
navigationItem.setRightBarButtonItems(rightBarItems, animated: true)
And make sure your custom bar button item's frame doesn't intersect with existing buttons.

UIGestureTap to dismiss view

I am trying to enable UIGestureTap on a custom view. I have a view controller, and in that view controller, when I press a button, a custom view pops up.
var transparentBackground = UIView()
#IBAction func UserViewImage(_ sender: UIButton) -> Void {
self.transparentBackground = UIView(frame: UIScreen.main.bounds)
self.transparentBackground.backgroundColor = UIColor(white: 0.0, alpha: 0.4)
UIApplication.shared.keyWindow!.addSubview(self.transparentBackground)
self.opaqueView = self.setupOpaqueView()
self.transparentBackground.addSubview(opaqueView)
UIApplication.shared.keyWindow!.bringSubview(toFront: self.transparentBackground)
self.view.bringSubview(toFront: transparentBackground)
}
I want to be able to tap on the transparentBackground view and dismiss it. So I have a dismiss function called removeAnimate()
func removeAnimate()
{
UIView.animate(withDuration: 0.25, animations: {
self.transparentBackground.transform = CGAffineTransform(scaleX: 1.3, y: 1.3)
self.transparentBackground.alpha = 0.0;
}, completion:{(finished : Bool) in
if (finished)
{
self.transparentBackground.removeFromSuperview()
}
});
}
So, in viewdidload I enabled the UITapGesture:
let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(removeAnimate))
self.transparentBackground.addGestureRecognizer(gestureRecognizer)
self.transparentBackground.isUserInteractionEnabled = true
I know the function removeAnimate works because I used it on a button in the transparentBackground view and it works perfectly. But when I tap on the transparentBackground view it does not dismiss and I am not sure what I am doing wrong
func setupOpaqueView() -> UIView{
let mainView = UIView(frame: CGRect(x: 16, y: 132, width: Int(UIScreen.main.bounds.width-32), height: 403))
mainView.backgroundColor = UIColor.clear
mainView.layer.cornerRadius = 6
self.imageView = UIImageView(frame: CGRect(x: 29, y: 18, width: 274, height: 350))
mainView.addSubview(OKbutton)
mainView.addSubview(self.imageView)
OKbutton.addTarget(self, action: #selector(ThirdWheelViewController.handleOKButtonTapped(_:)), for: .touchUpInside)
return mainView
}
This is an example and hope it helps you:
First of all create a variable:
var customView:UIView!
This is going to be our function for adding a custom view:
#IBAction func customAction(_ sender: AnyObject) {
self.customView = UIView.init(frame: CGRect.init(x: self.view.bounds.width / 2, y: self.view.bounds.height / 2, width: 100, height: 100))
self.customView.backgroundColor = UIColor.red
self.view.addSubview(self.customView)
let tap = UITapGestureRecognizer.init(target: self, action: #selector(self.removeFromSuperView))
tap.numberOfTapsRequired = 1
self.customView.addGestureRecognizer(tap)
}
And finally:
func removeFromSuperView() {
self.customView.alpha = 1.0
self.customView.transform = .identity
UIView.animate(withDuration: 0.3, animations: {
self.customView.alpha = 0.0
self.customView.transform = .init(scaleX: 1.5, y: 1.5)
}) { (finished) in
if !finished {
} else {
self.customView.removeFromSuperview()
}
}
}

Rotate UIBarButtonItem Swift

In Swift, I have a hamburger bar button, so when tapped I want that hamburger Bar button to rotate 90 degrees (so that the lines are vertical) and then when you click it again I would like it to go back to it's original state (horizontal)
NOTE: Can you make sure that this works for a UIBarButtonItem, because some solution to a normal UIButton does not work.
I use a UIButton inside of UIBarButtonItem to achieve this, and a variable with state vertical or not
this is my storyboard setup
Here is the code of simple view controller
import UIKit
class ViewController: UIViewController {
var isVertical : Bool = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func rotateAction(_ sender: Any) {
if(!self.isVertical)
{
UIView.animate(withDuration: 0.2, animations: {
self.navigationItem.leftBarButtonItem?.customView?.transform = CGAffineTransform(rotationAngle: 90 * .pi / 180)
}, completion: { (finished) in
self.isVertical = true
})
}else{
UIView.animate(withDuration: 0.2, animations: {
self.navigationItem.leftBarButtonItem?.customView?.transform = CGAffineTransform.identity
}, completion: { (finished) in
self.isVertical = false
})
}
}
}
Result
Hope this helps
#IBAction func rotateAction1(_ sender: Any) {
if (!self.isVertical) {
UIView.animate(withDuration: 0.2, animations: {
self.navigationItem.leftBarButtonItem?.customView?.transform = CGAffineTransform(rotationAngle: 90 * .pi / 180)
}, completion: {
(finished) in
self.isVertical = true
})
revealViewController().revealToggle(true)
} else {
UIView.animate(withDuration: 0.2, animations: {
self.navigationItem.leftBarButtonItem?.customView?.transform = CGAffineTransform.identity
}, completion: {
(finished) in
self.isVertical = false
})
revealViewController().revealToggle(false)
}
}
Swift 4:
func rotateBarButton() {
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 40, height: 40)) // Create new button & set its frame
button.setImage(#imageLiteral(resourceName: "settings"), for: UIControlState()) // Assign an image
let lef = UIBarButtonItem(customView: button)
self.navigationItem.leftBarButtonItem = lef// Set as barButton's customView
// Gets you half way there //
UIView.animate(withDuration: 0.8, delay: 0.1, options: UIViewAnimationOptions.curveEaseIn, animations: {
self.navigationItem.leftBarButtonItem?.customView?.transform = CGAffineTransform(rotationAngle: CGFloat(M_PI))
}, completion: nil)
// Rotates all the way around //
UIView.animate(withDuration: 0.5, delay: 0.5, options: UIViewAnimationOptions.curveEaseIn, animations: {
self.navigationItem.leftBarButtonItem?.customView?.transform = CGAffineTransform(rotationAngle: CGFloat(M_PI * 2))
}, completion: nil)
}

Stop block of animations with UITapGestureRecognizer

I have got this problem with breaking animations block in my app. I am animating an image inside UIScrollView (zooming-in, moving from left to right, zooming-out). Animation is being launched on tap with UITapGestureRecognizer.
The problem is that even though I can zoom-out the image when it is being animated, animations block continues and as a result I get the image off the iPhone screen.
I have tried to use removeAllAnimations() method on both scrollView.layer and view.layer but it seems not to work.
Here is my code:
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
setupGestureRecognizer()
}
func setupGestureRecognizer() {
let singleTap = UITapGestureRecognizer(target: self, action: #selector(self.handleSingleTap(recognizer:)))
singleTap.numberOfTapsRequired = 1
scrollView.addGestureRecognizer(singleTap)
}
func handleSingleTap(recognizer: UITapGestureRecognizer) {
animateRecipeImage()
}
// MARK: - Recipe Image Animation
func animateRecipeImage() {
let offset = CGPoint(x: 0, y: 0)
var middleOffset = CGPoint()
let endOffset = CGPoint(x: (imageView.bounds.width / 2), y: 0)
// To avoid animation in landscape mode we check for current device orientation
if (UIDeviceOrientationIsPortrait(UIDevice.current.orientation)) {
if (scrollView.zoomScale > scrollView.minimumZoomScale) {
scrollView.setZoomScale(scrollView.minimumZoomScale, animated: true)
// Remove all animations and update image contraints to fit the screen
self.scrollView.layer.removeAllAnimations()
self.view.layer.removeAllAnimations()
updateConstraintsForSize(size: view.bounds.size)
} else {
scrollView.setZoomScale(scrollView.maximumZoomScale, animated: true)
let screenWidth = screenSize.width
// Handle big screen sizes
if (screenWidth < self.imageView.bounds.width) {
middleOffset = CGPoint(x: ((self.imageView.bounds.width - screenWidth) * self.scrollView.zoomScale), y: 0)
} else {
middleOffset = CGPoint(x: (self.imageView.frame.width - screenWidth), y: 0)
}
// Start animating the image
UIView.animate(withDuration: 2, delay: 0.5, options: [.allowUserInteraction], animations: {
self.scrollView.setContentOffset(offset, animated: false)
}, completion: { _ in
UIView.animate(withDuration: 4, delay: 0.5, options: [.allowUserInteraction], animations: {
self.scrollView.setContentOffset(middleOffset, animated: false)
}, completion: { _ in
UIView.animate(withDuration: 1.0, delay: 0.2, usingSpringWithDamping: 0.4, initialSpringVelocity: 1.1, options: [.allowUserInteraction], animations: {
self.scrollView.setContentOffset(endOffset, animated: false)
}, completion: nil)
})
})
}
}
}
Any ideas how to break that animations block? The result I would like to achieve is break animation and zoom-out image.

added button to sceneKit view but it has a lag

I added a custom button to the sceneKit view. When it is touched, it plays an animation, indicating that it was clicked. The problem I'm facing is the delay between user touch and start of animation. My scene has 28.1K triangles and 84.4K vertices. Is that to much or do I need to implement buttons differently. The scene renders with 60fps. I added the button via sceneView.addSubview: Thanks for answers
viewDidLoad(){
// relevant code
starButton = UIButton(type: UIButtonType.Custom)
starButton.frame = CGRectMake(100, 100, 50, 50)
starButton.setImage(UIImage(named: "yellowstar.png"), forState: UIControlState.Normal)
sceneView.addSubview(starButton)
starButton.addTarget(self, action: "starButtonClicked", forControlEvents: UIControlEvents.TouchUpInside)
starButton.adjustsImageWhenHighlighted = false
}
func starButtonClicked(){
animateScaleDown()
}
func animateScaleDown(){
UIView.animateWithDuration(0.1, animations: {
self.starButton.transform = CGAffineTransformMakeScale(0.8, 0.8)
}, completion: { _ in
self.wait()
})
}
func wait(){
UIView.animateWithDuration(0.2, animations: {}, completion: { _ in
UIView.animateWithDuration(0.2, animations: {
self.starButton.transform = CGAffineTransformMakeScale(1, 1)
})
})
}
Okay I solved it. The problematic piece of code is
starButton.addTarget(self, action: "starButtonClicked", forControlEvents: UIControlEvents.TouchUpInside)
UIControlEvent.TouchUpInside gives the illusion of lag. Changing it to .TouchDown is much better.
For Swift 5
var starButton = UIButton()
func a () {
starButton = UIButton(type: UIButton.ButtonType.custom)
starButton.frame = CGRect(x: 100, y: 100, width: 50, height: 50)
starButton.backgroundColor = .blue
SpielFenster.addSubview(starButton)
starButton.addTarget(self, action: #selector(starButtonClicked), for: UIControl.Event.touchDown)
starButton.adjustsImageWhenHighlighted = false
}
#objc func starButtonClicked(){
animateScaleDown()
}
func animateScaleDown(){
UIView.animate(withDuration: 0.1, animations: {
self.starButton.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
}, completion: { _ in
self.wait()
})
}
func wait(){
UIView.animate(withDuration: 0.2, animations: {}, completion: { _ in
UIView.animate(withDuration: 0.2, animations: {
self.starButton.transform = CGAffineTransform(scaleX: 1, y: 1)
})
})
}

Resources