Animate UILabel in UITableViewCell - ios

I have a custom UITableViewCell with three labels - title, subtitle and right detail.
Now when a User taps on Cell this Cell becomes checked with the normal Checkmark, but I need to animate the right label to the left. I thought I could just do
CGRect rect = cell.playerRatingLabel.frame;
rect.origin.x -= 10;
[CLCPlayerViewCell animateWithDuration:1.0 animations:^{
cell.playerRatingLabel.frame = rect;
}];
but this appears to do nothing at all. I think it's about constraints but I don't know how to handle this, I'm using auto Layout.
Thanks for any help

Your playerRatingLabel should have a constraint to the right edge of the cell. Your custom cell need to make an IBOutlet to that constraint. Then on the cell tap, animate the constant parameter of that constraint (I've called the outlet rightCon in the example):
[UIView animateWithDuration:1.0 animations:^{
cell.rightCon.constant = 30; // change this value to meet your needs
[cell layoutIfNeeded];
}];
Here is the complete implementation that I use to do this. My custom cell had two labels, and I animate the right one when you click a cell and add a checkmark. I created a property selectedPaths (a mutable array) to keep track of the cells that are checked. If you click on a cell that's already checked, it un-checks it, and animates the label back to its original position.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RDCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.leftLabel.text = self.theData[indexPath.row];
cell.accessoryType = ([self.selectedPaths containsObject:indexPath])? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
cell.rightCon.constant = ([self.selectedPaths containsObject:indexPath])? 40 : 8;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
RDCell *cell = (RDCell *)[tableView cellForRowAtIndexPath:indexPath];
if (! [self.selectedPaths containsObject:indexPath]) {
[self.selectedPaths addObject:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[UIView animateWithDuration:.3 animations:^{
cell.rightCon.constant = 40;
[cell layoutIfNeeded];
}];
}else{
[self.selectedPaths removeObject:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
[UIView animateWithDuration:.3 animations:^{
cell.rightCon.constant = 8;
[cell layoutIfNeeded];
}];
}
}

You're trying to adjust the cell's frame which won't have any effect. Try adjusting the frame of the cell's contentView.

i guess following function will solve your problem
pass your label as cell.textLabel.layer and den pass the point like
CGPointMake(0, self.view.center.y)
-(void)moveLayer:(CALayer*)layer to:(CGPoint)point
{
// Prepare the animation from the current position to the new position
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"position"];
animation.fromValue = [layer valueForKey:#"position"];
animation.duration = 0.2;
animation.toValue = [NSValue valueWithCGPoint:point];
// Update the layer's position so that the layer doesn't snap back when the animation completes.
layer.position = point;
// Add the animation, overriding the implicit animation.
[layer addAnimation:animation forKey:#"position"];
}

Related

Animation on UITableViewCell

I am trying to put animation in a UITableViewCell. Animation is that onClick table view cell change the frame of tableCell into tableview frame.
I have the following code:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 10;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell*cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell*cell = [tableView cellForRowAtIndexPath:indexPath];
if(cell.frame.size.height == tableView.bounds.size.height){
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}else{
cell.frame = tableView.bounds;
[[cell superview] bringSubviewToFront:cell];
}
[UIView animateWithDuration:0.5 delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:0.2 options:UIViewAnimationOptionCurveEaseOut animations:^{
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
}];
}
It works fine but after change cell's frame I am able to tap another cells also which I don't want. How can I achieve this?
One of the possible solution would be to declare a variable that will hold an array of indexPath of expanded cell like this
// Will hold the indexPath of expanded cell
var expandedCell : [IndexPath] = []
Second thing would be adding and removing the the cell that are/aren't expanded and to do that you have to update your UITableView Delegate didSelectRowAt
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let index = expandedCell.firstIndex { (localIndexPath) -> Bool in
return indexPath == localIndexPath
}
if let index = index {
expandedCell.remove(at: index)
} else {
expandedCell.append(indexPath)
}
tableviewMessageList.reloadRows(at: [indexPath], with: .fade)
}
And in the end you have to add another UITableView Delegate heightForRowAt to return the height of the cell if the cell's indexPath is in array it will return the expanded size else return the normal size of your cell like this:-
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if expandedCell.contains(indexPath) {
return tableView.frame.height
}
return 200.0 //NormalHeight
}
Note: My answer is in Swift but the same principle will apply for Objective-C you just need to change the Syntax.
Overall, I think a better approach to this would be to use a separate view to display the cell details full screen, although you may have some restrictions that require you to do it this way. That being said, find my answer below.
This is what I gather your current problem is:
You'd like to show the cell expanded, and when in that expanded state touches are going through the cell view and hitting the table view behind it and re-triggering didSelectRowAtIndexPath: tableview delegate method (on other cells than the expanded one).
These are a couple of the possible solutions I see:
Add a tap gesture recognizer to the cell when it's expanded so it will absorb the touch, then remove the gesture recognizer once it's consumed.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(didTapOnExpandedCell:)];
[cell addGestureRecognizer:tap];
cell.frame = tableView.bounds;
[[cell superview] bringSubviewToFront:cell];
UIView *bgView = [[UIView alloc] init];
bgView.backgroundColor = [UIColor purpleColor];
cell.selectedBackgroundView = bgView;
[UIView animateWithDuration:0.5 delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:0.2 options:UIViewAnimationOptionCurveEaseOut animations:^{
[self.view layoutIfNeeded];
} completion:nil];
}
-(void)didTapOnExpandedCell:(UIGestureRecognizer *)recognizer {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:self.tableView.indexPathForSelectedRow];
// do whatever you were planning on doing when tapping on the
// expanded cell
[self.tableView reloadRowsAtIndexPaths:#[self.tableView.indexPathForSelectedRow] withRowAnimation:UITableViewRowAnimationNone];
[cell removeGestureRecognizer:recognizer];
}
Subclass UITableViewCell and override touchesBegan:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
R4NTableViewCell *cell = (R4NTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
cell.frame = tableView.bounds;
[[cell superview] bringSubviewToFront:cell];
UIView *bgView = [[UIView alloc] init];
bgView.backgroundColor = [UIColor purpleColor];
cell.selectedBackgroundView = bgView;
[UIView animateWithDuration:0.5 delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:0.2 options:UIViewAnimationOptionCurveEaseOut animations:^{
[self.view layoutIfNeeded];
} completion:nil];
}
// in R4NTableViewCell.m implementation override touchesBegan
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
// if we're not selected, don't intercept the touch so the tableview can handle it
// calling back to super will give the default tableview behavior and get our delegate callback
if (self.selected == NO) {
self.frameBeforeExpansion = self.frame;
[super touchesBegan:touches withEvent:event];
} else { // we're in the expanded state so intercept the touch
NSSet <UITouch *> *singleTouches = [[event allTouches] objectsPassingTest:^BOOL(UITouch * _Nonnull obj, BOOL * _Nonnull stop) {
return obj.tapCount == 1;
}];
if (singleTouches.count > 0) {
// the user single tapped our view
[UIView animateWithDuration:1.0 delay:0.0 usingSpringWithDamping:0.7 initialSpringVelocity:0.2 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.frame = self.frameBeforeExpansion;
[self.superview layoutIfNeeded];
} completion:^(BOOL finished) {
[self setSelected:NO];
self.backgroundView.backgroundColor = [UIColor greenColor];
}];
}
}
}
One additional thing I didn't really understand from your explanation (as the comments mentioned) is what you expect to happen when the user taps the expanded tableview cell.

Pop collectionview cell out and zoom - uicollectionviewcell animation

Im trying to create a cool animation with my collection view selection. Basically I have a collection view of photo cells displayed. What I want to happen is have the cell pop out of its location, scale and move to the center of the screen where the user will be prompted to confirm the selection.
Here is my code so far, but currently the animation takes the cells original frame location, so if I scroll it doesnt take into account that the frame position is no longer the same.
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
PhotoCell *cell = (PhotoCell *)[collectionView cellForItemAtIndexPath:indexPath];
collectionView.allowsSelection = NO;
[self createAnimationWithCell:cell];
}
- (void)createAnimationWithCell:(PhotoCell *)cell {
UIImageView *selectedImage = [[UIImageView alloc] initWithFrame:cell.bounds];
selectedImage.center = cell.center;
selectedImage.image = cell.imageView.image;
[self.view addSubview:selectedImage];
[UIView animateWithDuration:2.5 animations:^{
selectedImage.center = self.view.center;
} completion:^(BOOL finished) {
[selectedImage removeFromSuperview];
self.collectionView.allowsSelection = YES;
}];
}
I solved it myself:
For those who are experiencing the same problem, we have to take into account how much the collection view has scrolled (offset) and use that information. I created a variable called collectionViewOffset and gave it an initial value of 0.0
then used:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
// getting the scroll offset
collectionViewOffset = scrollView.contentOffset.y;
NSLog(#"offset: %f", collectionViewOffset);
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
PhotoCell *cell = (PhotoCell *)[collectionView cellForItemAtIndexPath:indexPath];
//collectionView.allowsSelection = NO;
//collectionView.scrollEnabled = NO;
[cell.superview bringSubviewToFront:cell];
[UIView animateWithDuration:2.0 delay:0 usingSpringWithDamping:0.7 initialSpringVelocity:.2 options:UIViewAnimationOptionCurveLinear animations:^{
cell.center = CGPointMake(self.view.vWidth/2, self.bannerView.vBottomEdge + collectionViewOffset + 40);
} completion:^(BOOL finished) {
}];
}

UITableviewcells unwanted animation from the side

I am trying to animate a tableview on a view that uses autolayout.
I am able to animate the tableview fine but for some reason there is a unwanted sideways animation when doing so.
The first animation closes the top tableview works fine. However the second animation that extends the bottom tableview is the one that has the sideways movement. Here is my code:
[self.dataSelectionTable layoutIfNeeded];
[self.comparatorSelectionTable layoutIfNeeded];
[UIView animateWithDuration:0.5 animations:^{
self.dataSelectionTableHeight.constant = 44;
[self.view layoutIfNeeded]; and then captures all of the frame changes
} completion:^(BOOL finished){
[UIView animateWithDuration:0.5 animations:^{
self.comparatorSelectionTableHeight.constant = 200;
[self.view layoutIfNeeded];
}];
}];
I have tried changing the animation type but that does not seem to work.
Here is a link to a gif that shows the unwanted sideways animation: http://makeagif.com/YubmP2
Edit
Here is the code for populating the tableviews:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
cell.textLabel.numberOfLines = 0;
cell.textLabel.font = [UIFont fontWithName:#"Helvetica" size:13.0];
}
if (tableView == self.dataSelectionTable) {
cell.textLabel.text = self.dataSelectionTitles[indexPath.row];
}
else {
cell.textLabel.text = [self.comparatorList[indexPath.row] name];
}
return cell;
}
I tried to duplicate your problem, but got slightly different results. Instead of a sideways movement, I got a downward movement of the label within the cell (but only the first time I did the animation).
I noticed that if I set the table view's height constraint's constant value to 0 in viewDidLoad, cellForRowAtIndexPath was not called until I did the expansion, so I'm guessing that some of the laying out of views of the table view wasn't happening until then.
I fixed the problem by setting the alpha value of the table view to 0 in IB, and set its height to 400 (the value I wanted after expansion). Then in viewDidAppear, I did this,
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.heightCon.constant = 0;
self.tableView.alpha = 1;
}
This caused the table's data source methods to run right away, but with the table view not visible. Now when I animated the expansion, I didn't get any movement of the label within the cell.

Animate tableView Cell on didSelectRowAtIndexPath?

I would like to resize my tableView cell when the user selects a row, the cell becomes smaller then larger again. This is what I have tried so far:
#pragma mark UITableView Delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
// My animation
cell.contentView.transform = CGAffineTransformMakeScale(0.95,0.95);
cell.contentView.alpha = 1.f;
[UIView beginAnimations:#"button" context:nil];
[UIView setAnimationDuration:0.2];
cell.contentView.transform = CGAffineTransformMakeScale(1,1);
cell.contentView.alpha = 1.0f;
[UIView commitAnimations];
}
This is my tableView data source:
#pragma mark UITableView Datasource
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Set up cell
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.backgroundColor = [UIColor clearColor];
cell.textLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:21];
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.highlightedTextColor = [UIColor lightGrayColor];
cell.selectedBackgroundView = [[UIView alloc] init];
}
// Images in my cell
NSArray *images = #[#"Songs", #"Albums", #"Artists", #"Playlists"];
UIImageView *cellImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:images[indexPath.row]]];
cellImage.frame = CGRectMake(0, 0, 90, 90);
[cell addSubview:cellImage];
return cell;
}
But this does not work. The image in the cell simply stays the same size. Any ideas? Thanks.
I seriously advise going with a UICollectionView for something like this. With it, you only have to call performBatchUpdates and you can put any frame setting inside of it's block. It's practically magic!
I don't know if you can or should do what you ask about, but if you can it would probably be with a custom UITableViewCell. But, you might be able to fake it with a custom cell, maybe with a UIView that holds all the cell's contents. The UIView would animate inside the cell, and if you are not showing separators on the table it could look like the cell itself is animating. So basically you're hiding the actual cell, and using a UIView in the cell to simulate animating the cell. Maybe like this:
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
self.customCell.frame = CGRectMake(110, 20, 100, 20);
} completion:^(BOOL finished) {
[UIView animateWithDuration:SLIDE_TIME delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
self.customCell.frame = CGRectMake(0, 0, 320, 60);
} completion:^(BOOL finished) {
}];
}];

How to animate the table view cell textLabel

i have this code, I want to animate this. Some one helps me please.? When i run the code it shows it normally !! i just want to show it as an animated textLabel. which slowly comes in.
somebody please help me out, there is animation property for cell.ImageView is available. but not for textLabel.
cell.textLabel.frame = CGRectMake(55, 143, 88, 24);
i tried this , but its not working,
[UIView animateWithDuration:0.036 animations:^{
cell.textLabel.frame = CGRectMake(55, 143, 88, 24);
} completion:nil];
[UIView commitAnimations];
May be you are looking for,
[UIView animateWithDuration:0.25 animations:^{
cell.textLabel.frame = CGRectMake(55, 143, 88, 24);
}];
[UIView animateWithDuration:0.25 animations:^{
cell.textLabel.frame = CGRectMake(55, 143, 88, 24);
//You should force them to layout subviews again
[cell layoutSubviews];
}];
The alpha property of a UILabel is animatable. You can set the alpha to be 0 (totally transparent) when you create it, and then animate the alpha to 1.0 (totally opaque). This can be achieved like this:
First set the alpha of your cells textLabel to 0.0 in tableView:cellForRowAtIndexPath:, as well as whatever other code you want here as well.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = [NSString stringWithFormat:#"Cell %lu", indexPath.row];
cell.textLabel.alpha = 0.0;
return cell;
}
Then you can animate it with a class method on UIView called animateWithDuration. I put it didSelectRowAtIndexPath just for this example, but you should be able to do it wherever you need to.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[UIView animateWithDuration:1.0 animations:^{
cell.textLabel.alpha = 1.0;
}];
}

Resources