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! :)
Related
I am using a custom uitableviewcell, which is written in Objective C (everything else I have is written in Swift) for the purpose of having easy customer slide buttons. I have a tableview which uses these cells, and I want it to update even when one of the slide buttons (think slide to delete button) is showing. This is my code here:
dispatch_async(dispatch_get_global_queue(priority, 0)) {
// do some task
dispatch_sync(dispatch_get_main_queue()) {
self.tasksTableView.reloadData()
self.tasksTableView.cellForRowAtIndexPath(NSIndexPath(forRow: searchForTaskByName(taskSlices[selectedSlice].name), inSection: 0))!.contentView.addSubview(self.view1)
(self.tasksTableView.cellForRowAtIndexPath(NSIndexPath(forRow: searchForTaskByName(taskSlices[selectedSlice].name), inSection: 0)) as! SESlideTableViewCell).setSlideState(SESlideTableViewCellSlideState.Left, animated: true)
})
})
Now, the subview I am adding is a rectangle that originally covers the cell, but over time shrinks (kind of like a reverse loading bar). The third line is part of the custom code:
[UIView animateWithDuration: 0.0 delay: 0.0 options:UIViewAnimationOptionCurveLinear animations:^{
//code with animation
CGRect frame = snapshotView.frame;
frame.origin.x = targetPositionX;
snapshotView.frame = frame;
m_slideState = slideState;
//[m_leftButtonGroupView layoutIfNeeded];
//[m_rightButtonGroupView layoutIfNeeded];
} completion:^(BOOL finished){
if (finished) {
if (animationId != m_slideAnimationId) {
return;
}
m_slideState = slideState;
if (slideState == SESlideTableViewCellSlideStateCenter) {
m_preparedSlideStates = SESlideStateOptionNone;
isMoved1 = NO;
[self cleanUpSlideView];
}
}
}];
This moves the cell to keep the button in view. Now, the problem is, the tableview has to reload to show the changes (update subviews??) and this causes the cell to shift back to starting position, then the cell is shifted back to button displaying position. This causes random flashes of the cell. I have already tried reloadCellsAtIndexPaths, same deal. I have tried to hide and unhide around the animations; using different threads; dispatch_sync and dispatch_async; removing the table from superview, updating, and putting back; UIView.animationsSetEnable(false) blocks; deleteCellsAtIndexPaths and insertCellsAtIndexPaths, NOTHING will work. This is reproducible on my iPhone 5 and simulator.
What I really need is to figure out what reloadData does so I can call only the bit I need, and hopefully not animate anything. All my animations used have time 0.0 and no delay. I am running a small counting up algorithm in the background, which is variable++ once every .01 seconds, if this matters. Thank you for any help you can give me, I have been working on this for two days now (I am fairly new to iOS development and I wanted to do my research before asking questions).
dispatch_sync(dispatch_get_main_queue()) { } is the source of your problem change it to dispatch_async(dispatch_get_main_queue()) { // reload table view } and your good to go
Well, I figured out a REALLY hacky fix. I created a duplicate UITableView, which I placed under the main one. I set the main one to get removed from superview and then put back with the reloadData call and other updates between these two calls. This would reveal the second tableview for a split second, and then 0.5 seconds after the first update I would update the second tableview to keep it current. This actually works. I can't believe it works and I am flabbergasted that it is necessary. I am still definitely looking for a legitimate solution and so I will not be accepting my answer for a while, in case someone can help me out.
[self.tableView registerNib:[UINib nibWithNibName:#"CellXibName" bundle:nil] forCellReuseIdentifier:CELL_IDENTIFIER];
I have the flash problem.I finally find that the cell are not reuse when table reload.
I have some query block when I set each cell, The cell always recreate make it flash.
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.
I am changing the size of a view using animation and I need to change the image of imageview inside that view in every step of the animation. The image depends on the view size that's why I want to do so. I have tried to do that in the animations: block, but it seems to be called only once and not for each iteration as I expected.
How can I perform some operations during each iteration of UIView animateWithDuration:animations:. Or maybe there is another solution for my problem?
P.S. I have tried to use completion: block, but it doesn't solve my problem correctly as I want to achieve smooth change of images.
if i give you simple answer, the answer is no...
but i have an alternative for this make a function which you can call recursively like..
-(void)animationRecursive
{
[UIView animateWithDuration:0.001 animations:^{
// Here set frame slide different from last frame use incremental variables
// for x,y,width,height
//yourImageView.frame = set frame
//yourImageView.image = set image
} completion:^(BOOL finished) {
if(![yourImage.frame isEqualToString NSStringFromCGRect(yourFinalCGRectAfterAnimation)]
{
[self animationRecursive];
}
}];
}
hope this will help you.............
In the app I'm working on the user taps on a tableview to zoom it up to full view from a "thumbnail" or a miniature view. Everything is working great except for a somewhat annoying animation glitch or whatever. The thing is I'm using the code below:
if ([subview respondsToSelector:#selector (name)] && [subview.name isEqualToString:self.labelListName.text])
{
[self.tabBarController.view addSubview:subview];
CGRect frame = CGRectMake(35, 78, self.scrollView.frame.size.width, self.scrollView.frame.size.height);
subview.frame = frame;
CGAffineTransform scale = CGAffineTransformMakeScale(1.39, 1.39);
CGAffineTransform move = CGAffineTransformMakeTranslation(0,44);
CGAffineTransform transform = CGAffineTransformConcat(scale, move);
[UIView animateWithDuration:0.15
delay:0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
subview.transform = transform;
}
completion:^(BOOL finished){ [self goToList],subview.hidden = YES; }];
}
- (void)goToList
{
self.gotoWishList = [[WishList alloc] initWithNibName:#"WishList" bundle:nil];
self.gotoWishList.hidesBottomBarWhenPushed=YES;
self.gotoWishList.name = self.labelListName.text;
[self.navigationController pushViewController:self.gotoWishList animated:NO];
self.gotoWishList.scrollLists = self;
[WishList release];
}
And when doing the animation the transfer between the zoom view and the actual view the user is going to interact with is not completely perfect. The text inside the cell jumps a little when switching between the views. The problem lies in the translation matrix. If I skip that I can get the animation to work perfectly but then of course I need to move the miniature view down in the GUI which is not an option. If I instead do the animations in another order (move, scale) then it works better. I still get a jump at the end but it looks better, as everything jumps...and not just the text.
So...basically my question is how can I make this animation fluent. I read that the CGAffineTransformConcat still does each animation separately, and I really need both animations (scaling and moving the list) to be ONE fluent animation.
Thanks for any tips!
I think you will have to nest views/graphic-context to get what you want. The animation system doesn't support simultaneous animations because the mathematics of doing so requires an exponential amount of computational power. You might be able to trick it by sliding one view while enlarging the other.
I'm not sure about that as I have never had need to try it.
You might also be getting a jerk or skip from the tableview itself. The bounce at the top and end of scrolls can produce effects if you radically resize the table on the fly. I would turn all that off and see if you still have the problem. You might also want to test on the view independent of the tableview to make sure the problem is with the animations and not the tableview moving itself.
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.