I have an uiimageview in my uittableviewcell in my uitableview. What I want to accomplish is rotate all the uiimageviews of each cell using a timer. I know how the nstimer and rotating concept goes about, but I do not know how to rotate ALL the images in EACH cell in the UITableView. Is there a way to have access to these properties of all the uitableviewcells?
Hopefully this isn't confusing, and if it is here is a simple example:
Take for example I have 5 cells in my uitableview. each of the 5 cells has an uiimageview since my cells are customely made and has its own class. How would I rotate all 5 uiimageviews?
Thanks for all your help,
kevin
In your timer callback function you want to do something like this.
NSArray* cellArray = [yourTableView visibleCells];
for (UITableViewCell* cell in cellArray)
{
// do your cell by cell rotation here
}
To do this when you create your cell for an infinite animation you can use the following code. Keep in mind that if you are caching cells then you only need to do this on cell creation, not on the cached cells.
[UIView beginAnimations:#"looping animation" context:nil];
[UIView setAnimationRepeatCount:0]; // 0 is infinite
[UIView setAnimationDuration:3];
// other animation options here if you'd like, and the duration can be anything, not just 3.
[UIView animateWithDuration:3 delay:0 options:UIViewAnimationOptionRepeat animations: ^{
// do your rotation stuff on your image, in this block, for the cell you will be returning.
} completion:nil];
[UIView commitAnimations];
Using a timer for animation isn't the best approach.
If you insist, I suggest you simply enumerate the visible cells (using the visibleCells tableview method) in the table view with each tick, and perform you rotation action on each cell.
How about some methods of UIView which controls the animation flow? You can repeat the animation of rotating.
Related
I've got a UICollection view that has a bunch of cells, when the user presses down on one id like to have it animate a bit. The problem i'm running into is the animation competes with no duration. Its like it just ignores the animate all together.
Heres the code from the collection view. Cells is just the collection of cells that i'm using, I tried doing cellForItemAtIndexPath: but I could'nt get the method inside the cell to call. So i created an array and put each cell inside there when they are created.
-(void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"Highlighted");
[[cells objectAtIndex:indexPath.row] shrinkCell:YES];
}
And here is the code from inside the cell.m
-(void)shrinkCell:(BOOL)shrink{
NSLog(#"Shrink");
if (shrink) {
[UIView animateWithDuration:1.0
delay:0.5
options: UIViewAnimationOptionCurveEaseIn
animations:^{
self.bg.frame = CGRectOffset(self.bg.frame, 100, 100);
}
completion:nil];
}
}
So just to reiterate. The cell does move, it just doesn't animate. Any thoughts?
Thanks!
I am new in iOS developement.When I press the stopwatch start button I want to display the timer like counter token effect.I have attached image for your reference.I have done to display secs and minutes but I dont know, How animate autoscroll effect? How can I do this?
When the counter is moving it shouldn't jump from one number to another number, instead it should move from one number to next number smoothly, just like the petrol pump meter. Thanks
I have done something like this before - this code is not necessarily clean, but it does the job.
You want to create twoUILabels in your .h file:
IBOutlet UILabel *figureLabel1;
IBOutlet UILabel *figureLabel2;
Then you want to create a BOOL so that we can tell which UILabel is visible to the user.
BOOL firstLabel;
So lets imagine that the initial label (showing the number 1) is figureLabel1 and the future UILabel to be displayed (showing the number 2) is figureLabel2. However when the counter adds one, then the figureLabel2 moves up and takes the figureLabel1's place. Then, while the figureLabel1 is hidden, it takes the place of figureLabel2 when figureLabel1 was visible.
See here:
// Check what label is showing
if (firstLabel == YES) {
// Following code the hide and move the figureLabel1
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelegate: self]; //or some other object that has necessary method
[UIView setAnimationDidStopSelector:#selector(animationDidStop:finished:context:)];
// Slowing fade out the figureLabel1
[figureLabel1 setAlpha:0];
// Move the figureLabel1 up and out of the way
[figureLabel1 setFrame:CGRectMake(20, 108, 287, 55)];
[UIView commitAnimations];
// Following code the show and move the figureLabel2
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
// Slowing fade in the figureLabel2
[figureLabel2 setAlpha:1];
// Move the figureLabel2 up and into position
[figureLabel2 setFrame:CGRectMake(20, 141, 287, 55)];
[UIView commitAnimations];
// Update BOOL for next label
firstLabel = NO;
} else {
// Exactly the same but opposite
}
As I said, this is not pretty but it shows the basic concept. All the best!
You need to manually scroll tableView instead of scrollToRowAtIndexPath because this animation uses its own timer interval and its very difficult or we can say impossible to change its time interval.
So, I am Implementing an API for such kind of problems and made a demo app for you with smooth scrolling as you want.
You need to use an outer timer that fires every 1 second and an internal timer that will fire every 0.03 sec as my tableRow Height is 30 I calculated internal timer interval as :---
Move 30 pixels for 1 sec , then
Move 1 pixel for 0.33 sec inside internal timer.
The Internal timer will invalidate and fire every 1 second as initialized within outer timer.
And internal timer will perform the movement of cell.
dial4 is a tableView
Have a look at my code.
#define rowHeight 30
-(void)startCounter
{
outertimer=[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(snapCell) userInfo:nil repeats:YES];
}
-(void)stopCounter
{
[outertimer invalidate];
}
-(void)snapCell
{
NSLog(#"Initialize Internal timer %i",secLsb);
secLsb++;
if (secLsb==10) {
[dial4 setContentOffset:CGPointMake(0, 0) animated:NO];
secLsb=0;
NSLog(#"dial content offset y is %f",dial4.contentOffset.y);
}
[internaltimer invalidate];
internaltimer=[NSTimer scheduledTimerWithTimeInterval:0.03
target:self
selector:#selector(automaticScroll)
userInfo:nil
repeats:YES];
}
-(void)automaticScroll
{
NSLog(#"val is & y ======== %f",dial4.contentOffset.y);
[dial4 setContentOffset:CGPointMake(dial4.contentOffset.x,dial4.contentOffset.y+1) animated:NO];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return rowHeight;
}
Have a look at Time Counter
From image it can be assume that you are trying to get an effect like count-down timer. Have a look at countdown timer here. It may helps you somehow.
Enjoy Programming !!
Refer both links for your output. It helps you
UIPickerView that looks like UIDatePicker but with seconds
and
How can I make my UIPickerView show labels after the selected value?
Thanks.
Several good ideas here so far, but I'll add another.
First, be sure to set the container view (your blue rectangle) to clip children, using the Clip Subviews checkbox in Interface Builder.
Second, add a set of child views with images of each numeral for each digit to be presented (4 * 10 = 40 child views in your case). Use tags in IB so you can easily access each one. Set the initial bounds to just below your bottom margin.
Call UIView animateWithDuration. In the animations block, set the new digit view's frame to appear in the clipped parent view's bounds, and set the old digit view's frame to just above the container's bounds. Since both view's frame changes are animated in the same block, this will create the effect of the new digit sliding up into place as the old digit slides out the top.
In the completion block, set the old digit's frame back to the original position below the container view.
With this approach, you can play with the duration and the timing curves, so that you cam emulate the pause that occurs with each digit fully displayed between transitions.
A similar approach can also be used with CALayer, or with sprites, but UIViews are lightweight, perform well, and easiest to assemble in Interface Builder.
How can I make imageView property of my cells fly in one by one?
I can now make them fly in, but only all at once.
And is it good for performance to do something like this?
Thank you!
Use the indexPath.row to calculate a delay.
float animationDelay = 0.2f;
[UIView animateWithDuration:0.3f
delay:animationDelay * indexPath.row
options:0
animations:^{
cell.imageView.transform = CGAffineTransformMakeScale(1.0f, 1.0f);
} completion:^{}];
This will delay every row by 0.2 seconds relative to the row above it. Of course this will only work when you initially load the table, but I guess this is what you're trying to animate? When you start scrolling and new cells are loaded, you probably should set the delay to zero. Otherwise the images will take a while to show up.
To achieve this I recommend introducing a BOOL ivar called loadingTheFirstTime that is set to YES initially (in the init or awakeFromNib methods). Then you can set that to NO when the table is shown the first time. When creating the cells you should then check for this variable first to see if you have to add a delay.
I supposed here that you are in cellForRowAtIndexPath:. Change your animation with that :
[UIView animateWithDuration: 3.0
delay: indexPath.row
options: UIViewAnimationCurveLinear
animations: ^{
cell.imageView.transform = CGAffineTransformMakeScale(1.0f, 1.0f);
}
completion:^(BOOL finished) {
}];
The animations will load with 1 sec of interval. If you're not in this function, set a tag to your cells when you create them, and put that tag in the delay.
Maybe set up a method where there is a for loop that runs through every cell and runs the animation for each time through the loop? Regarding performance, I have no idea. I would't imagine it would be GOOD for performance, especially if there are a lot of cells, but you can always try it and find out! :)
I have a subclass of UIScrollView that I'm using for images slideshow, with infinite scrolling and circular slideshow.
I used to animate the transition in this way: (Because I wanted the transition to be slower)
[UIView animateWithDuration:1.0
delay:0 options:(UIViewAnimationCurveEaseOut)
animations:^{
self.scrollView.contentOffset = newOffset;}
completion:NULL];
And it worked just fine.
Then I watched the lecture "Advanced Scrolling Techniques" from WWDC 2011, and they recommend to implement infinite scrolling by overriding layoutSubviews.
So I changed my implementation and override layoutSubviews
Once I did that the transition animation stopped working.
If I comment out my custom layoutSubviews - It's working again!
Why??
What can I do to make my own scrolling animation while overriding layoutSubviews?
Thanks!
OK, I think I found the problem, and a possible fix.
The key to understand the problem is understanding that when you call
[UIView animateWithDuration...]
All the properties that you change inside the animation block, are changed immediately. They do not change as the animation actually executing (visually).
So in my case, I'm animating the contentOffset to my target value.
This operation invokes layoutSubviews immediately.
In my implementation of layoutSubviews I'm checking to see if enough movement has been accumulated. If so - I'm rearranging my ImageViews, and set the contentOffset to its initial value. Once I do that there is nothing to animate anymore, because nothing has changed!
Animate contentOffset to X:
calls setContentOffset to X:
invokes layoutSubview
Sets the contentOffset back to Y! (after rearranging the views)
Nothing to animate at this point...
Possible Fix
I'm not sure if it is the right way to do it, but its working working.
So what we need to do is to ensure that no changes will be made in layoutSubviews while we are in the middle of animation block.
So I created a BOOL instance variable named isAnimating, and set it appropriately in the animation block:
self.isAnimating = YES;
[UIView animateWithDuration:self.transitionDuration
delay:0
options:(UIViewAnimationOptionCurveEaseOut)
animations:^{
self.contentOffset = newOffset;
}
completion:^(BOOL finished) {
self.isAnimating = NO;
[self setNeedsLayout];
}];
Now in layoutSubviews we need to take isAnimating into account:
-(void) layoutSubviews
{
[super layoutSubviews];
if (self.isAnimating == NO)
{
[self rearrangeIfNecessary];
}
}
And it's working again!
I want an UITableViewCell (-background) to shortly light up in red and return to the old appearance again. This is done during the life of an NSTimer which is giving the constant impulse to invoke the animation.
Right now I am using UIView's animateWithDuration:delay:options:animations:completion: method to first change the cells background color to red and then in the completion part to turn it gray again (the cell's background is gray). But this solution doesn't work smoothly for some reason.
QUESTION: Thinking of core animation, how would I best do this kind of animation for (a) an UITableVeiwCell and (b) an UIButton ?
Thanks for any help!
animateWithDuration is a UIView wrapper for core animation, but you could try doing it a little lower level and see if there is a change.
To do an explicit CA transaction on a CALayer do something like:
[CATransaction begin];
[CATransaction setAnimationDuration:0.5];
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
[CATransaction setCompletionBlock:^{ //Your completion block }];
view.layer.backgroundColor = [UIColor whiteColor].CGColor;
[CATransaction commit];
Where view is the control in question. For a UIButton that would just be the button itself, for UITableViewCell it would depend on whether the table was grouped or not or if you are using a custom UITableViewCell. A grouped table cell adds a backgroundview property.
I was using an NSTimer to trigger the animation over and over again. Somehow it was giving the above described side effects. Now I am using the block animation available since iOS4 which is working much smoother. You have to combine the (UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse) options to repeat the Animation:
[UIView animateWithDuration:kDurationOfCellAnimation delay:0 options:UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse
animations:^{
//this will be animated in and out
cell.backgroundColor = CELL_RECORDING_COLOR;
}
completion:^(BOOL finished){
cell.backgroundColor = TABLEVIEW_BACKGROUND_COLOR;
}];
The only side effect I experienced was that the animation stops when the cell goes off screen, which wasn't the case with the NSTimer.