Custom animation when switching tab/viewcontroller in UITabBarController - animation

I'd like to make a UITabBarController tab switching animation similar to pop and push animation of navigation controller.
That's means if I select a tab at the left of the current tab, the view of new viewcontroller move into the screen from the left, and the view of old/current viewcontroller move out of screen to the right (similar to pop).
I can only achieve this at the moment but I don't know how to implement slide in/out effect.
Thank you!
-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController:
UIView *fromView = tabBarController.selectedViewController.view;
NSInteger fromIndex = tabBarController.selectedIndex;
UIView * toView = [viewController view];
NSInteger toIndex = [[tabBarController viewControllers] indexOfObject:viewController];
[UIView transitionFromView:fromView
toView:toView
duration:0.3
options:UIViewAnimationOptionTransitionCrossDissolve
completion:^(BOOL finished) {
if (finished) {
tabBarController.selectedIndex = toIndex;
}
}];
}

Related

"Bottom NSView's" button border line still appears in the "top NSView" after top View is presented

I'm working on a "Mac OSX App" that has two view controllers, the app starts from the first view (bottom view) and later "Canvas view controller (top view)" is presented from the first view controller.
After presenting "CanvasViewController (top view)",
CanvasView appears correctly with its buttons on the top of bottom view however the border line of the button of the bottom view still appears. I have attached the images of the bottom and top views below.
It doesn't look like alpha value issue as it is set to 1.0, instead it is related to some things else in the viewController settings (ie. first responder or button state, etc).
How can I remove this bottom view's button border line when the top view is presented on the top?
Any solutions or helpful comments will be much appreciated. Thanks in advance.
// From bottom view's viewController
#interface MainMenuViewController : NSViewController
#end
#implementation MainMenuViewController
...
-(IBAction)presentNextViewWithAnimator:(id)sender{
id animator = [[MyCustomAnimator alloc] init];
CanvasViewController* viewController = [[CanvasViewController alloc] initWithNibName:#"CanvasViewController" bundle:nil];
// presenting "topView" with custom animator
[self presentViewController:viewController animator:animator];
}
...
#end
// From "top view's viewController"
#interface CanvasViewController : NSViewController
#end
#implementation CanvasViewController
...
// "close" button
-(IBAction)closeCanvas:(id)sender{
[self dismissViewController:self];
}
// "refresh" button
-(IBAction)refreshCanvas:(id)sender{
}
...
#end
// From the view presentation's custom animator
#interface MyCustomAnimator : NSObject <NSViewControllerPresentationAnimator>
#end
#implementation MyCustomAnimator
-(void) animatePresentationOfViewController:(NSViewController *)viewController
fromViewController:(NSViewController *)fromViewController
{
NSViewController* bottomVC = fromViewController;
NSViewController* topVC = viewController;
topVC.view.wantsLayer = YES;
topVC.view.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay;
topVC.view.alphaValue = 1.0f;
[bottomVC.view addSubview:topVC.view];
CGRect frame = NSRectToCGRect(bottomVC.view.frame);
[topVC.view setFrame:NSRectFromCGRect(frame)];
topVC.view.layer.backgroundColor = [NSColor whiteColor].CGColor;
[NSAnimationContext
runAnimationGroup:^(NSAnimationContext * context){
context.duration = 0.5f;
topVC.view.animator.alphaValue = 1.0f;
} completionHandler:nil];
}
...
#end

xcode UITapGestureRecognizer on scrollview not calling until second tap

I have the following code to dismiss the keyboard if the user taps the background. It works fine if the scrollview is in the PointZero position, but if the user scrolls the view and then selects the textview, it doesn't call the "dismissKeyboard' method until the 2nd background tap.
On the first tap (for some reason) moves the scrollview offset to align with the scrollview frame to the screen bottom. The second tap will dismiss the keyboard and run the code below. I know it has to do with the scrollview. Any help would be appreciated.
Thanks
- (void)viewDidLoad {
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)];
tapGesture.cancelsTouchesInView = NO;
[_scrollView addGestureRecognizer:tapGesture];
}
-(void)dismissKeyboard {
[self.view endEditing:YES];
}
- (void)keyboardWasShown:(NSNotification *)notification {
scrollViewRect = _scrollView.contentOffset.y;
NSDictionary* info = [notification userInfo];
CGSize keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
keyboardSize.height += 10;
CGFloat viewBottom = CGRectGetMaxY(self.scrollView.frame);
if ([_itemNotes isFirstResponder]) {
CGFloat notesBottom = CGRectGetMaxY(_itemNotes.frame);
viewBottom -= notesBottom;
if (viewBottom < keyboardSize.height) {
keyboardSize.height -= viewBottom;
CGPoint scrollPoint = CGPointMake(0.0, keyboardSize.height);
[self.scrollView setContentOffset:scrollPoint animated:YES];
}
else {
[self.scrollView setContentOffset:CGPointZero animated:YES];
}
}
else {
[self.scrollView setContentOffset:CGPointZero animated:YES];
}
}
- (void)keyboardWillBeHidden:(NSNotification *)notification {
CGPoint scrollPoint = CGPointMake(0.0, scrollViewRect);
[self.scrollView setContentOffset:scrollPoint animated:YES];
}
EDIT:
So I figured out a solution but it seems like there must be a better way to handle this. The problem was because I was setting the contentOffset of the scrollView so that the contentSize was beyond the screen boundaries. Thus the first tap was moving the scrollView contentOffset back within the screen boundaries and the second was performing the tap gesture. I will post my solution below hoping that someone has a better answer.
I would recommend setting
_scrollView.layer.borderColor = [UIColor redColor].CGColor;
_scrollView.layer.borderWidth = 1;
This will show you exactly where your scrollview boundaries are, which may not be where you think they are, or may be covered by something else. Also, when I open the keyboard, I generally set the scrollview frame bottom to the top of the keyboard. Otherwise, you may have content below the keyboard you can't get to. Not sure if this is exactly related to your issues.
I am assuming there must be a better solution to this but I was able to solve the issue by extending the contentSize when the keyboard is displayed and then shrinking it back down when the keyboard is hidden.
Set a float (scrollViewHeight) to hold the original content size for the reset.
//add this right before setting the content offset
scrollViewHeight = _scrollView.contentSize.height;
_scrollView.contentSize = CGSizeMake(_scrollView.frame.size.width , scrollViewHeight + keyboardSize.height);
//add this right before reseting the content offset
_scrollView.contentSize = CGSizeMake(_scrollView.frame.size.width , scrollViewHeight);
It really seems like there must be a better way that I'm not aware of. I will have to go back through the documentation to see if there is another way.

Display Image To Extend Splash Screen Using Storyboards in iPhone SDK

I have this app that has tabs and each tab's root view controller is a navigation controller. I want to display my splash screen or launch image while the app is busy parsing JSON and loading it up in my core data stack and remove it from superview using a fade out animation. I tried this code to make it work but I'm stuck since the image is only displayed on the view inside the navigation controller. What I wanted is to view it full screen with the status bar on top like what you see when launching an app.
_launchImageView = [[UIImageView alloc] initWithFrame:[UIScreen mainScreen].bounds];
if (kFourInchDevice) {
_launchImageView.image = [UIImage imageNamed:#"Default-568h#2x.png"];
}
[self.view addSubview:_launchImageView];
[self.view bringSubviewToFront:_launchImageView];
And this is my code when dismissing it:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationTransition:UIViewAnimationTransitionNone forView:self.view cache:YES];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(launchImageFadeAnimationDidFinished)];
_launchImageView.alpha = 0.0;
[UIView commitAnimations];
- (void)launchImageFadeAnimationDidFinished
{
[_launchImageView removeFromSuperview];
}
Any ideas on how to do this? Thanks!
I think you are having problem of hiding NavBar in splash screen isnt it ?
Just Add one extra ViewController in your story board.
Then under Utilities ( left side bar ) under Attribute Tab - View Controller make VC initial View Controller.
Call following in your View Did Load
- (void) hideNavBar {
UINavigationBar *navBar = self.navigationController.navigationBar;
navBar.hidden = TRUE;
}
Then when you you finish your json parser -
#pragma mark - Delegates
#pragma mark JSON Request
-(void) connectionReady; {
NextVC *viewController = [self.storyboard
instantiateViewControllerWithIdentifier:#"NextVC"];
[self.navigationController pushViewController:viewController
animated:YES];
}
Then finally in NextVC
- (void) showNavBar {
UINavigationBar *navBar = self.navigationController.navigationBar;
navBar.hidden = FALSE;
}

Programmatically add a close button to an NSWindow

I'd like to add a close button to an NSWindow programmatically. I can get the button to display, but there are no mouse-over or mouse-down effects. My "selector" never seems to get called when i click the button. I'm not really sure whats wrong and why this is so annoying.
Here is what I've been messing with:
closeButton = [NSWindow standardWindowButton:NSWindowCloseButton forStyleMask:self.styleMask];
NSView *themeFrame = [[self contentView] superview];
NSRect c = [themeFrame frame]; // c for "container"
NSRect aV = [closeButton frame]; // aV for "accessory view"
NSRect newFrame = NSMakeRect( c.size.width - aV.size.width - 5, // x position c.size.height - aV.size.height - 5, // y position aV.size.width, // width aV.size.height); // height
[closeButton setFrame:newFrame];
[themeFrame addSubview:closeButton];
[closeButton setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin];
[closeButton setEnabled:YES];
[closeButton setTarget:self];
[closeButton setAction:NSSelectorFromString(#"testClick:") ];
Where "testClick" is just a memeber function of my class and is defined as such:
- (void)testClick:(id)sender
The problem seems to be the call to:
[themeFrame addSubview:closeButton];
where the themeFrame is: [[self contentView] superview] Just adding the button to [self contentView] works, but I'd like it added to the titlebar.
No Interface Builder please...
Potential issue # 1)
The way you're calling "NSSelectorFromString" seems incorrect to me. I don't think you can pass parameters via this way in Objective C.
Try this:
[closeButton setAction: #selector(closeWindow:)];
and create a new "closeWindow:" action that looks like:
- (void) closeWindow: (id) sender;
which closes the window.
Potential issue # 2)
Instead of:
closeButton = [NSWindow standardWindowButton:NSWindowCloseButton forStyleMask:self.styleMask];
NSView *themeFrame = [[self contentView] superview];
Why not use:
NSWindow * parentWindow = [[self contentView] window];
if(parentWindow)
{
closeButton = [parentWindow standardWindowButton:NSWindowCloseButton forStyleMask:self.styleMask];
}

how to do animated transition between different UIViewControllers within a UITabBarController?

I have a UITabBarController,displaying 4 tabs.
I want to add an animated UIViewController transition when user swiping screen to switch tab. (- (void)tabBarController:(UITabBarController *)theTabBarController didSelectViewController:(UIViewController *)viewController method only work for select tab directly). transition will be in easeinout style.
I tried following codes but not work. only coming UIViewController moves, going UIViewController doesn't show at all.(I printed all UIViewControllers' frame data, all these 4 UIViewControllers are {0,0},{320,480} )
// Get views. controllerIndex is passed.
UIViewController *fromVC = [_tabBarController.viewControllers objectAtIndex:startIndex];
UIViewController *toVC = [_tabBarController.viewControllers objectAtIndex:to];
UIView *fromView = fromVC.view;
UIView *toView = toVC.view;
MWLog(#"from view is %#",fromView);
int direct = startIndex - to;
// calculate move direction.
if (direct < 0) {
CGRect outFrame = fromView.frame;
outFrame.origin.x = -320; // expect fromView will move to {-320,0}, out of screen.
MWLog(#"fromView's frame is %#", NSStringFromCGRect(fromView.frame));
CGRect inFrame = toView.frame;
inFrame.origin.x = 0;
MWLog(#"toView's frame is %#", NSStringFromCGRect(toView.frame));
[UIView beginAnimations:#"moveView" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.5f];
toView.frame = inFrame;
fromView.frame = outFrame;
[UIView commitAnimations];
}else
{
// reverse moving. ignored....
}
Could you tell me what's wrong and how to do it correctly? thanks in advance!
finally I found the solution.
use CATransition animation, type push, type left or right depending on direction(by calculating tabbarcontroller's selectedIndex property). then, add this animation to tabbarcontroller's container view.
This view's reference can be got by enumerate all UIViews in [tabbarcontroller subviews] array. Actually, if no custom UIView, tabbarcontroller contains 2 subviews, one is UITabBar, the other is the container view, UITransitionView. Add animation on this view, you can enable page transition animation for different content screen.

Resources