Switching to another UIView, within TabBar - cocoa-touch

Here is my app setup.
TabBar App with three tab items, tabs 2 and 3 are irrelevant
The TabBarController is located within MainWindow.xib
In interface builder for MainWindow.xib, within the TabBarController
i have the seperate viewControllers for each tab.
Then a view for each view controller underneath ( this can been seen when viewing the object in list view)
The application loads and displays the first tab.
I want to be able to have a button in the view of the first tab that can be clicked that will then animate the following:
the current view fading out
a new view fading in within the SAME tab.
Would the new view require a new viewcontroller or just an additional view under the view controller? or can i create a new view controller and load that with its view?
how would i go about this? just the method is needed.
How would i go about this? Thanks
EDIT
my interface builder list looks like this
Where should i place this new view?

You don't need the additional view controller. Just add additional view in current controller's view and that will be good enough. When user touch up on button make animation that will adjust transparency of views for desired duration. After animation is finished set transparent view as hidden so it won't capture the user actions.
#interface NewsletterViewController {
IBOutlet UIView *view1;
IBOUtlet UIView *view2;
}
In interface builder, add this views to NewsletterViewController->View and connect them with these outlets.
Some code for animation setup:
[UIView beginAnimations: #"Fade" context: nil];
[UIView setAnimationDuration: 0.5];
[UIView setAnimationDelegate: self];
[UIView setAnimationDidStopSelector: #selector(onFadeFinished)];
view1.alpha = 0;
view2.alpha = 1
[UIView commitAnimations];

Related

Add, remove subview and communicate between subview and main uiviewcontroller

I have created two uiviewcontrollers in storyboard. I am adding second UIview as a subview to 1st view when a button is pressed.
Now, my subview has a done and cancel button, which upon been touched, the subview has to be removed from the main view and needs to send some data back to main view. Is using delegates the only way to solve this? Please explain if there is any other simpler or better option.
Thank you :)
It sounds like the question is just about subviews of the 1st view controller's view. In that case, the 1st view controller can directly inspect all of them. i.e. Say the data that you'd like "passed" between views is the text of a UITextField contained on the subview.
You have an outlet to the subview, probably painted in IB?
// MyViewController.m
#property(weak, nonatomic) IBOutlet UIView *subview; // self.view is it's parent
Create an outlet that connects to whatever subviews you want data from:
#property(weak, nonatomic) IBOutlet UITextField *textField; // probably, subview is it's parent
Hide and show the "dialog":
self.subview.alpha = 0.0; // to hide (alpha is better than 'hidden' because it's animatable
self.subview.alpha = 1.0; // to show
When the button is pressed:
- (IBAction)pressedDoneButton:(id)sender {
self.subview.alpha = 0.0;
// or, prettier:
[UIView animateWithDuration:0.3 animations:^{ self.subview.alpha = 0.0; }];
// the text field still exists, it's just invisible because it's parent is invisible
NSLog(#"user pressed done and the text that she entered is %#", self.textField.text);
}
The point is that data is not being passed between views. The view controller has pointers to views. Some, like buttons generate events for the view controller to react to. Others carry data that the view controller can see.

AutoLayout won't resize view when rotating in a custom container view?

I have a very basic container view that contains a sidebar and swaps out the view controllers in the content area (think UISplitView but with a small icon sidebar / vertical UITabBar).
The container view controller uses autoLayout and resizes correctly when rotated.
Content viewController 1 uses autolayout and was made with IB, so it has a xib file.
Content viewController 2 inherits from UITableViewController and does not use a xib.
If I assign viewController 1 as the root view controller and rotate, the resize works and here are the callbacks that I get in viewController 1:
willRotateToInterfaceOrientation
updateViewConstraints
viewWillLayoutSubviews
didRotateFromInterfaceOrientation
However, if I assign my container view controller as the root view controller, load viewController 1 and rotate, the resize does not work. And I only get the following callbacks inside viewController 1:
willRotateToInterfaceOrientation
didRotateFromInterfaceOrientation
Inside my view controller container, here's how I swap the view controllers:
[self addChildViewController:toViewController];
[toViewController didMoveToParentViewController:self];
// Remove the old view controller
[fromViewController willMoveToParentViewController:nil];
[fromViewController.view removeFromSuperview];
[fromViewController removeFromParentViewController];
// Add the new view
[self.contentContainerView addSubview:toViewController.view];
Now, I do get the callbacks that a rotation is about to happen, but it seems as if neither updateViewConstraints nor viewWillLayoutSubviews is called. This explains why the resize is not happening, but why are those methods not called once I put the view controller in a container view?
I also tried to explicitly return YES in my container on both
shouldAutomaticallyForwardAppearanceMethods
and
shouldAutomaticallyForwardAppearanceMethods
although this should be the default already.
Also, the view controller not made with IB (view controller 2) resizes correctly when rotating inside the container. However, I don't explicitly use NSLayoutConstraints on this one, so I suspect it's defaulting to Springs and Struts for the resizing when rotating.
Do I need to forward some other events on my view controller container to get the auto layout view controller to resize correctly when rotating?
OK, I think I was missing this method here in my view controller container:
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
self.contentViewController.view.frame = self.contentContainerView.bounds;
}
While this resizes now correctly when rotating, it still doesn't trigger
updateViewConstraints
in my child view controller. Interesting
Seems like iOS 8 does call updateViewConstraints for you. But iOS 7 didn't. To get this called in iOS 7, call setNeedsUpdateConstraints, like this:
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
[super willAnimateRotationToInterfaceOrientation:interfaceOrientation duration:duration];
BOOL isiOS7 = floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1;
if (isiOS7) {
// Trigger a call to updateViewConstraints
[self.view setNeedsUpdateConstraints];
}
}
In updateLayoutConstraints, a good way to check which orientation is the one to layout for is to check the status bar's orientation. This works for 7 and 8.
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
BOOL layoutAsLandscape = UIInterfaceOrientationIsLandscape(orientation);

Autolayout with custom segues

I am attempting to cross-dissolve between two view controllers with a custom segue, the segue initiates properly and performs the animation as intended - however when in landscape mode the destination view controller appears in its portrait layout for the duration of the animation. Once the animation completes the destination view controller "snaps" to its landscape layout. Both of the view controllers are set up using auto layout.
Below is my custom segue's "perform" method:
- (void)perform
{
UIViewController *srcController = self.sourceViewController;
UIViewController *dstController = self.destinationViewController;
dstController.view.transform = srcController.view.transform;
[UIView transitionFromView:srcController.view
toView:dstController.view
duration:self.animationDuration
options:self.animationOptions
completion:self.animationCompletionBlock];
}
Is it necessary to manually tell the destination view controller to trigger autolayout before it is displayed? And if so how would this be performed? Using the built-in segue with a cross-dissolve does not appear to encounter this problem, I have attempted (without success) to determine what it is doing that my custom segue is not.
This has had me stumped for a while, any help would be appreciated and please let me know if more details are needed.
So it turns out that the solution to this problem was more simple than I would have imagined. Adding the following line ensures the destination view controller has the right bounds when it lays out its elements:
dstController.view.bounds = srcController.view.bounds;
So the rest of the code becomes:
- (void)perform
{
UIViewController *srcController = self.sourceViewController;
UIViewController *dstController = self.destinationViewController;
dstController.view.transform = srcController.view.transform;
dstController.view.bounds = srcController.view.bounds;
[UIView transitionFromView:srcController.view
toView:dstController.view
duration:self.animationDuration
options:self.animationOptions
completion:self.animationCompletionBlock];
}

Is it possible to display two views at the same time without switching option in view based application?

I am new to iOS programming and Xcode. I am doing a painter application via View based application in Xcode. Here I am going to draw in mainview and customize the settings in new view by click a button which is in mainview.
Whenver I click the button in mainview, it want to display a customize view in the mainview. mainview shouldnot be hidden. Customize view, it just a small view which display in mainview itself.
How can I do this?
Use like -
// Action on click of button -
UIView *newView = [[UIView alloc] initWithFrame:CGRectMake(xpos, yPos, width, height]; //pass these values whatever you want
[mainView addSubView:newView];
// Now when you want to remove this -
[mainView removeFromSuperView:newView];

How can I load a UIView from the same NIB (stems from a UITabController)?

So I have a UITabViewController from which a UIViewController (FirstViewController) is loaded (for the first tab button) and I want a button (calcbutton) to open a UIView (calculateview) from within the same NIB of that initial UIView (bedtime)
So basically I want calculateview to animate in when calcbutton is pressed and eventually dismissed with the other "close" button. I have not yet declared or created the IBAction that would dismiss the second view.
Here's an Xcode Screenshot
I would go with a ModalViewController, but that will require moving your other UIView ( calbulateview) to that controller.
If that is not possible, you could still do it within your own view controller.
Use transitionFromView:toView:duration:options:completion:
Here is a short sample:
[UIView transitionFromView:bedtime
toView:calculateview
duration:1.0
options:UIViewAnimationOptionTransitionCurlUp
completion:^(BOOL finished) {
if (finished) {
// In case you need to do something once
// the animation is completed
}
}];
In options you could specify other types of transition animations.
I believe what you are looking for is a modal view controller.
This should explain what you need:
http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ModalViewControllers/ModalViewControllers.html