Queueing Animations using blocks - iphone

In my didSelectRowAtIndexPath method I call [self dismissView]; when the user selects a cell in order to dismiss the view if its already been presented. This clearly isn't very optimal and its overriding the presentView method without it animating the dismissView. Is there a better way to do this? Or at the very least let it wait for the view to finish animating without using NSTimer.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
[self dismissView];
// Do xyz...
[self presentView:twitterLinksView];
Then..
- (void)presentView:(id)sender
{
twitterLinksView.frame = CGRectMake(0, (self.view.frame.size.height + viewHeight), 320, 300);
[UIView animateWithDuration:0.60f animations:^{
CGRect twitterLinkFrame = self.twitterLinksView.frame;
twitterLinkFrame.origin.y = (self.view.frame.size.height - viewHeight);
twitterLinksView.frame = twitterLinkFrame;
}];
}
- (void)dismissView
{
[UIView animateWithDuration:0.75f animations:^{
CGRect twitterLinkFrame = self.twitterLinksView.frame;
twitterLinkFrame.origin.y = (self.view.frame.size.height + viewHeight);
self.twitterLinksView.frame = twitterLinkFrame;
}];
}

[UIView animateWithDuration:1. animations:^{
//firstAnimationBlock
} completion:^(BOOL finished){
[UIView animateWithDuration:1. animations:^{
//animations in this block will be called after firstAnimationBlock has expired
}];
}];
as i understand you wanna fire 2 animation one after the other. this code (block inside block) makes this
this part is after edit:
ok now you can try writing like that
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
[self dismissView];
// Do xyz...
[self performSelector:#selector(presentView:) withObject:twitterLinksView afterDelay:0.75];
//[self presentView:twitterLinksView];
}

I ended up splitting out my creation method and using [[self.view subviews] containsObject:twitterLinksView] to check for the view. Also to be noted is [self performSelector:#selector(createView) withObject:twitterLinksView afterDelay:0.76f] had to be very slightly ahead of the dismissing animation for it to work at all... yeah wtf.
In the didSelectRowAtIndexPath method i used [self performSelector:#selector(presentView:)];
Thanks to meth for solving part of the puzzle.
- (void)presentView:(id)sender
{
if ([[self.view subviews] containsObject:twitterLinksView])
{
[self dismissView];
[self performSelector:#selector(createView) withObject:twitterLinksView afterDelay:0.76f];
NSLog(#"Animating ut old");
}
else
{
NSLog(#"Creating new view");
[self createView];
}
}
-(void)createView
{
twitterLinksView.frame = CGRectMake(0, (self.view.frame.size.height + viewHeight), 320, 300);
[UIView animateWithDuration:0.60f animations:^{
CGRect twitterLinkFrame = self.twitterLinksView.frame;
twitterLinkFrame.origin.y = (self.view.frame.size.height - viewHeight);
twitterLinksView.frame = twitterLinkFrame;
[self.view addSubview:twitterLinksView];
}];
}
- (void)dismissView
{
[UIView animateWithDuration:0.75f animations:^{
CGRect twitterLinkFrame = self.twitterLinksView.frame;
twitterLinkFrame.origin.y = (self.view.frame.size.height + viewHeight);
self.twitterLinksView.frame = twitterLinkFrame;
}completion:^(BOOL finished){
[twitterLinksView removeFromSuperview];
}];
}

Related

how to hide a headView of section on UITableView?

i want to hide navigationbar and tabbar on touch and move on uitableview, blow code:
_headView from viewForHeaderInSection it's no problem.
but sometimes after block Executed, _headView is visible
if(_headView)
_headView.hidden = YES; //
[UIView animateWithDuration:0.5 animations:^{
scrollView.frame = rect;
_vc.navigationController.navigationBar.top -= navigationBarHeight;
tabView.top = SCREEN_HEIGHT;
} completion:^(BOOL finished) {
}];
if i move hide code to completion block , it's run OK, but hide after 0.5 sec, it's slowly .
[UIView animateWithDuration:0.5 animations:^{
scrollView.frame = rect;
_vc.navigationController.navigationBar.top -= navigationBarHeight;
tabView.top = SCREEN_HEIGHT;
} completion:^(BOOL finished) {
if(_headView)
_headView.hidden = YES; //Delay after 0.5s.
}];
please help me , thanks.
We have a delegate method for the setting height of section for UITableView
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
just return 0 for this, for hiding header.

How do I pass touch events through to parentViewController?

I have a UIViewContoller with a few container(child) UIiewsController. The main UIViewController (mvc) contains:
1.) A UICollectionView that occupies the entire view of mvc (it is above mvc.view but below all other controls).
2.) A UIViewController that displays search options (s1vc)
3.) another similar to #2 (s2vc)
4.) another similar to #2 (s3vc)
I have added gesture recognizers to mvc so that a user can hide/show each of the child view controllers by swiping them off of the screen.
The problem is that when a user swipes any of the svcs off of the screen, they cannot scroll the mvc's collectionView.
Here is how I am hiding/showing the svcs:
-(void)swipeLeftGestureHandler:(UIGestureRecognizer*)gestureRecognizer{
SMLOG(#"Swiped Left");
if([SMUser activeUser] == nil) return;
if([self gestureHorizontalScreenSide:gestureRecognizer] == kHorizontalScreenSideLeft){
[self hideFacets];
}
else{
[self showAccordion];
}
}
-(void)swipeRightGestureHandler:(UIGestureRecognizer*)gestureRecognizer{
SMLOG(#"Swiped Right");
if([SMUser activeUser] == nil) return;
if([self gestureHorizontalScreenSide:gestureRecognizer] == kHorizontalScreenSideLeft){
[self showFacets];
}
else{
[self hideAccordion];
}
}
-(void)hideFacets{
if(self.facetVisible == NO) return;
[UIView animateWithDuration:0.25
animations:^{
CGRect newFrame = self.facetViewController.view.frame;
newFrame.origin = CGPointMake(newFrame.origin.x - newFrame.size.width, newFrame.origin.y);
self.facetViewController.view.frame = newFrame;
self.facetVisible = NO;
}
completion:^(BOOL finished){
self.facetViewController.view.hidden = YES;
self.facetViewController.view.userInteractionEnabled = NO;
}];
}
-(void)showFacets{
if([SMUser activeUser] == nil) return;
if(self.facetVisible == YES) return;
self.facetViewController.view.userInteractionEnabled = YES;
[UIView animateWithDuration:0.25
animations:^{
self.facetViewController.view.hidden = NO;
CGRect newFrame = self.facetViewController.view.frame;
newFrame.origin = CGPointMake(newFrame.origin.x + newFrame.size.width, newFrame.origin.y);
self.facetViewController.view.frame = newFrame;
self.facetVisible = YES;
}
completion:^(BOOL finished){
}];
}
As you can see I'm toggling the svc.view.hidden property and then I also tried toggling th svc.userInteractionEnabled.property but no luck. Still cannot swipe the collection view by swiping where the facets view controller was/is.
Any ideas?
The solution here is to add another outlet (using IB) for the container view in the parentViewController (I called it facetContainerView in this code) and then set it's userInteractionEnabled property.
-(void)hideFacets{
if(self.facetVisible == NO) return;
self.facetVisible = NO;
[UIView animateWithDuration:0.25
animations:^{
CGRect newFrame = self.facetViewController.view.frame;
newFrame.origin = CGPointMake(newFrame.origin.x - newFrame.size.width, newFrame.origin.y);
self.facetViewController.view.frame = newFrame;
}
completion:^(BOOL finished){
self.facetViewController.view.hidden = YES;
self.facetContainerView.userInteractionEnabled = NO;
}];
}
-(void)showFacets{
if(self.facetVisible == YES) return;
self.facetVisible = YES;
self.facetContainerView.userInteractionEnabled = YES;
[UIView animateWithDuration:0.25
animations:^{
self.facetViewController.view.hidden = NO;
CGRect newFrame = self.facetViewController.view.frame;
newFrame.origin = CGPointMake(newFrame.origin.x + newFrame.size.width, newFrame.origin.y);
self.facetViewController.view.frame = newFrame;
}
completion:^(BOOL finished){
}];
}
I was curious as to how this new view outlet was different from self.facetViewController.view, so I inserted this code to compare addresses (they are different indeed). I'm not sure about the heirarchy, but it seems that there is an extra view layer that I was not aware of.
NSLog(#"self.facetViewController.view: %p", self.facetViewController.view);
NSLog(#"self.facetContainerView: %p", self.facetContainerView);
Hopefully this will help someone at some point.

Keyboard hides the custom cell

I am having a custom cell in my tableview, when showing keyboard some of my cell gets hidden behind the keyboard.
To fix this issue I have tried as below
- (void) textFieldDidBeginEditing:(UITextField *)textField {
CustomCell *cell = (CustomCell*) [[textField superview] superview];
NSIndexPath *indexPath = [self.mySmlMsgTemplatesTbl indexPathForCell:cell];
[self.mySmlMsgTemplatesTbl scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
// [self.mySmlMsgTemplatesTbl scrollToRowAtIndexPath:[self.mySmlMsgTemplatesTbl indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
But it seems to be not working.
You should try following code as I have shown below. I didn't try it but it should work.
- (void)textFieldDidBeginEditing:(UITextField *)textField{
CGPoint point = [self.tableView convertPoint:yourtextview.bounds.origin fromView:yourtextview];
NSIndexPath* path = [self.tableView indexPathForRowAtPoint:point];
[self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
If it is the last cell for example, this won't work. The tableview can't scroll that far up. You will need to resize the tableview frame or use it's contentInset property to resize it.
There is another way. You could try to move the whole view up and down.
Hope this will help
#define kOFFSET_FOR_KEYBOARD 200.0
- (BOOL)textFieldShouldBeginEditing:(UITextField*)textField {
[txtField addTarget:self action:#selector(setViewMovedUp:)forControlEvents:UIControlEventEditingDidBegin];
[txtField addTarget:self action:#selector(setViewMovedDown:)forControlEvents:UIControlEventEditingDidEndOnExit];
}
-(void)setViewMovedUp:(id)sender
{
if (isKeyboardAppeared) {
return;
}
isKeyboardAppeared = YES;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3]; // if you want to slide up the view
CGRect rect = self.view.frame;
rect.origin.y -= kOFFSET_FOR_KEYBOARD;
rect.size.height += kOFFSET_FOR_KEYBOARD;
self.view.frame = rect;
[UIView commitAnimations];
}
-(void)setViewMovedDown:(id)sender
{
[self actionSaveRegistration];
if (!isKeyboardAppeared) {
return;
}
isKeyboardAppeared = NO;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
CGRect rect = self.view.frame;
rect.origin.y += kOFFSET_FOR_KEYBOARD;
rect.size.height -= kOFFSET_FOR_KEYBOARD;
self.view.frame = rect;
[UIView commitAnimations];
}
i do this type of app you just need the textFieldname or textfield tag ..and you can pgive the tag to textField with visiblecell...
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if(textField.tag==3)
{
tableview.frame=CGRectMake(tableview.frame.origin.x, tableview.frame.origin.y-40,tableview.frame.size.width , tableview.frame.size.height+40);
}
else if(textField.tag==4)
{
tableview.frame=CGRectMake(tableview.frame.origin.x, tableview.frame.origin.y-40,tableview.frame.size.width , tableview.frame.size.height+40);
}
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if(textField.tag==3)
{
tableview.frame=CGRectMake(0,0, 320,460);
//tableview.frame=CGRectMake(tableview.frame.origin.x, tableview.frame.origin.y+70,tableview.frame.size.width , tableview.frame.size.height-70);
}
else if(textField.tag==4)
{
tableview.frame=CGRectMake(0,0, 320,460);
//tableview.frame=CGRectMake(tableview.frame.origin.x, tableview.frame.origin.y+70,tableview.frame.size.width , tableview.frame.size.height-70);
}
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[textField resignFirstResponder];
if(textField.tag==3)
{
tableview.frame=CGRectMake(0,0, 320,460);
//scrollview.frame=CGRectMake(tableview.frame.origin.x, tableview.frame.origin.y+70,tableview.frame.size.width , tableview.frame.size.height-70);
}
else if(textField.tag==4)
{
tableview.frame=CGRectMake(0,0, 320,460);
//tableview.frame=CGRectMake(scrollview.frame.origin.x, tableview.frame.origin.y-70,tableview.frame.size.width , tableview.frame.size.height+70);
}
}
i use here scrollView for Registration form here not a perfect code which you want but i think you can get idea from this code...
Hope,this help you..
:)

Displacing one view with another with a custom segue animation?

I am trying to implement SUBJ but can't make destination segue appear in my animation. I want to make animation for view change where new segue will displace old one. Currently my perform method looks like this:
- (void) perform {
UIViewController *src = (UIViewController *) self.sourceViewController;
UIViewController *dst = (UIViewController *) self.destinationViewController;
[UIView animateWithDuration:2.0
animations:^{
//tried a lot of staff to make dst view to fall from top at the same time as current view falling to bottom but failed.
src.view.transform=CGAffineTransformMakeTranslation(0, 480);
}
completion:^(BOOL finished){
[[self sourceViewController] presentModalViewController:[self destinationViewController] animated:NO];
}
];
}
Any ideas how can I add to my animation block new view appearing from top?
Many thanks!
EDIT:
- (void) perform {
UIViewController *src = (UIViewController *) self.sourceViewController;
UIViewController *dst = (UIViewController *) self.destinationViewController;
src.view.transform = CGAffineTransformMakeTranslation(0, 0);
dst.view.transform = CGAffineTransformMakeTranslation(0, -480);
[UIView animateWithDuration:2.0
animations:^{
[src.view addSubview:dst.view];
src.view.transform = CGAffineTransformMakeTranslation(0, 460);
}
completion:^(BOOL finished){
[src presentModalViewController:dst animated:NO];
}
];
}
Thats how I did it in the end.
I don't quite get what you mean by new and old so i assume new = dst and old = src.
- (void) perform {
UIViewController *src = (UIViewController *) self.sourceViewController;
UIViewController *dst = (UIViewController *) self.destinationViewController;
src.view.transform = CGAffineTransformMakeTranslation(0, 0);
dst.view.transform = CGAffineTransformMakeTranslation(0, -480);
[UIView animateWithDuration:2.0
animations:^{
[src presentModalViewController:dst animated:NO];
src.view.transform = CGAffineTransformMakeTranslation(0, 480);
dst.view.transform = CGAffineTransformMakeTranslation(0, 0);
}
];
}
This should do it.

How can we implement pagecurl animation in tableview?

Ha ii every body ,how can we implement a page-curl in tableview,i have a tableview which contains pages of the book and i have implement the touch events in the tableview cell for next chapter and previous chapter,left-swipe for next and right-swipe for previous chapter,when we swipe the tableview it reloads the next chapter and previous chapter content,it really works well but i want it in a page-curl animation,when the user swipe left or right tableview loads content with a page-curl animation.Is that possible to do in a tableview cell?my code for left and right swipe for chapter navigation as follows.
-(void) handleSwipeGesture:(UISwipeGestureRecognizer*)recognizer {
if(![delegate.selectedChapter isEqualToString:[NSString stringWithFormat:#"%d",[DbHandler mNumberOfChaptersInBook:delegate.selectedBook]]]) {
// if the currentChapter is the last then do nothing
delegate.selectedChapter = [NSString stringWithFormat:#"%d",[delegate.selectedChapter intValue] + 1];
[delegate reloadVerses];
[self resetReadViewToVerse:1];
[table removeGestureRecognizer:recognizer];
}
if (recognizer.state==UIGestureRecognizerStateBegan ) {
self.table.scrollEnabled = NO;
}
else if(recognizer.state==UIGestureRecognizerStateEnded) {
self.table.scrollEnabled = YES;
}
return;
}
-(void) handleSwipeGestureleft:(UISwipeGestureRecognizer*)recognizer {
if(![delegate.selectedChapter isEqualToString:#"1"])
{
delegate.selectedChapter = [NSString stringWithFormat:#"%d",[delegate.selectedChapter intValue] - 1];
[delegate reloadVerses];
[self resetReadViewToVerse:1];
[table removeGestureRecognizer:recognizer];
}
if (recognizer.state==UIGestureRecognizerStateBegan ) {
self.table.scrollEnabled = NO;
}
else if(recognizer.state==UIGestureRecognizerStateEnded) {
self.table.scrollEnabled = YES;
}
return;
}
Thanks in advance.
I got the answer.
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.4];
[UIView setAnimationDelay:0.0];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDidStopSelector:#selector(animCompleteHandler:finished:context:)];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.view cache:YES];
[UIView commitAnimations];
just put this code inside the methods.Thanks