Flash and remove my arrow - ios

After flashing my arrow for x seconds, I want it to disappear automatically. I used [self.arrowImage.slayer removeAllanimations], but it does not work:
#IBAction func answerButtonTapped(sender: AnyObject){
var score = scoreField.text?.toInt()
var question = questionField.text
// display question
questionField.text = listOfQuestions[currentQuestionIndex]
if (questionField.text == listOfQuestions[9]) {
if (score >= 7) {
// move to stage 2
}
if (score < 3) {
arrowImage.hidden = false
self.arrowImage.alpha = 0;
UIView.animateWithDuration(0.5, delay: 0.2,
options: UIViewAnimationOptions.Repeat | UIViewAnimationOptions.Autoreverse,
animations: {
self.arrowImage.alpha = 0.5
},
completion:nil)
}
// questions of stage 1 still display

In the completion block of your animation, just set the arrowImage to be hidden.
self.arrowImage.hidden = true

Related

Repeat Fade In / Fade Out Between Two Different Texts On Same UILabel

I've been searching online for an answer to my question but there doesn't seem to be any solutions. I have a UILabel which contains two interchangeable icons (from FontAwesome). I would like to create an animation where it changes the UILabels text from one to the other repeatedly.
What I have so far is an animation which calls itself again and again. It seemed to look fine on the simulator but when I ran it on the phone it didn't work how I wanted it to. I seem to almost be there but my code creates some sort of flash when it fades out
func animateLabel() {
self.runningPersonLabel.text = self.runningPersonLabel.text == "ICON 1" ? "ICON 2" : "ICON 1"
self.runningPersonLabel.sizeToFit()
self.runningPersonLabel.center = modalContainer.boundsCenter
self.runningPersonLabel.frameTop = titleLabel.frameBottom + 40
UIView.animate(withDuration: 2, delay: 0, options: [.autoreverse], animations: {
self.runningPersonLabel.alpha = 1.0
}, completion: { finished in
self.runningPersonLabel.alpha = 0.0
self.animateLabel()
})
}
Try with this class:
import UIKit
#IBDesignable class FadingLabel: UILabel
{
// The secondary text
#IBInspectable var secondaryText:String?
var primaryText:String?
// Animation time, is divided by 2
#IBInspectable var animationTime:TimeInterval = 1
// Set this flag to true to stop animation
var stop = true
// Start the animation
func startAnimating()
{
stop = false
if primaryText == nil
{
primaryText = self.text
}
fadeAnim()
}
// Stop the animation
func stopAnimating(_ sender: UIButton)
{
stop = true
}
#objc private func fadeAnim()
{
if stop
{
return
}
// Fade out
UIView.animate(withDuration: animationTime / 2, animations: {
self.alpha = 0
}) { (complete) in
UIView.animate(withDuration: self.animationTime / 2, animations: {
if self.text == self.primaryText
{
self.text = self.secondaryText
}
else
{
self.text = self.primaryText
}
self.alpha = 1
}, completion: { (complete2) in
self.fadeAnim()
})
}
}
}
Usage:
put a label in your view controller;
set the label class to FadingLabel;
set the secondary text and the animation time in the storyboard inspector
call the methods startAnimating or stopAnimating as needed.

iOS - Transition between gradients?

I'm trying to rotate the background colour endlessly between two different gradients, but the actual transition isn't lasting as long as expected (it lasts for less than a second and there's no delay between each transition).
var backgroundColours = [CAGradientLayer()]
var backgroundLoop = 0
override func viewDidLoad() {
super.viewDidLoad()
backgroundColours = [Colors.init().one, Colors.init().two] // These are two CAGradientLayers but I haven't included their code
backgroundLoop = 0
self.animateBackgroundColour()
}
func animateBackgroundColour () {
backgroundLoop = (backgroundLoop + 1) % (backgroundColours.count)
UIView.animate(withDuration: 2.0, delay: 2.0, options: .curveLinear, animations: {
self.view.backgroundColor = UIColor.clear
let backgroundLayer = self.backgroundColours[self.backgroundLoop]
backgroundLayer.frame = self.view.frame
self.view.layer.insertSublayer(backgroundLayer, at: 0)
}, completion: { (Bool) -> Void in
self.animateBackgroundColour()
})
This is all inside the ViewController Class
UIView.animate animates only about five specialized view properties. You are not animating any of those properties. What you want is layer animation (e.g. CABasicAnimation).

UIView Animate only animates if it's in a IBAction. How do I get it to animate in my situation?

func pickWash() {
bottomChange = self.mapView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -350.0)
bottomChange.isActive = true
UIView.animate(withDuration: 10.0, animations: {
self.view.layoutIfNeeded()
self.waterlessLabel.isHidden = false
self.exteriorInterior.isHidden = false
self.exteriorOnly.isHidden = false
self.info.isHidden = false
self.blackLine.isHidden = false
self.extIntPrice.isHidden = false
self.extPrice.isHidden = false
self.confirmWash.isHidden = false
self.when.isHidden = false
self.timeChoice.isHidden = false
}, completion: nil)
}
func tester(){
self.pickWash()
}
In actuality, my tester method in my code is using Google's Place autocomplete iOS, but I did not want to flood my code with useless autocomplete code. Thus, when the user is done entering their location in Google's autocomplete, the function pickwash() is called and the animate does not work. It only worked for me when I had it in an IBAction with a button. Any idea?
pickWash() is being on a thread other than the main one (as confirmed in OP comments) and since the main thread is the only one allowed to work on the UI the behaviour is undefined (here nothing happens). You have to move your code execution to the main thread using
func pickWash() {
// Code here is on a non-main thread
DispatchQueue.main.async {
// Code here is executed on the main thread
bottomChange = self.mapView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -350.0)
bottomChange.isActive = true
UIView.animate(withDuration: 10.0, animations: {
self.view.layoutIfNeeded()
self.waterlessLabel.isHidden = false
self.exteriorInterior.isHidden = false
self.exteriorOnly.isHidden = false
self.info.isHidden = false
self.blackLine.isHidden = false
self.extIntPrice.isHidden = false
self.extPrice.isHidden = false
self.confirmWash.isHidden = false
self.when.isHidden = false
self.timeChoice.isHidden = false
}, completion: nil)
}
}
func tester(){
self.pickWash()
}
isHidden can't be animated use alpha, see the below code.
and I noticed that you are setting the time to 10.0 and 10 is so long.
func pickWash() {
UIView.animate(withDuration: 1.0, animations: {
self.view.layoutIfNeeded()
self.waterlessLabel.alpha = 1
self.exteriorInterior.alpha = 1
self.exteriorOnly.alpha = 1
self.info.alpha = 1
self.blackLine.alpha = 1
self.extIntPrice.alpha = 1
self.extPrice.alpha = 1
self.confirmWash.alpha = 1
self.when.alpha = 1
self.timeChoice.alpha = 1
}, completion: nil)
}
func tester(){
self.pickWash()
}
If you want to animate a constraint, all you have to do is update the constant property. Here's some sample code:
#IBOutlet private weak var mapViewBottomConstraint; // If you are not using InterfaceBuilder, then hold a reference to the bottom constraint when you add it to your view.
func pickWash() -> Void {
self.mapViewBottomConstraint.constant = -350.0; // or whatever is appropriate here.
UIView.animate(withDuration: 1.0, animations: { [weak self] in
self?.view.layoutIfNeeded()
// do your stuff
}, completion: nil)
}

How to animate an indicating arrow below a specific position in a fixed time?

As you can see, there are 5 buttons over an indicating arrow, the arrow triangle object is separate, and I can move it.
By default the triangle is on button 1
What is the best way to make it like when I tap button 3, it moves there in 0.2 second, just to take 0.2 second whatever number of space it moves, what is the best way to do it?
Do you I need to make interpolation or there is something ready for this?
as Mr Daniel Nagy said
animateWithDuration did the job, done ! :)
func moveSideBarToXposition(target: Int)
{
var convertedXposition = CGFloat(0)
if(target == 1){convertedXposition = imageViewFacebook.center.x}
if(target == 2){convertedXposition = imageViewTwitter.center.x}
if(target == 3){convertedXposition = imageViewSnapChat.center.x}
if(target == 4){convertedXposition = imageViewInstagram.center.x}
if(target == 5){convertedXposition = imageViewLinkedIn.center.x}
if(target == 6){convertedXposition = imageViewPintrest.center.x}
UIView.animateWithDuration(0.2, delay: 0.05, options: UIViewAnimationOptions.TransitionNone, animations:
{
() -> Void in
self.imageViewHighlightTri.frame = CGRectMake(convertedXposition, self.imageViewHighlightTri.frame.origin.y, self.imageViewHighlightTri.frame.size.width, self.imageViewHighlightTri.frame.size.height)
}, completion: { (finished: Bool) -> Void in })
}

Swift UIView appearing in different places

Im trying to make a small game. And there is some problem with the animation. Im new to Swift. So lets take a look. I create a UIImageView picture and want to do animation of this picture appear in a different places on a screen. I believe that the algorithm will look like this:
Infinite loop{
1-GetRandomPlace
2-change opacity from 0 to 1 and back(with smooth transition)
}
Looks simple, but I can't understand how to do it correctly in Xcode.
Here is my test code but it looks useless
Thank you for help and sorry if there was already this question, I can't find it.
class ViewController: UIViewController {
#IBOutlet weak var BackgroundMainMenu:UIImageView!
#IBOutlet weak var AnimationinMenu: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// MoveBackgroundObject(AnimationinMenu)
// AnimationBackgroundDots(AnimationinMenu, delay: 0.0)
// self.AnimationinMenu.alpha = 0
//
// UIImageView.animateWithDuration(3.0,
// delay: 0.0,
// options: UIViewAnimationOptions([.Repeat, .CurveEaseInOut]),
// animations: {
// self.MoveBackgroundObject(self.AnimationinMenu)
// self.AnimationinMenu.alpha = 1
// self.AnimationinMenu.alpha = 0
// },
// completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(animated: Bool) {
AnimationBackgroundDots(AnimationinMenu, delay: 0.0)
}
func ChangeOpacityto1(element: UIImageView){
element.alpha = 0
UIView.animateWithDuration(3.0) {
element.alpha = 1
}
}
func ChangeOpacityto0(element: UIImageView){
element.alpha = 1
UIView.animateWithDuration(3.0){
element.alpha = 0
}
}
func AnimationBackgroundDots(element: UIImageView, delay: Double){
element.alpha = 0
var z = 0
while (z<4){
MoveBackgroundObject(AnimationinMenu)
UIImageView.animateWithDuration(3.0,
animations: {
element.alpha = 0
element.alpha = 1
element.alpha = 0
},
completion: nil)
z++
}
}
func MoveBackgroundObject(element: UIImageView) {
// Find the button's width and height
let elementWidth = element.frame.width
let elementHeight = element.frame.height
// Find the width and height of the enclosing view
let viewWidth = BackgroundMainMenu.superview!.bounds.width
let viewHeight = BackgroundMainMenu.superview!.bounds.height
// Compute width and height of the area to contain the button's center
let xwidth = viewWidth - elementWidth
let yheight = viewHeight - elementHeight
// Generate a random x and y offset
let xoffset = CGFloat(arc4random_uniform(UInt32(xwidth)))
let yoffset = CGFloat(arc4random_uniform(UInt32(yheight)))
// Offset the button's center by the random offsets.
element.center.x = xoffset + elementWidth / 2
element.center.y = yoffset + elementHeight / 2
}
}
The problem is in AnimationBackgroundDots.
You are immediately creating 4 animations on the same view but only one can run at a time. What you need to do is wait until one animation is finished (fade in or fade out) before starting a new one.
Also, the animations closure is for setting the state you want your view to animate to. It looks at how your view is at the start, runs animations, then looks at the view again and figures out how to animate between the two. In your case, the alpha of the UIImageView starts at 0, then when animations runs, the alpha ends up being 0 so nothing would animate. You can't create all the steps an animation should take that way.
Want you need to do it move your view and start the fade in animation. The completion closure of fading in should start the fade out animation. The completion closure of the fading out should then start the process all over again. It could look something like this.
func AnimationBackgroundDots(element: UIImageView, times: Int) {
guard times > 0 else {
return
}
MoveBackgroundObject(element)
element.alpha = 1
// Fade in
UIView.animateWithDuration(3.0, animations: {
element.alpha = 1
}, completion: { finished in
// Fade Out
UIView.animateWithDuration(3.0, animations: {
element.alpha = 0
}, completion: { finished in
// Start over again
self.AnimationBackgroundDots(element, times: times-1)
})
})
}
You called also look at using keyframe animations but this case is simple enough that theres no benefit using them.
Also as a side note. The function naming convention in swift is to start with a lowercase letter, so AnimationBackgroundDots should be animationBackgroundDots.

Resources