Is there a standard way to display a short message to the user in an iOS application and then disappear automatically.
I have an app where a user can make changes. If he/she saves the changes I want to give feedback. But it's probably annoying if an AlertBox is displayed all the time and the user needs to klick on a button.
You have a few options that you can try. What you want might be the following :
Create an UIView, where you want to give feedback. This way, you can create it exactly the way you want it.
Set it hidden by default. yourView.alpha = 0.0f; => required if you want to animate when it appears, if not, just use yourView.hidden = true and ignore all animation stuff below, just replace it by yourView.hidden = false.
When you need your user to see your feedback you can animate it by the following :
[UIView beginAnimations:#"fadeIn" context:nil];
[UIView setAnimationDuration:0.5]; // add the value you want
yourView.alpha = 1.0f;
[UIView commitAnimations];
Right after, to hide it again but later, add the following :
NSTimeInterval timeInterval = 1.0f; // how long your view will last before hiding
[NSTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:#selector(hideView) userInfo:nil repeats:NO];
Finally, create your hideView method, that will be called by your timer :
-(void) hideView {
[UIView beginAnimations:#"fadeOut" context:nil];
[UIView setAnimationDuration:0.5]; // add the value you want
yourView.alpha = 0.0f;
[UIView commitAnimations];
}
Maybe there are better ways to do it, but i think this one will do the trick, and lets you create your view as you need it. The trick with animation will add a nice look and feel to your feedback. Hope that helps :)
You can create a Custom View by UIView and use the NSTimer to display it for a certain time and remove the view
You can display a custom view with [.... addSubview: yourView].
After that, u create a NSTimer, with a 1 second delay for example.
On the timerĀ“s selector, u can do a backcount, and show for example
on your custom view, how much remain time the view will be shown.
On the selector, make an if, and after X seconds just do
[youtView removeFromSuperview];
You can use a custom view with scheduled timer to present some info and then hide it when the timer completes.
However, if you are looking for a Android-style toast that shows pop-up like information and then hides after a specific time. Then, you might consider using Toast Control for iOS. This is one of the easiest controls (Atleast, I've come across) for implementing simple popup without having user to cancel it.
Related
The problem is when I'm using:
[transLabel.layer removeAllAnimations];
(transLabel is a UILabel that show the information)
After that, I try to add a new animation to this Label
[UIView animateWithDuration:showTime
animations:^{
transLabel.hidden = NO;
transLabel.transform = CGAffineTransformMakeScale(1.5, 1.5);
}
completion:^(BOOL finished) {
transLabel.hidden = YES;
transLabel.transform = CGAffineTransformMakeScale(1.0, 1.0);
}];
But It didn't work anymore, it just work at odd number click. Like, first time it works, and second time it doesn't work, but third time it shows again, forth not, fifth yes..
What I want to do is keep pushing down one button again again again
and the Label is show again again again with animation
Thank you and wait for your answer
If i understood your question correctly, the problem occurs because the presentation layer do all the animations and are the layer that actually performs all the animations. When you cancel an ongoing animation that is reflected upon the presentation layer and not the view layer. Try capturing the changes to the view's layer and see if that helps you in this case:
transLabel.layer.transform = transLabel.layer.presentationLayer.transform;
I just had a similar issue. The problem is that when you stop animation you hide your transLabel.
Show it right after [transLabel.layer removeAllAnimations]; like this:
[transLabel.layer removeAllAnimations];
transLabel.hidden = NO;
I have an iOS application where the main screen that is launched (A login screen) has 3 text fields and a button to "Login" below the fields. There is a content view within the main view which holds the fields and the button and it is vertically centered. When any of the 3 fields begins editing, the view shifts up such that they are visible and so is the button. The relevant code for this is:
(void)viewDidLoad {
[super viewDidLoad];
[userName addTarget: self action: #selector(slideFrameUp:) forControlEvents: UIControlEventEditingDidBegin];
[userName addTarget: self action: #selector(slideFrameDown:) forControlEvents: UIControlEventEditingDidEnd];
//.... same thing for 2 other fields
}
-(void) slideFrameUp: (id)sender {
CGFloat slidePoints = 116.0;
[self slideFrame: YES distance: slidePoints];
}
-(void) slideFrameDown: (id)sender {
CGFloat slidePoints = 116.0;
[self slideFrame: NO distance: slidePoints];
}
-(void) slideFrame:(BOOL) up distance: (NSInteger)amount {
const float movementDuration = 0.3f; // tweak as needed
int movement = (up ? -amount : amount);
[UIView beginAnimations: nil context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
This works fine and does what we need. The one hiccup is that when the user is editing a text field and presses the home button and then opens the app again, when the app re-opens (if it only went to background and wasn't killed) it will be positioned exactly how it was previously initially (for like 1/10th of a second) and then it will reset back to center with the keyboard still present, thus leaving it lower on the screen than it should be and hiding some fields. The thing is none of my code runs when the view position resets. slideFrame is not called at all either when the app enters background or when it goes back to active. None of my view related methods (viewDidLoad/viewDidAppear/viewWillAppear/viewWillDisappear, etc) are called on entering background or active. I'm wondering why does ios reposition my view when going back to active, and how can I prevent it?
I figured out one solution which I didn't really like. What I did was observe UIApplicationDidEnterBackgroundNotification and then dismiss the keyboard using the code:
[self.view endEditing: YES];
This seems to work fine except when the app opens the user is no longer focused in the field. I would prefer though if the app just opened back up as it was. I'm also just kind of curious why the system behaves this way and if maybe there is a more elegant way to handle this.
My approach would be to dismiss the keyboard as the app goes to background and set focus on your text field in viewWillAppear:
I have to give a delete thumbnail animation in my ipad application just like iphone/ipad applications delete effect.
Any body help me please sample photo is attached
If you need more details then kindly mention it in comments
I have done this using CGAffineTransformMakeRotation. Don't know there is some other better method. But What I have done is my logic you can copy that as it is and you just need to add a delete button on the left top of that view. In the following code I am just animating the thumbnail or any view just like iPad does on its home screen. One thing, You need to declare int direction globally. and every time when you will call this method you will set direction = 1;
-(void)shakeToDelete:(UIView *)shakeMe
{
[UIView animateWithDuration:0.1 animations:^
{
shakeMe.transform = CGAffineTransformMakeRotation(0.05 * direction);
}
completion:^(BOOL finished)
{
direction = direction * -1;
[self shakeToDelete:shakeMe];
}];
}
/// edit
I tried this way and got it working in my sample screen as attached in photo
You better should use an autoreverse and looped animation, cause creating animations over and over will fulfill the phone memory.
With this code, only one animation is retained.
view.transform = CGAffineTransformMakeRotation(-kDeleteAnimationAmplitude);
[UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationOptionRepeat|UIViewAnimationOptionAutoreverse animations:^{
view.transform = CGAffineTransformMakeRotation(kDeleteAnimationAmplitude);
} completion:nil];
Then if you want to stop your animation, just call:
[view.layer removeAllAnimations];
I have two animations running; show search bar and show banner. Both those animations are resizing the same view and if they are running on the same time (Which they are) the latest animation will cancel the resize. Is there anyway to check if UIView is currently animating and then standby for animation?
I'm pretty sure I'm not using CAAnimations, since Cocoa not is detecting such class.
This one is running when an ad was received. Unfortunately, that is the same time as ShowSearch is running.
- (void)adViewDidReceiveAd:(GADBannerView *)bannerView {
if (!hasloaded) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve: UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration: 1.0];
[bannerView_ setFrame:CGRectMake(0, self.view.frame.size.height, bannerView_.frame.size.width, bannerView_.frame.size.height)];
// move and grow
[bannerView_ setFrame:CGRectMake(0, self.view.frame.size.height-50, bannerView_.frame.size.width, bannerView_.frame.size.height)];
// set original position
[UIT setFrame:CGRectMake(UIT.frame.origin.x, UIT.frame.origin.y, UIT.frame.size.width, UIT.frame.size.height)];
// move and grow
[UIT setFrame:CGRectMake(UIT.frame.origin.x, UIT.frame.origin.y, UIT.frame.size.width, UIT.frame.size.height-50)];
[UIView commitAnimations];
hasloaded = true;
}
}
You can use the completion block in the UIView method +animateWithDuration:animations:completion: (which is a more modern alternative to beginAnimations/commitAnimations) to chain multiple animations (I'm guessing this is what you want to do?).
If you select your code while entering it and press control + K, you will preserve formatting and make it pretty. Try it. Reading the wall of text made from pasting code into a true-type non-color-formatted environment.
Nick Weaver says:
A UIView has a layer (CALayer). You can send animationKeys to it which will give you an array of keys which identify the animations attached to the layer. I suppose that if there are any entries, the animation(s) are running. If you want to dig even deeper have a look at the CAMediaTiming protocol which CALayer adopts. It does some more information on the current animation.
I am using the following code in my presenting VC to fade in the child modal VC, and this works fine:
self.infoViewController.view.alpha = 0.0;
[self.navigationController presentModalViewController:self.infoViewController animated:NO];
[UIView animateWithDuration:0.5
animations:^{self.infoViewController.view.alpha = 1.0;}];
However I can't get it to fade out, I have tried a few things, this is the latest I tried that doesn't work:
- (IBAction)dismissAction:(id)sender
{
if ([[self parentViewController] respondsToSelector:#selector(dismissModalViewControllerAnimated:)])
{
[[self parentViewController] dismissModalViewControllerAnimated:YES];
self.parentViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
self.parentViewController.view.alpha = 0.0;
[UIView animateWithDuration:0.5
animations:^{self.parentViewController.view.alpha = 1.0;}];
} else
{
[[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];
self.presentedViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
self.presentedViewController.view.alpha = 0.0;
[UIView animateWithDuration:0.5
animations:^{
self.presentedViewController.view.alpha = 1.0;}];
}
}
The modal view controller is faded out but immediately, not over a time period like it is when its displayed.
This (original part) is not to take away from H2CO3's correct answer. UIModalTransitionStyleCrossDissolve does pretty-much exactly the effect you're looking for. You are just not setting the modalTransitionStyle until it's to late. Replace all of your code with these functions in there respective positions:
-(void)show{
self.infoViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:self.infoViewController animated:YES];
}
- (IBAction)dismissAction:(id)sender{
[self dismissModalViewControllerAnimated:YES];
}
Edit in response to timing being an issue: Let's talk about the offending code. We'll concentrate on just the if true part, since it's essentially identical to the else.
[[self parentViewController] dismissModalViewControllerAnimated:YES];
self.parentViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
self.parentViewController.view.alpha = 0.0;
[UIView animateWithDuration:0.5
animations:^{self.parentViewController.view.alpha = 1.0;}];
If you're looking for a reciprocal animation this isn't it. In your original animation you set the next view's alpha to 0, then presented the next view controller, then set it's view's alpha to 1. So logically you need to dismiss the view controller after the animation; This is really easy using blocks. The code would look something like this:
[UIView animateWithDuration:0.5 animations:^{
self.view.alpha = 0;
} completion:^(BOOL b){
[self.presentingViewController dismissModalViewControllerAnimated:NO];
self.view.alpha = 1;
}];
This line of code animates the view's alpha to 0, then (upon completion) dismisses the presented view controller, and sets the view's alpha back to 1. This is a reciprocal animation.
In the docs of UIViewController, we can find:
#property(nonatomic, assign) UIModalTransitionStyle modalTransitionStyle
Set this property to UIModalTransitionStyleCrossDissolve and it will dissolve properly :)
Hope that helps.
I guess, this might be useful for those heroic guys, who still tries to use MPMoviePlayerViewController in full screen mode and with orientation, which differs from the app major one.
I've spent literally a half of working day playing with presenting MPMoviePlayerViewController modally or not modally. But there is no luck with that at all, in sense of transition animation changing. (The modal mode needed for setting orientation which differs from the app major orientation).
I tried presentViewController or presentModalViewController, but the result is the same. No matter what type is the modalTransitionStyle property set, if I do [... dismissViewControllerAnimated:true ...] then default transition style (UIModalTransitionStyleCoverVertical) used anyway. I tested that in iOS 5.1 device and in iOS 6 Simulator.
I haven't tried any other types of controllers... Considering that common controller has method dismissMoviePlayerViewControllerAnimated, I can assume, that this method is used anyway for dismissing a video controller, no matter how did it appear. (Entering transitions didn't work for me as well, except they did not process as CoverVertical (in case of modalTransitionStyle changing).
So, my solution was not use the transition animation at all.
I am sure, Apple had some reasons for allowing only some definite animation for MovieViewController (I really hope so, and that was made not because of "laziness"), but if they wanted some nice experience user would get, they failed, as in my app that's even better when the video appears without any animation (which is worse than CrossDisolving for sure) but that's better than banal CoverVertical.
Looking on that from developer's point of view, it really sounds like they spend much more money for designers to paint nice icons for customers instead of more pleasant and effective work of developers. (