I'm developing an app with a scroll view in it. It's not immediately obvious that there's more content, and there's no scroll indicator (scroll view is paged).
So, to give the user a 'hey, there's something down here...', I would like to have the scroll view do a subtle bounce - down then up - on launch. I've tried this:
- (void)viewDidLoad
....
[NSTimer scheduledTimerWithTimeInterval:0.8 target:self selector:#selector(bounceScrollView) userInfo:nil repeats:NO];
}
- (void)bounceScrollView
{
[self.verticalScrollViews[0] scrollRectToVisible:CGRectMake(0, 600, 1, 1) animated:YES];
[NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(_unbounceScrollView) userInfo:nil repeats:NO];
}
- (void)_unbounceScrollView
{
[self.verticalScrollViews[0] scrollRectToVisible:CGRectZero animated:YES];
}
However, this code makes the view get 'stuck' at about halfway between two pages.
Any help?
Idea 1: You need to turn off paging, animate the bounce, and turn the paging back on.
Idea 2: Your second move is coming way too soon:
scheduledTimerWithTimeInterval:0.01
Experiment with longer time intervals! I would start with 0.4.
Idea 3: Instead of your bounce, why not use flashScrollIndicators? This is exactly what it is for!
I had a memory problems when using NSTimer. That's why I used another solution for scrollView preview.
[UIView animateWithDuration:1.0
delay:0.00
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
_scrollView.contentOffset = CGPointMake(200,0);
}
completion:^(BOOL finished){
[UIView animateWithDuration:1.0
delay:0.00
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
_scrollView.contentOffset = CGPointMake(0,0);
}
completion:^(BOOL finished){
}
];
}
];
Related
I implemented corePlot in my xcode project. I'm trying to "explode" a slice of the pie chart with animation. Here is the method I'm using:
- (void)radialOffsetForPieChart:(CPTPieChart *)pieChart recordIndex:(NSUInteger)idx
{
if (myIndex == idx) {
return 20;
}
return 0;
}
I have another method which calls [pieChart reloadRadialOffset];.
For example:
- (void)thisMethod {
[pieChart reloadRadialOffset];
}
How can I animate the reloadRadialOffsets?
I just added an example to the "Simple Pie Chart" demo in the Plot Gallery example app. I added two properties to the controller to hold the index of the selected slice and the desired offset value. Since the offset is a CGFloat it is easily animated using Core Animation or CPTAnimation.
Set the index to NSNotFound to indicate that no slice should be selected. You could also use an array or set of indices if you want to highlight more than one slice at a time.
self.offsetIndex = NSNotFound;
Trigger the animation to offset the slice:
self.offsetIndex = idx;
[CPTAnimation animate:self
property:#"sliceOffset"
from:0.0
to:35.0
duration:0.5
animationCurve:CPTAnimationCurveCubicOut
delegate:nil];
The plot datasource needs the radial offset method:
-(CGFloat)radialOffsetForPieChart:(CPTPieChart *)pieChart recordIndex:(NSUInteger)index
{
return index == self.offsetIndex ? self.sliceOffset : 0.0;
}
The sliceOffset property needs a custom setter to trigger the plot to update the offsets during the animation:
-(void)setSliceOffset:(CGFloat)newOffset
{
if ( newOffset != sliceOffset ) {
sliceOffset = newOffset;
[self.graphs[0] reloadData];
}
}
In your question is bit confusing. Your question title says "how to reaptedly call a mathod using timer" and at the end of your question it changes to "How can I animate the reloadRadialOffsets?".
For repeatedly calling a method you can use any of the following options
option 1.
[NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(animatedPie:)
userInfo:nil
repeats:YES];
option 2:
[self performSelector:#seletor(animatePie) withObject:nil afterDelay:1.0];
and in your method
-(void) animatePie
{
[UIView animateWithDuration:1.0 animations:^
{
[pieChart reloadRadialOffsets];
} completion:^(BOOL finished)
{
[self performSelector:#seletor(animatePie) withObject:nil afterDelay:1.0];
}];
}
Here the repeated method will be called agian with a delay once the animation is complete.
When you wanted to stop the animation call
- (void)cancelPerformSelector:(SEL)aSelector target:(id)target argument:(id)arg
When timer is used it will be fired once the interval is elapsed.
For animation
You can use
[UIView animateWithDuration:1.0 animations:^
{
} completion:^(BOOL finished) {
}];
or user
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:key];
You can use below code. In this UIViewAnimationOptionRepeat is helpful for repeat animation what you want to achieve..
[UIView animateWithDuration:5
delay:1
options:UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionRepeat
animations:^{
[UIView setAnimationRepeatCount:2];
[pieChart reloadRadialOffsets];
}
completion:nil];
//Still you want to call method using timer
NSTimer *animateTimer;
animateTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self
selector:#selector(thisMethod) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:animateTimer forMode:NSDefaultRunLoopMode];
[animateTimer fire];
- (void)thisMethod {
[pieChart reloadRadialOffsets];
}
Hope it helps you...!
I want to rotate an image by 360 degree delay for 2 or 3 seconds again rotate it by 360 degree and the process should continue on. Any possible suggestions for the same ? Actually tried Cgaffinetransfom but its not working for 360 degree .
You can rotate your image like this:
[YourImageView setTransform:CGAffineTransformMakeRotation(10*(M_PI/360))];
Now to perform it continuous you need to set the timer like this:
[NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:#selector(doRotateImage) userInfo:nil repeats:YES];
Rotate function:
-(void)doRotateImage{
[YourImageView setTransform:CGAffineTransformMakeRotation(10*(M_PI/360))];
}
Thats it.
You could try this method:
- (void)rotateImageView{
[UIView animateWithDuration:0.4f delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
[yourImageView setTransform:CGAffineTransformRotate(yourImageView.transform, M_PI_2)];
}completion:^(BOOL finished){
if (finished) {
[self rotateImageView];
}
}];
}
I am stuck in something I hope you guys can help
I have a scrollview , when the user scrolling a subview appear with animation from bottom to top. the timer then start counting 5 sec and then call another method to hide the subview
I implemented and it works as wanted except :
while the subview appear and when it's almost to hide , if I scrolled that moment the subview appear statically and never hide . try to scrolling again another subview dynamically work over the static one ( as it duplicated or something)
this is my code for controlling show and hide of subview
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if(!show){
[self showSubview];
if (!myidleTimer)
[self resetIdleTimer];
}
}
-(void)resetIdleTimer
{
//convert the wait period into minutes rather than seconds
int timeout = kApplicationTimeoutInMinutes;// equal to 5 seconds
[myidleTimer invalidate];
myidleTimer = [NSTimer scheduledTimerWithTimeInterval:timeout target:self selector:#selector(idleTimerExceeded) userInfo:nil repeats:NO];
}
-(void)idleTimerExceeded
{
if (show){
[myidleTimer invalidate];
[self hideSubview];
show=false;
}
}
"show" is a bool to insure when to hide and when to show
her is the show / hide implementation
-(void)hideSubview{
[UIView animateWithDuration:0.5
animations:^{
subview.frame = CGRectMake(0, screenWidth, screenHeight, 60);//move it out of screen
} completion:^(BOOL finished) {
[subview removeFromSuperview];
subview.frame=CGRectMake(0,screenWidth, screenHeight, 0);
}];
show=false;
}
-(void) showSubview{
subview = [[UIView alloc] init ];
[self.view addSubview:subview];
subview.frame = CGRectMake(0, screenWidth, screenHeight, 60);
[UIView animateWithDuration:1.0
animations:^{
subview.frame = CGRectMake(0, screenWidth-60, screenHeight, 60);
}];
show=TRUE;
}
I hope that's clear enough to understand and be able to help me identify the problem
thanks in advance
The timer will not fire while the scroll view is being scrolled, if you create the timer the way you do. Instead, create it as below.
NSTimer *timer = [NSTimer timerWithTimeInterval:1 target:self selector:#selector(doStuff:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: adds the timer to the run loop using the defaultRunLoopMode instead of the NSRunLoopCommonModes, which is the one you want to have timer fire while the user scrolls.
I'm trying to set the image of an UIImageView with an alternative image.
I know I can do [imageView setImage: image]. However, is it possible to add any dissolve effect(animation) when I change image?
I have done this earlier and here is the piece of code that helps you out.This code works fine for the issue you described above.
-(void)changeImage
{
myImageView.animationImages=[NSArray arrayWithArray:self.yourImageArray];
myImageView.animationDuration=10.0;
myImageView.animationRepeatCount=0;
[myImageView startAnimating];
myImageView.transform = CGAffineTransformMakeRotation(M_PI/2);
[self.view addSubview:myImageView];
//The timers time interval is the imageViews animation duration devided by the number of images in the animationImages array. 20/5 = 4
NSTimer *timer = [NSTimer timerWithTimeInterval:2.0
target:self
selector:#selector(onTimer)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
[timer fire];
}
//This will Fade in and fade Out Images.
-(void)onTimer{
[UIView animateWithDuration:2.0 animations:^{
myImageView.alpha = 0.0;
}];
[UIView animateWithDuration:0.5 animations:^{
myImageView.alpha = 1.0;
}];
}
If you want cross Dissolve you can use this UIViewAnimationOptionTransitionCrossDissolve.
Hope this will help you out if not please feel free ask.
You can use UIView's transitionWithView method for achieving this.
A sample code snippet:
UIImage * newImage= [UIImage imageNamed:#"newImg.png"];
[UIView transitionWithView:self.view
duration:3.0f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
yourImageView.image = newImage;
} completion:nil];
You can achieve this by using CAAnimation transitions
the effect you are looking for is called kCATransitionFade
Take a look here and here for some handy tutorials as well as the class reference.
I have some views and I want to display them one by one . I can't find how to do this . Instead , if I use the following code , all the views appear at once .
NSTimer *timer1 = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(showStar2) userInfo:nil repeats:NO];
NSTimer *timer2 = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(showStar3) userInfo:nil repeats:NO];
NSTimer *timer3 = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(showStar4) userInfo:nil repeats:NO];
NSTimer *timer4 = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(showStar5) userInfo:nil repeats:NO];
[timer1 fire];
[timer2 fire];
[timer3 fire];
[timer4 fire];
-(void)showStar2
{
[UIView beginAnimations:#"anim1" context:NULL];
[UIView setAnimationDuration:0.5];
[stars[1] setAlpha:1];
[UIView commitAnimations];
}
All the showStar functions are identical except the lines
[UIView beginAnimations:#"anim1" context:NULL];
[stars[1] setAlpha:1];
which have different arguments . stars is an array of UIImageView's.
Any suggestion is welcome .
Actually you are firing all the timers exactly after 2 seconds. Change the timeInterval for different timers.
Instead you can use a single NSTimer that will fire repeatedly.
Declare NSUInteger count; in .h file.
Start a NSTimer as follows:
[NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(showStar:) userInfo:nil repeats:YES];
And your showStar method should be as follows:
-(void)showStar:(NSTimer*)timer
{
if( count > 0 )
{
[stars[count-1] setAlpha:0];
}
[UIView beginAnimations:#"anim1" context:NULL];
[UIView setAnimationDuration:0.5];
[stars[count] setAlpha:1];
[UIView commitAnimations];
count++;
if( count == 4 )
{
[timer invalidate];
count = 0;
}
}
The following code has been added.
if( count > 0 )
{
[stars[count-1] setAlpha:0];
}
All your timers are using the same time delay, so that's what the all appear at once. Also, don't call fire on the timers, they fire automatically. Calling fire probably makes them fire right away.
Incidentally, you don't need to use timers to trigger the animations, you can just add this to your animations:
[UIView setAnimationDelay:x];
And use a different x for each view.
I would do something like this
- (void)firstAnimation{
[UIView animateWithDuration:2.0f animations:^{
//first animation
} completion:^(BOOL finished){
[self secondAnimation];
}];
}
probably with recursion and a flag for current animation would be cleaner though
In my opinion your implementation is wrong.
Better to place a UImageView on your UIView.
Next create an NSArray of images and load then onto the imageView.
arrAnimations = [[NSArray alloc] initWithObjects:[UIImage imageNamed:#"image1.png],.....nil];
then call
imageView.animationImages= arrAnimations;
imageView.animationDuration=2;
[imageView startAnimating];