I want uicollectionviewcell move like things on assembly line.
Now I use
(void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated
in a method and in the last of method i make method call it self.
But UICollectionViewCell move and stop and go on.
UICollectionView inherits from UIScrollView, so you can use
// determine point, which you want to scroll
CGPoint scrollPoint = CGPointMake(0, self.tableView.contentSize.height - self.tableView.frame.size.height);
// scroll to it, with custom animation duration
[UIView animateWithDuration:5 animations:^{
[self.tableView setContentOffset:scrollPoint];
// Also you can use scrollToItemAtIndexPath here instead of setContentOffset
}];
Related
I'm using a custom UICollectionview Layout that displays the items in a circle. On a swipe up I reset the constraints on my collectionview and animate those constraint changes. I would like my items to animate with the constraint change so it's one smooth experience.
I get them to animate but only after the constraint change (I think), it looks messy and strange, check the screencast out here: http://cl.ly/ZmA0
This is the code in the swipe gesture method:
- (void)foo:(UISwipeGestureRecognizer *)gesture {
[self.view layoutIfNeeded];
[self.collectionView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(self.view.mas_width);
make.height.equalTo(self.collectionView.mas_width);
make.top.equalTo(self.view.mas_top).offset(50);
}];
[UIView animateWithDuration:1.0 animations:^{
[self.view layoutIfNeeded];
}];
[self.collectionView performBatchUpdates:^{
CircleLayout *layout = (CircleLayout *)self.collectionView.collectionViewLayout;
} completion:nil];
}
Any suggestions?
I'm not sure what MASConstraintMaker is (and the video is not working).
But within the performBatchUpdates block you are getting the collection view layout. What are you doing with it? it unused. Maybe that can point you to the right solution.
I have a UITableView displaying cells. I am using Auto Layout. At some point, I add cells to a section of my tableView and I need to animate a subview of each cells as soon as the cells are visible.
I wrote the following method to animate the content of my cell:
- (void)animateWithPercentage:(NSNumber *)percentage
{
self.progressViewWidthConstraint.constant = [percentage intValue];
[self.progressView setNeedsUpdateConstraints];
[UIView animateWithDuration:0.6f animations:^{
[self.progressView layoutIfNeeded];
}];
}
The method works as expected but I don't know when to call it.
If I call it when - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath is called, I end up animating the whole layout of my cell because the cell did not layout itself before.
I also tried calling it in layoutSubviews but the animation is skipped. I guess at this point it is too early to animate anything.
Any idea where my method should be called?
I've gotten this kind of animation to work by calling performSelector:withObject:afterDelay: in either awakeFromNib or didMoveToSuperview in the custom cell's class. It works even with a delay of 0, but it doesn't work if you just use performSelector. I've noticed that with this method, if some of the cells are off screen, they don't update until they are scrolled on, and the scrolling animation ends. You can get the animation to start as soon as the cell scrolls on screen, even while the scrolling animation is still in progress by using dispatch_async instead.
-(void)awakeFromNib {
dispatch_async(dispatch_get_main_queue(), ^{
[UIView animateWithDuration:2 animations:^{
self.rightCon.constant = 150;
[self.contentView layoutIfNeeded];
} completion:nil];
});
}
Try to put your method in -(void)didMoveToSuperview
I have a UICollectionView. I want a behaviour where when the user touches a cell, it scales down, as if it is getting pushed down slightly. I've accomplished this by using the UICollectionViewDelegate methods:
- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
[self scaleDownCell:cell];
}
- (void) collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
[self scaleUpCell:cell];
}
My problem is that sometimes my cell will start to scale down, and then suddenly go back to full size, without performing the scale up animation, creating jerky effect. I have checked with breakpoints that it scales up before my scale up method is called. I am trying to figure out why.
The scale functions are as follows:
+ (void)scaleDownCell:(UICollectionViewCell *)cell
{
CGAffineTransform transform = CGAffineTransformMakeScale(0.95, 0.95);
[UIView animateWithDuration:SCALE_DOWN_ANIMATION_DURATION
delay:0.0
usingSpringWithDamping:SCALE_DOWN_SPRING_DAMPING
initialSpringVelocity:SCALE_DOWN_SPRING_VELOCITY
options:0
animations:^{
cell.transform = transform;
}
completion:^(BOOL finished) {
}];
}
+ (void)scaleUpCell:(UBCollectionViewCell *)cell
{
CGAffineTransform transform = CGAffineTransformMakeScale(1.0, 1.0);
[UIView animateWithDuration:SCALE_UP_ANIMATION_DURATION
delay:0.3
usingSpringWithDamping:SCALE_UP_SPRING_DAMPING
initialSpringVelocity:SCALE_UP_SPRING_VELOCITY
options:0
animations:^{
cell.transform = transform;
}
completion:^(BOOL finished) {
}];
}
EDIT: I basically want to replace highlighting in my cells with this scaling behaviour, it serves the exact same purpose and I want it to happen in exactly the same situation that the cell would be highlighted, so it seemed like an appropriate place to apply my transformation.
Regardless, I had first tried overriding the UIResponder touch methods in the cell subclass, but was observing the same behaviour. The sudden scale up happens even if I delete the scale up method so that it is never called, so my scale down is not being cancelled by the scale up animation. I can see through log statements that my scale down is called once, and the animation completion block is getting called with finsished == YES. The cell is getting scaled back up BEFORE the completion block is called (I have set the animation duration to be extra long to help in debugging). This seems to happen when I touch on the cell and then quickly scroll, so I guess the scrolling has something to do with it.
The problem is that you are hijacking the notion of "highlighting" for something that it isn't. Highlighting is a complicated and confusing business. In the course of being tapped and selected, the cell highlights and unhighlights more than once. Thus it is the wrong thing to respond to.
If what you are trying to detect is a touch, then you should respond to touch. If a gesture recognizer won't do, then use a cell subclass of your own so that you can implement UITouch detection directly.
One more thing to keep in mind is that, the way you've written this, if the scale up happens while the scale down is in progress, it will just kill it dead.
EDIT - One final thought - in your edit, you make a comment about scrolling having something to do with this. That makes sense. Think how a collection view layout works - it is responsible for the attributes of each cell, including its transform (https://developer.apple.com/library/ios/documentation/uikit/reference/UICollectionViewLayoutAttributes_class/Reference/Reference.html). So naturally if you change the transform of the cell yourself, and you don't tell the layout, and the layout takes charge, it will cancel your transform.
So I have a UIViewController and I have a UIScrollView inside of it, which has some UI elements.
I want the user to be able to drag the UIScrollView up and down, but when it drags past a certain threshold, I want it to animate off the screen. There needs to be some springiness to it though. I tried using -(void)scrollViewDidScroll: but couldn't seem to get it right. Any thoughts?
In scroll view delegate method -(void)scrollViewDidScroll:(UIScrollView *)scrollView; observe scrollView.contentOffset.y and trigger animation when it reaches expected y position.
for example:
CGFloat yTranslation = -200.f; // Value you want to shift
[UIView animateWithDuration:0.35 animations:^{
scrollView.transform = CGAffineTransformMakeTranslation(0, yTranslation);
} completion:^(BOOL finished) {
// code after completion
}];
I am animating a UITableView. I want the table view to slide open like this:
http://www.youtube.com/watch?v=XIGJLbiRsXE
However, it opens like this:
http://www.youtube.com/watch?v=UJUX-ILCB_0
Notice how the table cells themselves are animating. How can I stop this from happening?
I am using autolayout. The code is thus:
[theView addSubview:theTable];
[theTable reloadData];
[theTable invalidateIntrinsicContentSize];
[UIView animateWithDuration:.33 animations:^{
[theView layoutIfNeeded];
}];
Other details, which may or may not matter:
The table view's parent is a scrollView
I have overridden the intrinsicContentSize of the table view to return the height of all the cells in the table view, so the table view will not scroll
I am changing the datasource of the table view before displaying it
I had a similar problem and was able to stop the animation on the UITableViewCell with the UIView performWithoutAnimation: method.
Use the tableView:willDisplayCell:forRowAtIndexPath: UITableViewDelegate method to get a reference to the cell before it is shown. Then, within the performWithoutAnimation: block, call layoutIfNeeded on the cell object to give it a chance to layout its subviews:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
[UIView performWithoutAnimation:^{
[cell layoutIfNeeded];
}];
}
It might be too late to answer this question but the problem in these kind of cases generally lies in the animation block capturing all the pending layouts scheduled in the next run loop.
The solution that i use is. I call layoutIfNeeded before the animation (before setting or invalidating any constraints) and then inside the animation block.
In your case it will something like this,
[theView addSubview:theTable];
[theTable reloadData];
[theView layoutIfNeeded];
[theTable invalidateIntrinsicContentSize];
[UIView animateWithDuration:.33 animations:^{
[theView layoutIfNeeded];
}];
Have you considered animating instead an opaque subview that is positioned above the table view?
[theView addSubview:theTable];
[theTable reloadData];
UIView *subview = [[UIView alloc] initWithFrame:theTable.frame];
subview.backgroundColor = [UIColor whiteColor];
[theView addSubview:subview];
[UIView animateWithDuration:0.33 animations:^{
subview.frame = CGRectMake(subview.frame.origin.x, subview.frame.size.height, subview.frame.size.width, 0.0);
}];
Try laying out the table first, before you call [theView layoutIfNeeded] inside the animation block. Ideally you could layout piecemeal and for that 0.33 seconds you may get a scroll bar on the table but the goal is to get the table cell layout changes outside of the animated block.