Custom UITableView Cell Animation - ios

I am trying to make custom cell highlighted animation...but it does not work. Any thoughts how can I animate .alpa change?
ViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellID = #"myID";
TableViewCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
cell.selectedImg.frame = cell.contentView.frame;
cell.selectedImg.image = [ViewController imageFromColor:[UIColor colorWithRed:0.55 green:0.95 blue:0.68 alpha:0.0]];
cell.selectedImg.hidden = NO;
return cell;
}
TableViewCustomCell.m
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{
if (highlighted) {
[UIView animateWithDuration:0.2 animations:^(void) {
self.selectedImg.alpha = 0.5;}];
}
else {
[UIView animateWithDuration:0.2 animations:^(void) {
self.selectedImg.alpha = 0.0;}];
}
}
P.S. I will have a lot of UITableViews and they all will have the same cell style, so Should I place cell.selectedImg code somewhere in TableViewCustomCell.m? If yes, where is the right place?

Try to replace the code in
(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
in TableViewCell.m with the following code:
[UIView animateWithDuration:0.2
delay:0
options:UIViewAnimationOptionCurveLinear
animations:^{
if (highlighted) {
self.selectedImg.alpha = 0.5;
}
else {
self.selectedImg.alpha = 0;
}
}
completion:^(BOOL finished){
if (highlighted) {
self.selectedImg.alpha = 0;
}
else {
self.selectedImg.alpha = 0.5;
}
}];

Related

How to Reorder tableview cell with a custom button, but not with move edit icon in ios

I'm developing an application with a new requirement of reordering tableview cell. In the tableview cell I should display only one label. When I select the entire cell it must get selected and able to drag the cell to the new position.
I have a UITableView, I am using the following code to manage reordering:
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
return YES;
}
-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath{
return YES;
}
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewCellEditingStyleNone;
}
- (BOOL)tableView:(UITableView *)tableview shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
NSString *stringToMove = resourceDetailsArray[sourceIndexPath.row];
[resourceDetailsArray removeObjectAtIndex:sourceIndexPath.row];
[resourceDetailsArray insertObject:stringToMove atIndex:destinationIndexPath.row];
[orderListTableView reloadData];
}
Can anyone please assist me a better solution?
Thanks in advance.
There's a library out there called ObjcReorder translate from SwiftReorder。
These lines of code had helped me alot. It works like a charm for my requirement i.e reorder the cell when long press the tableview cell.
- (IBAction)longPressGestureRecognized:(id)sender {
UILongPressGestureRecognizer *longPress = (UILongPressGestureRecognizer *)sender;
UIGestureRecognizerState state = longPress.state;
CGPoint location = [longPress locationInView:orderListTableView];
NSIndexPath *indexPath = [orderListTableView indexPathForRowAtPoint:location];
static UIView *snapshot = nil; ///< A snapshot of the row user is moving.
static NSIndexPath *sourceIndexPath = nil; ///< Initial index path, where gesture begins.
switch (state) {
case UIGestureRecognizerStateBegan: {
if (indexPath) {
sourceIndexPath = indexPath;
UITableViewCell *cell = [orderListTableView cellForRowAtIndexPath:indexPath];
// Take a snapshot of the selected row using helper method.
snapshot = [self customSnapshoFromView:cell];
// Add the snapshot as subview, centered at cell's center...
__block CGPoint center = cell.center;
snapshot.center = center;
snapshot.alpha = 0.0;
[orderListTableView addSubview:snapshot];
[UIView animateWithDuration:0.25 animations:^{
// Offset for gesture location.
center.y = location.y;
snapshot.center = center;
snapshot.transform = CGAffineTransformMakeScale(1.05, 1.05);
snapshot.alpha = 0.98;
cell.alpha = 0.0;
cell.hidden = YES;
}];
}
break;
}
case UIGestureRecognizerStateChanged: {
CGPoint center = snapshot.center;
center.y = location.y;
snapshot.center = center;
// Is destination valid and is it different from source?
if (indexPath && ![indexPath isEqual:sourceIndexPath]) {
// ... update data source.
[resourceDetailsArray exchangeObjectAtIndex:indexPath.row withObjectAtIndex:sourceIndexPath.row];
// ... move the rows.
[orderListTableView moveRowAtIndexPath:sourceIndexPath toIndexPath:indexPath];
// ... and update source so it is in sync with UI changes.
sourceIndexPath = indexPath;
}
break;
}
default: {
// Clean up.
UITableViewCell *cell = [orderListTableView cellForRowAtIndexPath:sourceIndexPath];
cell.alpha = 0.0;
[UIView animateWithDuration:0.25 animations:^{
snapshot.center = cell.center;
snapshot.transform = CGAffineTransformIdentity;
snapshot.alpha = 0.0;
cell.alpha = 1.0;
} completion:^(BOOL finished) {
cell.hidden = NO;
sourceIndexPath = nil;
[snapshot removeFromSuperview];
snapshot = nil;
}];
break;
}
}
}
/** #brief Returns a customized snapshot of a given view. */
- (UIView *)customSnapshoFromView:(UIView *)inputView {
// Make an image from the input view.
UIGraphicsBeginImageContextWithOptions(inputView.bounds.size, NO, 0);
[inputView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Create an image view.
UIView *snapshot = [[UIImageView alloc] initWithImage:image];
snapshot.layer.masksToBounds = NO;
snapshot.layer.cornerRadius = 0.0;
snapshot.layer.shadowOffset = CGSizeMake(-5.0, 0.0);
snapshot.layer.shadowRadius = 5.0;
snapshot.layer.shadowOpacity = 0.4;
return snapshot;
}

Animation in willSelectRowAtIndexPath after validation

I have a table view delegate which checks if a specific cell may be selected. If not, the selection is aborted. In order to give the user a visual feedback I want to dye a label of this cell red and after a short amount of time dye it back to black:
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (true) { // Some simplification
MyTableViewCell cell = ... // The correct cell is loaded here
[UIView animateWithDuration:0.5 animations:^{
cellToSelect.labelAmount.textColor = [UIColor redColor];
} completion:^(BOOL finished) {
[UIView animateWithDuration:1.0 animations:^{
cellToSelect.labelAmount.textColor = [UIColor blackColor];
}];
}];
return nil;
}
return indexPath;
}
The animations are not performed. Instead, the cell is just (visually) deselected.
EDIT: I just tried the proposed solutions and neither seemed to work. So I digged a little bit further and found out that I can do animations but am not able to change the textColor of any label inside a cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyTableViewCell cell = ...
cell.labelAmount.textColor = [UIColor redColor];
// Now, although the property was set (as I can see in the debugger)
// the label is still drawn with standard black text.
}
Also, setting the color via a colorful attributed string does not work.
On the other hand, a change of highlightedTextColor is presented accordingly. So this works.
This property - textColor - is not animatable. Use transitionWithView:duration:options:animations:completion:
[UIView transitionWithView:label duration:0.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
label.textColor = [UIColor redColor];
} completion:^(BOOL finished) {
[UIView transitionWithView:label duration:1.0 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
label.textColor = [UIColor blackColor];
} completion:nil];
}];
Conforming to apple documentation you can't animate all you want:
From apple :
The following properties of the UIView class are animatable:
#property frame
#property bounds
#property center
#property transform
#property alpha
#property backgroundColor
#property contentStretch
Now this is a trick to animate what you want:
For instance, set alpha to 1.0
- will result in no visual change to the view but launch animation
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (true) { // Some simplification
MyTableViewCell cell = ... // The correct cell is loaded here
[UIView animateWithDuration:0.5 animations:^{
//here the trick set alpha to 1
self.view.alpha = 1;
cellToSelect.labelAmount.textColor = [UIColor redColor];
} completion:^(BOOL finished) {
[UIView animateWithDuration:1.0 animations:^{
cellToSelect.labelAmount.textColor = [UIColor blackColor];
}];
}];
return nil;
}
return indexPath;
}

UIView animation is cancelled at the end

I have a cell with a UIView with a white backgroundColor. I want to change background color with an animation. I use this method in -tableView:tableView didSelectRowAtIndexPath:indexPath :
[UIView animateWithDuration:1.0 delay:0 options:UIViewAnimationOptionOverrideInheritedCurve animations:^(void){
([cell viewWithTag:20]).backgroundColor = [UIColor orangeColor];
} completion:NULL];
The animation begin correctly, but at the end, the UIView becomes white again.
How can I fix that ?
edit: full code
#pragma mark - Table view
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 71;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _arFiles.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"RecentCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
((UILabel*)[cell viewWithTag:2]).text = [[_arFiles objectAtIndex:indexPath.row]objectForKey:KEY_FILE_NAME];
cell.separatorInset = UIEdgeInsetsMake(0, 0, 0, 10);
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return 0.01f;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewCell *cell = ((UITableViewCell*)[tableView cellForRowAtIndexPath:indexPath]);
[UIView animateWithDuration:1.0 delay:0 options:UIViewAnimationOptionOverrideInheritedCurve animations:^(void){
([cell viewWithTag:20]).backgroundColor = [UIColor orangeColor];
} completion:NULL];
}
subclassing the cell may work as u expected, hear is the code try it out in custom cell
do somthing like below
//in CustomCell.m
#import "CustomCell.h"
#implementation CustomCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
UIView *view = [[UIView alloc]initWithFrame:CGRectZero];//your view
view.tag = 100;
[self addSubview:view];//add to cell
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
UIView *view = [self viewWithTag:100];
if(selected)
{
//animation when selected
[UIView animateWithDuration:1.0 delay:0 options:UIViewAnimationOptionOverrideInheritedCurve animations:^(void){
view.backgroundColor = [UIColor orangeColor];
} completion:NULL];
}
else
{
//this is for when deselect if u want color in same sate then set it
}
// Configure the view for the selected state
}
- (void)layoutSubviews
{
[super layoutSubviews];
UIView *view = [self viewWithTag:100];//get the view
view.frame = CGRectMake(5, 5, 100, 30);//setting the frame
}
in your controller just use this custom cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if(cell == nil)
{
cell = [[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//dont add any animation hear becz u already added in custom cell
// [UIView animateWithDuration:1.0 delay:0 options:UIViewAnimationOptionOverrideInheritedCurve animations:^(void){
// ([cell viewWithTag:100]).backgroundColor = [UIColor orangeColor];
// } completion:NULL];
}
I have solve my problem:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
UITableViewCell *cell = ((UITableViewCell*)[tableView cellForRowAtIndexPath:indexPath]);
[self performSelector:#selector(launchAnimation:) withObject:cell afterDelay:0.1];
}
-(void)launchAnimation:(UITableViewCell*)cell{
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionOverrideInheritedCurve animations:^(void){
([cell viewWithTag:20]).backgroundColor = [UIColor orangeColor];
} completion:NULL];
}

How to make an iOS Drop down menu

How do I create a good looking drop down menu in iOS. It should open when the user clicks a button in the navigation bar.
I tried creating a table, but got the error Static table views are only valid when embedded in UITableViewController instances. If I use UITableViewController, then it has to be full width.
Maybe you could try using a CollectionView instead of TableView, and if you need sopport for iOS 4+, PSTCollectionView is a good option :)
What I did is added a Button and on button tap one table view is shown, whenever any row is selected that row title is set to button title.
- (void)addOrganizationButton {
self.organizationButton = [UIUtils createButtonWithFrame:CGRectMake(203,115,451,38)
titleText:#"Organization"
type:UIButtonTypeCustom
normalImage:nil selectedImage:nil
target:self
view:self.registerView
tag:0
selector:#selector(organizationButtonTap)];
self.organizationButton.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
[self.organizationButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
self.organizationButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
self.organizationButton.layer.borderWidth = 1;
}
//Show table view on button tap
- (void)organizationButtonTap {
self.organizationTable = [[UITableView alloc]initWithFrame:CGRectMake(203,153, 451,220)];
self.organizationTable.layer.borderWidth = 1;
self.organizationTable.dataSource = self;
self.organizationTable.delegate = self;
[UIView animateWithDuration:1
delay:0.0
options: UIViewAnimationOptionCurveEaseInOut
animations:^{
CGRect frame = self.organizationTable.frame;
frame.size.height = 220;
self.organizationTable.frame = frame;
}
completion:^(BOOL finished){
NSLog(#"Done!");
}];
[self.registerView addSubview:self.organizationTable];
}
//Table view delegates
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;//to be changed
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section{
return 3;//get dictionary count
}
- (UITableViewCell *) tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;
NSString *cellIdentifier=#"Cell Identifier";
cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell==nil){
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
cell.accessoryType = UITableViewCellAccessoryNone;
}
cell.textLabel.text = [NSString stringWithFormat:
#"Section %ld, Cell %ld",
(long)indexPath.section,
(long)indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.organizationButton setTitle:#"faf" forState:UIControlStateNormal];
[UIView animateWithDuration:1
delay:0.0
options: UIViewAnimationOptionCurveEaseInOut
animations:^{
CGRect frame = self.organizationTable.frame;
frame.size.height = 0;
self.organizationTable.frame = frame;
}
completion:^(BOOL finished){
NSLog(#"Done!");
}];
}
You can prepare a custom view for that and add it as a subview in your ViewController.
Use UIView animations for simulating "drop down" effect.

UICollectionViewCell flip and grow on tap

How can I achieve the animation where a UICollectionViewCell with flip and grow to show modal view on tap?
Here is what I used in another project and it was working well :
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
if (cell.selected) {
[collectionView deselectItemAtIndexPath:indexPath animated:YES];
[UIView transitionWithView:cell
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
[cell setFrame:self.selectedCellDefaultFrame];
cell.transform = self.selectedCellDefaultTransform;
}
completion:^(BOOL finished) {
self.selectedCellDefaultFrame = CGRectZero;
[collectionView reloadItemsAtIndexPaths:#[indexPath]];
}];
return NO;
}
else {
return YES;
}
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
[cell.superview bringSubviewToFront:cell];
self.selectedCellDefaultFrame = cell.frame;
self.selectedCellDefaultTransform = cell.transform;
[UIView transitionWithView:cell
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
[cell setFrame:collectionView.bounds];
cell.transform = CGAffineTransformMakeRotation(0.0);
}
completion:^(BOOL finished) {}];
}
Different things here :
The bringSubviewToFront: message call is used to prevent the cell to animate behind the other cells
We use two properties declared in the controller : selectedCellDefaultFrameand selectedCellDefaultTransform to save the default state of the cell and reinitialize it when deselecting
When deselecting, we call the reloadItemsAtIndexPaths: method of UICollectionView to be sure that the reset of the position is totally complete
Let me know if you have any trouble with this.
Good luck,
I haven't tried the grow animation, but I think I can help with the UICollectionViewCell flip animation.
Try:
UICollectionViewCell* cell = [collectionView cellForItemAtIndexPath:indexPath];
[UIView animateWithDuration:1.0
delay:0
options:(UIViewAnimationOptionAllowUserInteraction)
animations:^
{
NSLog(#"starting animation");
[UIView transitionFromView:cell.contentView
toView:newView
duration:.5
options:UIViewAnimationOptionTransitionFlipFromRight
completion:nil];
}
completion:^(BOOL finished)
{
NSLog(#"animation end");
}
];
Hope that helps!

Resources