UIView animates away on Timer - ios

So there is a UITextField and I have a limit of characters on the field. If user tries to enter anything bigger, UIView appears. I already have that part animated. Here is what I have:
public void animateHoursMesg() {
var HoursMesgExpandPos = new PointF (248.0f, 273.0f);
var HoursMesgInitPos = new PointF (400.0f, 273.0f);
UIView.Animate (
duration: 0.3f,
delay: 0,
options: UIViewAnimationOptions.CurveEaseInOut,
animation: () => {
if (Flag_HoursMesg) {
view_HoursLimitMesg.Center = HoursMesgInitPos;
Flag_HoursMesg = false;
} else {
view_HoursLimitMesg.Center = HoursMesgExpandPos;
Flag_HoursMesg = true;
}
},
completion: () => {
}
);
}
The problem is I want this view to animate away 5 seconds after it appears.
Can someone please help me with this?
Thank you for your time.

In your completion block on the animate method, use an NSTimer to schedule a block to execute 5 seconds from then.
[NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:#selector(animateAway)
userInfo:nil
repeats:NO];
Then just create another method for the animateAway that reverses your previous animation.

In the completion block of the animation, you can run a different animation to animate the view away with a delay of 5 seconds.

Related

iOS animation malfunctioning, Y-Coordinate Problems

For hours I've been trying to solve the smallest animation glitch. My code successfully moves the view off screen, then animates it back in. It gets the x-coordinations right but the Y axis has behavior I don't understand. Here's the code:
func listTrans_slideIn (slideFrom: String) {
//var newFrame = tableView.frame
tableView.frame.origin.x = 1000
//tableView.frame.origin.y = 100
print("Table pushed to side")
UIView.animateKeyframesWithDuration(1.375 /*Total*/, delay: 0.0, options: UIViewKeyframeAnimationOptions.CalculationModeLinear, animations: {
UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 1/1, animations:{
self.tableView_toTLG_Top.constant = 130
self.tableView_toSV_Left.constant = 0
self.tableView_toSV_Right.constant = 0
self.setupView()
//newFrame.origin.y = self.hdrBox.frame.height+50
//newFrame.origin.x = 0
//self.tableView.frame = newFrame
self.tableView.layoutIfNeeded()
})
},
completion: { finished in
if (!finished) { return }
})
}
The weird behavior is that if I put the correct y-coordinate in the animation keyframe, it comes in too high but then settles at the correct coordinate. If I put in a y-Coordinate that is too low, it comes in at the correct height but then settles too low.
As you can see, I've tried using frames and constraints. I've tried changing the height that I move it off screen to, but that seems to have no effect.
Anyone have any idea why I've spent half my day seeing this bug?
Can you try something like this :
// Use the same value here and below, it moves it out of the screen
self.tableView.center.y -= 500
UIView.animateWithDuration(1.0, animations: { () -> Void in
// Then it comes back
self.tableView.center.y += 500
})
This turned out to be an order of operations problem. The solution required that I move the animation to take place in the viewDidAppear.
Other notes:
To make the animation look as smooth as possible, consider turning off the segue's animation.
Also make sure you're running the segue call and animation in your main thread so that everything happens smoothly and without delay

removeFromSuperview() Not Removing Reference To View, CPU Load Remains High

I have an activity indicator that I created. It's a series of five UIViews that animate their alphas from 0.0 -> 1.0 for about 3 seconds a piece. In the device profile the CPU is over 100% and energy usage is "Very High". The profile levels remain at that height even after running .removeFromSuperview() on the container view of the activityIndicator, also the same if I remove each subview from the container view and then the container itself.
My question is what is the proper way to remove a series of views from a parent view so they no longer are referenced? Or I suppose that I could be asking the wrong question, maybe it's not in the removal but in the implementation of the activity view. Why would that type of simple animation create such a high CPU load?
The high load happens most specifically when the activityIndicator is placed in a viewController over a nested tableView while the tableView loads.
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(true)
if currentMatchObject == nil {
let indicator = SquaresActivityIndicator()
checkForUser(self) { () -> () in
delay(2.0, closure: { () -> () in
indicator.stopIndicator(self.view)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.matchTableView.frame.size.width = self.view.frame.width
self.matchTableView.frame.size.height = self.view.frame.height * 0.75
self.matchTableView.frame.origin.y = self.view.frame.height * 0.10
self.matchTableView.frame.origin.x = centerXAlignment(self.matchTableView, masterView: self.view)
self.matchTableView.backgroundColor = bgColor
})
})
self.reloadMatchView()
}
indicator.runIndicator(self.view, percentageSize: 15.0, activityBorderWidth: 6.0)
} else {
self.reloadMatchView()
}
}
ActivityIndicator stop function:
func stopIndicator(masterView: UIView) {
let viewToRemove = masterView.viewWithTag(123)
for v in (viewToRemove?.subviews)! {
v.removeFromSuperview()
}
viewToRemove?.removeFromSuperview()
}
In most cases this problem with animations or iterations in another threads.
How detect code?
Attention: as example i use my application.
Run instruments and choose Time
Start application and "go to" high load processor. Wait few seconds for aggregate information. The next, find own method ;)
And, code in this method:
- (void)animateKeep
{
CGFloat angle = self.activeAngle;
if (self.turnToLeft) {
angle += 90;
} else {
angle -= 90;
}
self.activeAngle = angle;
[UIView animateWithDuration:self.angleSpeed * 3 delay:.0f options:UIViewAnimationOptionCurveLinear animations:^{
self.transform = CGAffineTransformMakeRotation(DegreesToRadians(angle));
} completion:^(BOOL finished) {
[self animateKeep];
}];
}
And we see loop animation in completion code [self animateKeep]. And we should control all animation and stop animation before remove from superview.
Solution in this example - add custom flag (bool) and in start method control this flag.
Solution:
You should stop all animations and iterations (if exist in another thread) for this view before remove from superview.

Delay after each animation iteration in Swift

I have a Core Animation whose .repeatCount is set to Float.infinity. After each iteration of the Animation, ie. after each repetition, I want to have a delay of 3 seconds. How can I achieve this? Thanks!
You can use a function like the following to do what you need.
func animateInfinitelyWithDelay(delay: TimeInterval, duration: TimeInterval) {
UIView.animate(
withDuration: duration,
delay: delay,
options: UIView.AnimationOptions.curveEaseIn,
animations: { () -> Void in
// Your animation Code
}) { (finished) -> Void in
if finished {
self.animateInfinitelyWithDelay(delay: delay, duration: duration)
}
}
}
One way to accomplish this effect using Core Animation is to configure everything except the repeat count on the original animation object and then wrap it in an animation group with a longer duration and repeat that animation group instead.
let originalAnimation = /* create and configure original animation ... */
originalAnimation.duration = shortDuration
let group = CAAnimationGroup()
group.animations = [originalAnimation]
group.duration = shortDuration + delayAtTheEnd
group.repeatCount = .infinity
theLayer.add(group, forKey: "repeating animation with delay between iterations")
Note that depending on what the original animation is doing, you may need to configure a fill mode to achieve the right look.
You could also use a UIView keyframe animation (animateKeyframesWithDuration) where there is "dead time" built into the animation at the end, and then repeat that animation.

Swift UIView Animation block increment error

I have a UIView Animation block that I want to run on paragraphs in an array.
UIView.animateWithDuration(0.4, delay: 0.2, options: .CurveEaseOut, animations: {
var frame = self.textViewForPlayer.frame
frame.origin.y += 20
self.textViewForPlayer.frame = frame
}, completion: { finished in
UIView.animateWithDuration(0.4, delay: 0, options: .CurveEaseOut, animations: {
var frame = self.textViewForPlayer.frame
frame.origin.y -= 80
self.textViewForPlayer.frame = frame
}, completion: { finished in
})
}
)
textViewForPlayer = paragraphs[++currentParagraph]
Strange thing is - the first block (first animation before completion) runs the animation on the first paragraph, but the chained animation in the first completion block runs on the second paragraph (somehow the "paragraphs[++currentParagraph]" is executing in between the two blocks of animation.
Not sure how this is happening, the increment code is after the animation itself, so it seems bizarre or maybe even a bug that causes it to execute in the middle.
Your problem is that the animations and completion block are called at a latter time, but animateWithDuration returns immediately.
Everything outside the scope of the blocks will run without respect to the delay of the animation or the animation being finished.
Consider putting the incrementation inside your last finished block. This should increment the number at the end of both animations.
...,completion: { finished in
textViewForPlayer = paragraphs[++currentParagraph]
})

SlapshScreen Monogame Wp8

I try to making a splash screen
all i want is wait at splash screen for 1 sec then automatically load to play screen .
I try to use Thread.Sleep() but it's not work .
Any idea,Plsssssssss .
THANKS YOU :D
try something like this
timer = 10000f; // 10 seconds
Then in the update method:
timer -= gameTime.ElapsedGameTime.TotalMilliseconds;
if (timer <= 0.0f)
{
// trigger whatever happens when the timer expires.
}
Davor's solution is fine, but I suggest you to use TimeSpan if you have to handle with time:
TimeSpan timer = new TimeSpan(0, 0, 1); //1 second
Then in the Update method:
if (timer > TimeSpan.Zero)
timer -= gameTime.ElapsedGameTime;
if (timer < TimeSpan.Zero)
{
timer = TimeSpan.Zero;
//load your play screen
}
timer = TimeSpan.Zero ensures that you load your play screen only once.

Resources