I have UITableView on SingleView. Table view have constraint left 0, right 0, bottom 0, top 520. I need change top 520 to the 0 when scrolling up, and when scrolling bottom return 520. How can make it.
How change NSLayoutConstraint from scroll in -
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
I was trying to implement the so-but failed
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
if (scrollView.tag == 1){
if (scrollView.contentOffset.y < pointNow.y) {
self.heightLogTabTableView.constant = 0;
[UIView animateWithDuration:0.5f animations:^{
[self.view layoutIfNeeded];
}];
}else if (scrollView.contentOffset.y > pointNow.y) {
self.heightLogTabTableView.constant = 520;
[UIView animateWithDuration:0.5f animations:^{
[self.view layoutIfNeeded];
}];
}
}
}
Replace [self.view layoutIfNeeded]; in your code by-- [_tableView beginUpdates]; and [_tableView endUpdates];. Also modify your variable pointNow as follows.
#import "ViewController.h"
#interface ViewController (UIScrollViewDelegate){
}
#end
#implementation ViewController
CGPoint pointNow;
- (void)viewDidLoad{
[super viewDidLoad];
pointNow = CGPointMake(0, 0);
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
if (scrollView.contentOffset.y < pointNow.y) {
self.heightLogTabTableView.constant = 0;
[UIView animateWithDuration:0.5f animations:^{
[_tableView beginUpdates];
[_tableView endUpdates];
}];
}else if (scrollView.contentOffset.y > pointNow.y) {
self.heightLogTabTableView.constant = 520;
[UIView animateWithDuration:0.5f animations:^{
[_tableView beginUpdates];
[_tableView endUpdates];
}];
}
pointNow = scrollView.contentOffset;
}
#end
Try the setNeedsUpdateConstraints method right after you change the constraint constant. Like:
[self.tableView setNeedsUpdateConstraints];
Update -
If I understood you correctly, this is what you are looking for I think :
-(void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{
if(self.heightLogTabTableView.contentOffset.y<0){
//it means table view is pulled down like refresh
}
else if(self.heightLogTabTableView.contentOffset.y >= 0) {
//it means table view is being scrolled up
}
}
Hope this helps you.
This single line of code will solve your issue with all top,bottom,left, right constraints to Zero
[self.tableView setContentInset:UIEdgeInsetsMake(520, 0, 0, 0)];
Please try this and it will help you....
-(void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
if (scrollView.tag != 1)
{
return;
}
if(self.heightLogTabTableView.contentOffset.y<0)
{
self.heightLogTabTableView.constant = 0;
[UIView animateWithDuration:0.5f animations:^{
[self.view layoutIfNeeded];
}];
}
else
{
self.heightLogTabTableView.constant = 520;
[UIView animateWithDuration:0.5f animations:^{
[self.view layoutIfNeeded];
}];
}
}
i add global varible CGFloat in my .h file "#property (nonatomic) CGFloat lastScrollOffset;"
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
if (scrollView.tag == 1){
if (scrollView.contentOffset.y > _lastScrollOffset) {
self.heightLogTabTableView.constant = 0;
[UIView animateWithDuration:0.5f animations:^{
[self.view layoutIfNeeded];
}];
} else if (scrollView.contentOffset.y < _lastScrollOffset) {
self.heightLogTabTableView.constant = self.informationTask.frame.size.height;
[UIView animateWithDuration:0.5f animations:^{
[self.view layoutIfNeeded];
}];
}
_lastScrollOffset = scrollView.contentOffset.y;
}
else if (scrollView.tag == 2){
if (scrollView.contentOffset.y > _lastScrollOffset) {
self.heightCommentTabTableView.constant = 0;
[UIView animateWithDuration:0.5f animations:^{
[self.view layoutIfNeeded];
self.typeCommentView.hidden = NO;
}];
} else if (scrollView.contentOffset.y < _lastScrollOffset) {
self.heightCommentTabTableView.constant = self.informationTask.frame.size.height + 220;
[UIView animateWithDuration:0.5f animations:^{
[self.view layoutIfNeeded];
self.typeCommentView.hidden = YES;
}];
}
}
}
Related
I’m working on a UI effect, with “pull up to load more” and “pull down to go back”.
It should works like: When user pull theUIScrollView up by a certain distance, a load-more action is triggered, and lower half of theUIScrollView’s content would be scrolled into visible area. After that, if user pull down thescrollView by a distance, it should roll back to the upper half.
I have implemented it by settingcontentInsets of theUIScrollView when dragging triggered the action.
The problem is that at the time of changing of thescrollView’s contentInsets, it flickers. I printed some logs and found that it is caused by an unusually jump ofcontentOffset.y whencontentInsets changes! But I don’t know why.
The following are simplified but enoughViewController codes for reproducing the issue. With logs you can see clearly what happens.
Could someone helps me to solve it?
#import "IssueShowcaseViewController.h"
#interface IssueShowcaseViewController () <UIScrollViewDelegate>
{
BOOL _isShowingUpperView;
}
#property (nonatomic, strong) UIScrollView* scrollView;
#property (nonatomic, strong) UIView* upperView;
#property (nonatomic, strong) UIView* lowerView;
#end
#implementation IssueShowcaseViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
self.upperView = [[UIView alloc] initWithFrame:self.scrollView.bounds];
self.lowerView = [[UIView alloc] initWithFrame:CGRectOffset(self.scrollView.bounds, 0, self.scrollView.bounds.size.height)];
[self.upperView setBackgroundColor:[UIColor blueColor]];
[self.lowerView setBackgroundColor:[UIColor greenColor]];
//Add upperView to upper half, and lowerView to lower half:
[self.scrollView addSubview:self.upperView];
[self.scrollView addSubview:self.lowerView];
[self.view addSubview:self.scrollView];
_isShowingUpperView = YES;
self.scrollView.delegate = self;
// Observe scrollView.contentOffset for watching unnormal changes:
[self.scrollView addObserver:self forKeyPath:#"contentOffset" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
// Set contentSize as the sum height of two subviews:
self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width, CGRectGetMaxY(self.lowerView.frame) - CGRectGetMinY(self.upperView.frame));
// But the contentInset is set as to not allow scrolling into lower half:
// 1-pixel more space is necessary, as the scrollView would not be able to scroll downwards without it:
self.scrollView.contentInset = UIEdgeInsetsMake(0, 0, 1-self.lowerView.frame.size.height, 0);
}
- (void) scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if (_isShowingUpperView)
{
if (scrollView.contentOffset.y > 60)
{
scrollView.contentInset = UIEdgeInsetsMake(1-self.upperView.frame.size.height, 0, 0, 0);
_isShowingUpperView = NO;
}
}
else
{
if (scrollView.contentOffset.y < self.upperView.frame.size.height - 60)
{
scrollView.contentInset = UIEdgeInsetsMake(0, 0, 1-self.lowerView.frame.size.height, 0);
_isShowingUpperView = YES;
}
}
}
#pragma mark Here we can see what happens:
- (void) scrollViewDidScroll:(UIScrollView *)scrollView {
NSLog(#"contentOffsetY = %f", scrollView.contentOffset.y);
}
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (object == self.scrollView) {
CGPoint oldOffset = [[change objectForKey:#"old"] CGPointValue];
CGPoint newOffset = [[change objectForKey:#"new"] CGPointValue];
if (fabs(newOffset.y - oldOffset.y) > 300) {
NSLog(#"Weird: %#", change);
}
}
}
#end
After so many tries, I have found a solution: First set a zero contentInsets in an animation block, then in the completion block, set the new contentInsets and correct contentOffset:
- (void) scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if (_isShowingUpperView)
{
if (scrollView.contentOffset.y > 60)
{
[UIView animateWithDuration:0.0f animations:^{
scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3f animations:^{
scrollView.contentOffset = CGPointMake(0, self.upperView.frame.size.height);
} completion:^(BOOL finished) {
scrollView.contentInset = UIEdgeInsetsMake(1-self.upperView.frame.size.height, 0, 0, 0);
}];
}];
_isShowingUpperView = NO;
}
}
else
{
if (scrollView.contentOffset.y < self.upperView.frame.size.height - 60)
{
[UIView animateWithDuration:0.0f animations:^{
scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3f animations:^{
scrollView.contentOffset = CGPointMake(0, 0);
} completion:^(BOOL finished) {
scrollView.contentInset = UIEdgeInsetsMake(0, 0, 1-self.lowerView.frame.size.height, 0);
}];
}];
_isShowingUpperView = YES;
}
}
}
I hope this question makes sense, I have a login screen, when I click on the one of my input fields (either Username or Password) a keyboard appears. but when that happens Everything moves in motion from left to right, so I have a big white space on the left side. What I am expecting is for everything to move from down to up instead. I really hope this makes sense. Here is my code:
- (void)animateTextField:(UITextField *) textField up: (BOOL) up;
- (void)NavButtonPressed: (UIButton*)sender;
- (void)NavButtonPressed: (UIButton*)sender
{
if([sender isEqual:navBarNextButton])
{
[self.idTextField resignFirstResponder];
[self.passwordTextField becomeFirstResponder];
currentResponder = 1;
[self animateTextField:self.passwordTextField up:NO];
[self animateTextField:self.passwordTextField up:YES];
[navBarNextButton setEnabled:NO];
[navBarPrevButton setEnabled:YES];
}
else
{
[self.passwordTextField resignFirstResponder];
[self.idTextField becomeFirstResponder];
currentResponder = 0;
[self animateTextField:self.idTextField up:NO];
[self animateTextField:self.idTextField up:YES];
[navBarNextButton setEnabled:YES];
[navBarPrevButton setEnabled:NO];
}
}
- (void)animateTextField:(UITextField *) textField up: (BOOL) up
{
int movementDistance;
if(UIInterfaceOrientationIsLandscape(self.interfaceOrientation))
{
if([textField isEqual:self.idTextField])
{
[textfieldNavigatorView setFrame:CGRectMake(0.0f, (1024.0f/2.0f)-31.5f, 1024.0f, 45.0f)];
movementDistance = 110;
}
else
{
[textfieldNavigatorView setFrame:CGRectMake(0.0f, (1024.0f/2.0f)-26.5f, 1024.0f, 45.0f)];
movementDistance = 115;
}
}
else
{movementDistance = 0;}
const float movementDuration = 0.3f;
int movement=0;
if([self interfaceOrientation] == UIInterfaceOrientationLandscapeLeft)
movement = (up? -movementDistance : movementDistance);
if([self interfaceOrientation] == UIInterfaceOrientationLandscapeRight)
movement = (up? movementDistance : -movementDistance);
[UIView beginAnimations:#"keyboardtransition" context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:movementDuration];
self.view.frame = CGRectOffset(self.view.frame, movement, 0);
[UIView commitAnimations];
}
If anyone could help, that would be amazing. My project Device is set to Landscape Right only.
I had same issue before, in iOS 7 and 8 it works differently. So I implemented a method for handling the issue:
- (void)keyboardHideShow:(UIView *)view shiftBy:(float)shiftAmount forState:(BOOL)state
{
float keyBoardOffset = shiftAmount;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3]; // if you want to slide up the view
[UIView setAnimationBeginsFromCurrentState:YES];
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
CGRect rect = [[[UIApplication sharedApplication] keyWindow] bounds];
if (state)
{
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8)
{
if (orientation == UIInterfaceOrientationLandscapeLeft)
{
rect.origin.x -= keyBoardOffset;
}
else
{
rect.origin.x += keyBoardOffset;
}
}
else
{
rect.origin.y -= keyBoardOffset;
}
}
view.frame = rect;
[UIView commitAnimations];
}
You can call it like:
[self keyboardHideShow:textfieldNavigatorView shiftBy:31.5 forState:true]; // For up
[self keyboardHideShow:textfieldNavigatorView shiftBy:31.5 forState:false]; // For down
I have a tableview with a hidden property. I want to unhide it with animation so that it could slide from bottom to top? Any suggestions please.
-(IBAction) hideTable : (id) sender;
{
if(self.tb.hidden==true)
{
self.tb.alpha=1;
[self.tb setHidden:NO];
}
else{
[self.tb setHidden:YES];
}
}
-(IBAction) hideTable : (id) sender{
if (self.sessionView.hidden == YES) {
// Currently NOT Visible. Show it now
// First unhide it
yourTableView.hidden = NO;
[UIView animateWithDuration:0.5f
animations:^{
// Get the Existing table View frame
CGRect hiddenFrame = yourTableView.frame;
// Reset it to 0 or your own value
hiddenFrame.origin.y = 0;
// Set the new frame
yourTableView.frame = hiddenFrame;
} completion:^(BOOL finished) {
NSLog(#"Shown");
}];
}
else{
// Currently Visible. Hide it Now
[UIView animateWithDuration:0.5f
animations:^{
// Get the Existing table View frame
CGRect hiddenFrame = yourTableView.frame;
// Under the superview height
hiddenFrame.origin.y = yourTableView.superview.frame.size.height;
// Set the new frame
yourTableView.frame = hiddenFrame;
} completion:^(BOOL finished) {
yourTableView.hidden = YES;
NSLog(#"Hidden");
}];
}
}
try this
CGRect frame = self.tb.frame;
if (self.tb.hidden) {
CGRect temp_frame = frame;
frame.size.height = 1;
self.tb.frame = temp_frame;
self.tb.hidden = NO;
[UIView animateWithDuration:0.3
animations:^{
self.tb.frame = frame;
} completion:^(BOOL finished) {
}];
}
else
{
[UIView animateWithDuration:0.3
animations:^{
CGRect temp_frame = frame;
frame.size.height = 1;
self.tb.frame = temp_frame;
} completion:^(BOOL finished) {
self.tb.hidden = YES;
}];
}
try this
-(IBAction) hideTable : (id) sender;
{
if(self.tb.hidden==true)
{
self.tb.alpha=1;
[self.tb setHidden:NO];
[UIView animateWithDuration:.25
animations:^{
self.tb.frame = CGRectMake(0,50,320,400); // your req frame
}
];
}
else
{
[UIView animateWithDuration:0.35
animations:^{
self.tb.frame = CGRectMake(0, self.view.frame.size.height+10, 320,400); // y point of yor tableview is more than view bounds so it goes down
}
completion:^(BOOL finished){
[self.tb setHidden:YES];
}
];
}
}
You can use the below methods:
1. (void)showDropDownTable:- To show tableview with top to bottom animation.
2. (void)hideDropdownTable:- To hide tableview with bottom to top animation.
- (IBAction)btnDropDownClicked:(id)sender
{
if (checkShowHideTableView == TRUE)
{
[self hideTableView];
}
if (self.tblDropDown.hidden)
{
[self showDropDownTable];
}
else
{
[self hideDropdownTable];
}
}
- (void)showDropDownTable
{
[UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationCurveEaseOut animations: ^{
_tblDropDown.frame = CGRectMake(self.tblDropDown.frame.origin.x, self.tblDropDown.frame.origin.y, self.tblDropDown.frame.size.width, kDropdownTableHeight);
self.tblDropDown.hidden = FALSE;
} completion: ^(BOOL finished) {
}];
}
- (void)hideDropdownTable
{
[UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationCurveEaseOut animations: ^{
_tblDropDown.frame = CGRectMake(self.tblDropDown.frame.origin.x, self.tblDropDown.frame.origin.y, self.tblDropDown.frame.size.width, 0);
} completion: ^(BOOL finished) {
self.tblDropDown.hidden = TRUE;
}];
}
Hope this can help you.
Try the following
[self.tb beginUpdates];
[UIView animateWithDuration:0.5
delay:0.1
options:(UIViewAnimationCurveEaseInOut|UIViewAnimationOptionAllowUserInteraction)
animations:^{
if(self.tb.isHidden)
{
self.tb.alpha=1;
[self.tb setHidden:NO];
}
else
{
self.tb.alpha=0;
[self.tb setHidden:YES];
}
}
completion:^(BOOL finished) {
}];
[self.tb endUpdates];
I am implementing a custom focus bar on top of my keyboard. The focus bar has widgets to move cursor back and forward along with a done button.
Now, with iOS 7, I am seeing the focus bar is moving faster than keyboard. Because of this for a second I see screen behind the focus bar before it sits on top of keyboard. This is working fine in iOS 6.
Below is what I am doing:
- (void)keyboardWillShow:(NSNotification *)iNotification {
self.dismissForm = NO;
self.shouldScrollCell = YES;
CGFloat aKeyboardAnimationDuration = [[iNotification userInfo][UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect aKeyboardFrame = [[iNotification userInfo][UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect adjustedKeyboardFrame = [self.view convertRect:aKeyboardFrame fromView:nil];
CGFloat adjustedHeight;
adjustedHeight = aKeyboardFrame.size.height + self.focusControlBar.frame.size.height;
[self.focusControlBar viewForFocusControlWillShowWithEndFrame:adjustedKeyboardFrame andAnimationDuration:aKeyboardAnimationDuration];
[UIView animateWithDuration:0.3 animations:^() {
[self.tableView setContentInset:UIEdgeInsetsMake(kScreenOrigin, kScreenOrigin, adjustedHeight, 0.0f)];
[self.tableView setScrollIndicatorInsets:UIEdgeInsetsMake(kScreenOrigin, kScreenOrigin, adjustedHeight, 0.0f)];
}];
}
This is my focus bar animation code:
- (void)viewForFocusControlWillShowWithEndFrame:(CGRect)iFrame andAnimationDuration:(CGFloat)iDuration {
BOOL aShouldAppear = YES;
if (self.delegate && [self.delegate respondsToSelector:#selector(focusControlBarShouldAppear:)]) {
aShouldAppear = [self.delegate focusControlBarShouldAppear:self];
}
if (aShouldAppear) {
if (self.delegate && [self.delegate respondsToSelector:#selector(focusControlBarWillAppear:)]) {
[self.delegate focusControlBarWillAppear:self];
}
CGRect aBarFrame = self.frame;
UIInterfaceOrientation anInterfaceOrientation = [UIApplication sharedApplication].statusBarOrientation;
aBarFrame.size.height = [self heightForOrientation:anInterfaceOrientation];
self.frame = aBarFrame;
aBarFrame.origin.y = self.superview.bounds.size.height - iFrame.size.height - aBarFrame.size.height;
[UIView animateWithDuration:iDuration animations:^(void) {
self.frame = aBarFrame;
} completion:^(BOOL iFinished) {
if (self.delegate && [self.delegate respondsToSelector:#selector(focusControlBarDidAppear:)]) {
[self.delegate focusControlBarDidAppear:self];
}
}];
}
}
I just got to know that with iOS 7 we need to also keep KeyboardAnimationCurve into account. With the below modified code I had it worked.
- (void)keyboardWillShow:(NSNotification *)iNotification {
self.dismissForm = NO;
self.shouldScrollCell = YES;
NSDictionary *aNotificationInfo = [iNotification userInfo];
CGFloat aKeyboardAnimationDuration = [aNotificationInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve aKeyboardAnimationCurve = [aNotificationInfo[UIKeyboardAnimationCurveUserInfoKey] intValue];
CGRect aKeyboardFrame = [aNotificationInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect adjustedKeyboardFrame = [self.view convertRect:aKeyboardFrame fromView:nil];
CGFloat adjustedHeight;
adjustedHeight = aKeyboardFrame.size.height + self.focusControlBar.frame.size.height;
[self.focusControlBar viewForFocusControlWillShowWithEndFrame:adjustedKeyboardFrame animationCurve:aKeyboardAnimationCurve andAnimationDuration:aKeyboardAnimationDuration];
[UIView animateWithDuration:0.3 animations:^() {
[self.tableView setContentInset:UIEdgeInsetsMake(kScreenOrigin, kScreenOrigin, adjustedHeight, 0.0f)];
[self.tableView setScrollIndicatorInsets:UIEdgeInsetsMake(kScreenOrigin, kScreenOrigin, adjustedHeight, 0.0f)];
}];
}
- (void)viewForFocusControlWillShowWithEndFrame:(CGRect)iFrame animationCurve:(UIViewAnimationCurve)iAnimationCurve andAnimationDuration:(CGFloat)iDuration {
BOOL aShouldAppear = YES;
if (self.delegate && [self.delegate respondsToSelector:#selector(focusControlBarShouldAppear:)]) {
aShouldAppear = [self.delegate focusControlBarShouldAppear:self];
}
if (aShouldAppear) {
if (self.delegate && [self.delegate respondsToSelector:#selector(focusControlBarWillAppear:)]) {
[self.delegate focusControlBarWillAppear:self];
}
CGRect aBarFrame = self.frame;
UIInterfaceOrientation anInterfaceOrientation = [UIApplication sharedApplication].statusBarOrientation;
aBarFrame.size.height = [self heightForOrientation:anInterfaceOrientation];
self.frame = aBarFrame;
aBarFrame.origin.y = self.superview.bounds.size.height - iFrame.size.height - aBarFrame.size.height;
[UIView animateWithDuration:iDuration delay:0.0 options:(iAnimationCurve << 16) animations:^{
self.frame = aBarFrame;
} completion:^(BOOL finished) {
if (self.delegate && [self.delegate respondsToSelector:#selector(focusControlBarDidAppear:)]) {
[self.delegate focusControlBarDidAppear:self];
}
}];
}
}
I'm trying to flip animate a view into another view, which corresponds of a small section of the screen. Both views have the same dimensions and center.
I keep getting as a result the animation of the full screen. From the code below, can somebody please let me know what the heck i'm doing wrong?
Thank you,
-j
+ (void) flipView:(UIView*)viewA toView:(UIView*)viewB wait:(Boolean)wait
{
// get parent view
UIView *parent = [viewA superview];
CGRect r = viewA.frame;
// create container view with the same dimensions as ViewA
UIView *containerView = [[UIView alloc] initWithFrame:viewA.bounds];
containerView.center = viewA.center;
// attache both views to intermidiate view
[containerView addSubview:viewA];
[containerView addSubview:viewB];
[viewA removeFromSuperview];
[parent addSubview:containerView];
viewB.alpha = 0;
viewA.alpha = 1;
// Perform the annimation
__block BOOL done = NO;
[UIView transitionWithView:viewA
duration:2.0
options: (UIViewAnimationOptionTransitionFlipFromTop)
animations:^{
viewA.alpha = 0;
viewB.alpha = 1; }
completion:^(BOOL finished) {
done = YES;
// detach all views
[viewA removeFromSuperview];
[viewB removeFromSuperview];
[containerView removeFromSuperview];
}
];
if(wait) {
while (done == NO)
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
}
}
First get rid of the old animation code (or at least commit it), it should look like this:
+ (void) flipView:(UIView*)viewA toView:(UIView*)viewB wait:(BOOL)wait
{
viewB.alpha = 0;
viewA.alpha = 1;
__block BOOL done = NO;
[UIView transitionWithView:viewA
duration:2.0
options: (UIViewAnimationOptionTransitionFlipFromTop)
animations:^{
viewA.alpha = 0;
viewB.alpha = 1; }
completion:^(BOOL finished) {
done = YES;
}
];
if(wait) {
while (!done)
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
}
}
Second, the superview of the subview that you want to transition is actually going to get the transition. So this means that you'll have to add viewA and viewB to a subview, add this subview to another view and then do the animation.
Here is a solution without any hacks with runloop. Just use the first message to run a transition to another view, and the second message to return to original state:
- (void) forwardTransitionFromView: (UIView *) viewA toView: (UIView *) viewB
{
NSAssert(viewA.superview, #"The 'from' view should be added to a view hierarchy before transition");
NSAssert(!viewB.superview, #"The 'to' view should NOT be added to a view hierarchy before transition");
CGSize viewASize = viewA.bounds.size;
viewB.frame = CGRectMake(0.0, 0.0, viewASize.width, viewASize.height);
[UIView transitionWithView:viewA
duration:1.0
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
[viewA addSubview:viewB];
}
completion:NULL];
}
- (void) backwardTransitionFromView: (UIView *) viewB toView: (UIView *) viewA
{
NSAssert([viewB.superview isEqual:viewA], #"The 'from' view should be a subview of 'to' view");
[UIView transitionWithView:viewA
duration:1.0
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
[viewB removeFromSuperview];
}
completion:NULL];
}
Why dont you flip both views in same direction?
-(void) FlipView:(bool) fromRight {
if(fromRight) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.75];
[UIView setAnimationDelegate:self];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:view1 cache:YES];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:view2 cache:YES];
[UIView commitAnimations];
}
else {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.75];
[UIView setAnimationDelegate:self];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:view1 cache:YES];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:view2 cache:YES];
[UIView commitAnimations];
}
}
and call the method like below:
[view1 setHidden:NO];
[self FlipView:YES];
[view2 setHidden:YES];
to reverse the animation:
[view2 setHidden:NO];
[self FlipView:NO];
[view1 setHidden:YES];