I am animating a view over table view when user taps a cell. Although my DidSeclectRowAtIndexPath is getting called when I tap the cell first time but the animation does not take place. On the second tap the animation block gets triggered.
What may be causing this issue?
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.ChosenSubCategory=[self.SubCategoryListArray objectAtIndex:indexPath.row];
[self getUserSpecificLevelDetails];
// [self ShowLevelPickerView];
[UIView animateWithDuration:1.0 animations:^{
[self.ChooseLevelView setCenter:CGPointMake(self.view.frame.size.width/2, self.view.frame.size.height/2)];
[player prepareToPlay];
[player play];
}];
}
Might be because of the threading issue.
Please try the below solution. Hope it works.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
*)indexPath
{
self.ChosenSubCategory=[self.SubCategoryListArray objectAtIndex:indexPath.row];
[self getUserSpecificLevelDetails];
// [self ShowLevelPickerView];
[self performSelector:#selector(performOperation) withObject:nil afterDelay:0];
}
- (void)performOperation
{
[UIView animateWithDuration:1.0 animations:^{
[self.ChooseLevelView setCenter:CGPointMake(self.view.frame.size.width/2, self.view.frame.size.height/2)];
[player prepareToPlay];
[player play];
}];`
}
Related
I have a Horizontal UICollectionView with n number of records. Each cell has an UIImageView which needs to animate the Fadein Fadeout with some TimerInterval. So, i have planned to implement that reload my UICollectionView using NSTimer My code snippet,
....
....
if (collectionTimer) {
[collectionTimer invalidate];
collectionTimer = nil;
}
collectionTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(reloadCollection) userInfo:nil repeats:YES];
....
....
reloadCollection Method
-(void)reloadCollection{
[_collectionView reloadData];
}
cellForItemAtIndexPath Method
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
....
....
/* Basic Animation working fine*/
[UIView animateKeyframesWithDuration:1.0 delay:1.0 options:UIViewKeyframeAnimationOptionAutoreverse animations:^{
cell.articleImage.image = [UIImage imageNamed:[NSString stringWithFormat:#"%#.jpg", [images objectAtIndex:i]]];
} completion:nil];
/* Not working */
/* [UIView transitionWithView:cell.articleImage duration:1.0f options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
cell.articleImage.image = [UIImage imageNamed:[NSString stringWithFormat:#"%#.jpg", [images objectAtIndex:i]]];
} completion:nil]; */
....
....
}
The basic animation works fine. But, whenever i am trying to implement UIViewAnimationOptionTransitionCrossDissolve with transitionWithView method. It will showing the animation, but immediately one more image loaded because of reloadData calling. How to fix this? How to animate only the images in UICollectionView
Any Idea appreciated!
My animation work like this:
cell.articleImage.alpha = 0.0;
[UIView animateWithDuration:0.3f animations:^{
[cell.articleImage setAlpha:1.0];
}];
Try to add the animation for visible cells without reloading the collectionView:
NSArray* visibleCells = [collectionView visibleCells];
[visibleCells enumerateObjectsUsingBlock:^(UICollectionViewCell* cell, NSUInteger idx, BOOL *stop) {
//TODO: add animation;
}];
Update
To animate new cells, you should start animation after adding cell to window. In cell you can override method didMoveToWindow:
- (void)didMoveToWindow
{
[super didMoveToWindow];
if (self.window && self.shouldStartAnimation)
{
[self startAnimation];
}
}
And in ViewController these methods:
- (void)animateVisibleCells
{
NSArray* visibleCells = [self.collectionView visibleCells];
[visibleCells enumerateObjectsUsingBlock:^(BTCollectionViewCell* cell, NSUInteger idx, BOOL *stop) {
[cell startAnimation];
}];
}
#define ANIMATION_DURATION (0.3)
- (void)animateCells
{
self.shouldAnimationStart = YES;
[self animateVisibleCells];
[NSTimer scheduledTimerWithTimeInterval:ANIMATION_DURATION target:self selector:#selector(endAnimateCells) userInfo:nil repeats:NO];
}
- (void)endAnimateCells
{
self.shouldAnimationStart = NO;
}
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{
((BTCollectionViewCell*)cell).shouldStartAnimation = self.shouldAnimationStart;
}
But problem with synchronization of the animation continues to be (new animations will starts from 0 time). If you know method to start animation from concrete time, you can use it method in willDisplayCell
Well i guess that in your method cellForItemAtIndexPath you are not configuring animation right.
please use this.
[UIView animateKeyframesWithDuration:1.0 delay:0.1 options:UIViewKeyframeAnimationOptionAutoreverse animations:^{
cell.articleImage.image = [UIImage imageNamed:[NSString stringWithFormat:#"%#.jpg", [images objectAtIndex:i]]];
} completion:nil];
You were not assigning the delay properly to let animation work.
Hope it works for you now. Thanks
I'm trying to make a navigation-site for my app with an UICollectionView. As a user clicks on one of the cells, the ViewController should push another one with a zooming animation of the Image of the cell.
Everything is working fine and the next view is shown but here is the problem: when I called the next view and then navigate back to my UICollectionView and click on my cell again, the animation isn't shown anymore.
So I think that the ViewController doesn't call the
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{}
function anymore and kind of remembers the seque. But how do I tell him to do the animation again?
Here is the code for the segue:
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
CostumCollectionCell *theCell =(CostumCollectionCell*)[self.theCollectionView cellForItemAtIndexPath:indexPath];
UIImageView *overlayer = [[UIImageView alloc]initWithImage:theCell.theImageView.image];
overlayer.frame=theCell.frame;
[overlayer setContentMode:UIViewContentModeScaleAspectFill];
[self.theCollectionView addSubview:overlayer];
[UIView animateWithDuration:0.75 animations:^{
overlayer.frame=CGRectMake(theCell.frame.origin.x-theCell.frame.size.width/2, theCell.frame.origin.y-theCell.frame.size.height/2, theCell.frame.size.width*2, theCell.frame.size.height*2);
} completion:^(BOOL finished) {
switch (indexPath.row) {
case 0:
[self.navigationController pushViewController:[self.storyboard instantiateViewControllerWithIdentifier:#"auditionView"] animated:YES];
[overlayer removeFromSuperview];
break;
default:
break;
}
}];
}
updated code:
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
CostumCollectionCell *theCell =(CostumCollectionCell*)[self.theCollectionView cellForItemAtIndexPath:indexPath];
[self.overlayer setImage:theCell.theImageView.image];
self.overlayer.frame=theCell.frame;
[self.overlayer setHidden:NO];
[UIView animateWithDuration:0.75 delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:5.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
self.overlayer.frame=CGRectMake(theCell.frame.origin.x-theCell.frame.size.width/2, theCell.frame.origin.y-theCell.frame.size.height/2, theCell.frame.size.width*2, theCell.frame.size.height*2);
} completion:^(BOOL finished) {
if(finished){
switch (indexPath.row) {
case 0:
[self performSegueWithIdentifier:#"auditionSegue" sender:self];
[self.overlayer setHidden:YES];
break;
default:
break;
}
}
}];
}
I don't know if this is possible. I have UITableview when the user click one cell or row, the tableview will automatically scroll to top then do an action method after it reach at the top.
Here's my code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[UIView animateWithDuration:5.0 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
[self.tableView setContentOffset:CGPointZero animated:YES]; // scroll to top
} completion:^(BOOL finished) {
[self connectToSubMenu:indexPath.row];
}];
}
I don't know if I miss anything here. Sorry I'm still learning objective-c.
Add this to set your tableview to scroll top automatically.
-(void)tableView:(UITableView *)tableview didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Your custom code
[self.tableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
// Call your custom method here, Now tableview scrolled to top
}
I think you were pretty close. Using UIView's animateWithDuration is good, just need to use the right method to scroll the table position.
-(void)tableView:(UITableView *)tableview didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[UIView animateWithDuration:5.0 animations:^{
[self.tableView scrollToRowAtIndexPath:0 atScrollPosition:UITableViewScrollPositionTop animated:NO];
} completion:^(BOOL finished){
[self connectToSubMenu:indexPath.row];
}];
}
Note also that I set animated:NO in the inner method call, since the outer method is doing the animating.
I Have a UITableView with custom cell with UITextField and buttons on that ,my issue is when ever the user selects some textfields in bottom keybord is hiding that textfield , i tried to scroll up the UITableView by seeing some answers in stackoverflow. but it is not scrolling can any one help me in finding out the mistake made by me please.i have written code for scrolling in textFieldDidBeginEditing: method .textFieldDidBeginEditing: is also firing and executing the code in that but it is not scrolling up.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
{
// NSLog(#"No OF rows:%d",[contents count]);
return [contents count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
static NSString *cellIdentifier = #"cell";
// Try to retrieve from the table view a now-unused cell with the given identifier.
cell = (uploadCustomCell *)[tableView dequeueReusableCellWithIdentifier:#"uploadCustomCell"];
if (cell == nil) {
cell = [[uploadCustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"uploadCustomCell"];
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"uploadCustomCell"
owner:self options:nil];
cell = [nib objectAtIndex:0];
}
saveBtnCcell.hidden = YES;
cell.textNamefield.hidden = YES;
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[cell.defaultSwitch setEnabled:NO];
dictionaryContents = [contents objectAtIndex:indexPath.row];
cell
.nameLabelCell.text = [dictionaryContents valueForKey:#"VideoName"];
cell.userName.text = [dictionaryContents valueForKey:#"User"];
cell.thumbImg.image = [arrayimage objectAtIndex:indexPath.row];
NSString *defaultVideo = [dictionaryContents valueForKey:#"DefaultVideo"];
if ([defaultVideo isEqual: #"1"]) {
[defaultSwitche setOn:YES animated:YES];
}
else{
[defaultSwitche setOn:NO animated:YES];
}
[cell.defaultSwitch addTarget:self action:#selector(setState:)forControlEvents:UIControlEventValueChanged];
VideoNameTextField.hidden = YES;
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 207;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
// selectedRow=indexPath.row;
indexpathTest = indexPath.row;
[tabelView1 reloadData];
NSMutableArray *dictionary = [contents objectAtIndex:indexPath.row];
guid = [dictionary valueForKey:#"GUID"];
detailsVehImg.image = [arrayimage objectAtIndex:indexPath.row];;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;
{
return UITableViewCellEditingStyleDelete;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[self.tabelView1 scrollToRowAtIndexPath:1 atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
You should listen to the keyboard notifications and change your table view frame to show the cell you want. Scrolling isn't enough as if the cell is at the bottom it will be hidden anyway
-(void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillDisappear:)
name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillAppear:)
name:UIKeyboardWillShowNotification
object:nil];
}
-(void)viewDidUnload
{
[super viewDidUnload];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
-(void)keyboardWillAppear:(NSNotification *)note
{
CGRect tableViewFrame = self.tableView.frame;
// If your table view doesn't end at the bottom of the screen then this calculation of the height wouldn't be enough, you would need to take into consideration the distance between the screen bottom and the table view
tableViewFrame.size.height = tableViewFrame.size.height - [[note.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
CGRect visibleFrame = CGRectZero;
visibleFrame.origin = self.tableView.contentOffset;
visibleFrame.size = tableViewFrame.size;
[UIView animateWithDuration:[[note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]
delay:0
options:UIViewAnimationOptionBeginFromCurrentState | [[note.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]
animations:^{
self.tableView.frame = tableViewFrame;
}
completion:^(BOOL finished){
[self.tableView scrollRectToVisible:visibleFrame
animated:YES];
}];
}
-(void)keyboardWillDisappear:(NSNotification *)note
{
CGRect tableViewFrame = self.tableView.frame;
tableViewFrame.size.height = tableViewFrame.size.height + [[note.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
[UIView animateWithDuration:[[note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]
delay:0
options:UIViewAnimationOptionBeginFromCurrentState | [[note.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]
animations:^{
self.tableView.frame = tableViewFrame;
}
completion:nil];
}
Try this
[self.myTableView setContentOffset:CGPointZero animated:YES];
OR
// Table View - Scroll to top
[self.myTableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
[self.myTableView reloadData];
Parameter
animated:YES show scrolling animation.
animated:NO display table after scrolling(no animation.)
You have to reload your tableView before scrolling it. I have added one line of code in your textFieldDidBeginEditing. PLease try this.
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[self.tabelView1 reloadData];
NSArray *indexPathsForVisibleRows = [self.tabelView1 indexPathsForVisibleRows];
NSIndexPath *selectedIndexPath = [indexPathsForVisibleRows objectAtIndex:(indexPathsForVisibleRows.count/2)];
[self.tabelView1 scrollToRowAtIndexPath:selectedIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
}
Good Luck
When I select a row in a UITableView, I'm calling scrollRectToVisible:animated on the GCRect of the row's frame, and immediately afterwards doing some other animations. My problem is that I don't know when the animation from scrollRectToVisible:animated is complete.
My code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRwoAtIndexPath:indexPath];
[self.tableView scrollRectToVisible:cell.frame animated:YES];
//more animations here, which I'd like to start only after the previous line is finished!
}
I ran across this UIScrollViewDelegate method:
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
// Do your stuff.
}
Only called for animated scrolls. Not called for touch-based scrolls. Seems to work great.
An easier way is to encapsulate the scrolling code in a UIView animateWith[...] block, like this:
[UIView animateWithDuration:0.3f animations:^{
[self.tableView scrollRectToVisible:cell.frame animated:NO];
} completion:^(BOOL finished) {
// Some completion code
}];
Note that animated == NO in the scrollRectToVisible:animated: method.
The protocol UITableViewDelegate conforms to UIScrollViewDelegate. You can set BOOL parameter when you scroll manually and than check it in scrollViewDidScroll:
BOOL manualScroll;
...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRwoAtIndexPath:indexPath];
manualScroll = YES;
[self.tableView scrollRectToVisible:cell.frame animated:YES];
}
...
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (manualScroll)
{
manualScroll = NO;
//Do your staff
}
}
Don't forget to set UITableViewDelegate.