I have my navigation controller and my view controller. I can't seem to get a simple transition between those views when I push a button in the navigation bar. It now just pops up.
When I push the button in the navigation controller, it calls the code below in the main file.
public void GoToViewController()
{
window.AddSubview(theViewController.View);
}
I have been calling:
UIView.SetAnimationTransition(UIViewAnimationTransition.None, spct.View, true);
which works, but I would like to let this view simple appear from the right, over the other view (just like the navigation controller does with its views).
You should just use UINavigationController.
Making the transition should be fairly easy, and is worth it over trying to recreate what Apple has already built.
For each of your view controllers, you should be able to change their base class to UINavigationController--or just change their type to UINavigationController if you did not subclass them. After that, you should just have to replace your custom transition code to use PushViewController(), PopViewControllerAnimated(), etc.
Using UINavigationController is fairly simple in general.
Related
I have a View Controller that is presented when you first open the app, and I have another controller that can be shown on screen if you tap a button at the top of the screen. However, instead of doing it this way I was wondering if I can either drag the view down or tap the button and have an animation take care of that.
I have tried doing this with a PageView Controller, but this doesn't show the effect I wanted as it simply translates over to the next view and doesn't actually keep the initial view fixed in place while the second view slides over it.
Also, instead of a view controller would a view initially placed out of bounds in the main View Controller work? Thanks in advance!
You could use a side menu like MMDrawerController that has 4 type of animations for presenting the viewController.
Or you can create your custom UIView (not viewController) even using Interface Builder and animate that screen yourself. The animation can be started using UIScreenEdgePanGestureRecognizer.
I have a split view controller in landscape mode with two navigation controllers.
This collapses to a single navigation controller in portrait and the detail view controller is pushed from the master.
If I rotate back to landscape when the detail view controller is pushed in portrait I don't understand how to put the detail view controller back into it's own navigation controller.
You should implement UISplitViewControllerDelegate. Simplest way may be to have your own MySplitViewController class and set itself as a delegate in viewDidLoad:
self.delegate = self;
First, you may want showDetailViewController to look something like:
- (BOOL) splitViewController:(UISplitViewController*)splitViewController showDetailViewController:(UIViewController*)vc sender:(id)sender
{
if (splitViewController.collapsed)
{
[(UINavigationController*)splitViewController.viewControllers[0]) pushViewController:vc animated:YES];
}
else
{
self.viewControllers = #[ self.viewControllers.firstObject, vc ];
}
return YES;
}
That should take care of proper showing of details view in both orientations.
Next, you should implement following delegate method similar to this:
- (UIViewController*) splitViewController:(UISplitViewController*)splitViewController
separateSecondaryViewControllerFromPrimaryViewController:(UIViewController*)primaryViewController
{
UINavigationController* nc = primaryViewController;
UIViewController* detailVC = nc.viewControllers.lastObject;
return detailVC;
}
This method is your chance to take whatever you want from primary controller and return that as detail view controller. The example code above is rather simple one, you may need to traverse through navigation viewControllers and pick all starting from specific view controller (assuming you had pushes from details view).
Anyways, it would really payoff to take some time and read: UISplitViewController class reference and especially UISplitViewControllerDelegate Protocol Reference
This will be much clearer.
If you want a shortcut, take a look at Xcode split view controller template project. That one should also contain hint or exact solution for your problem.
Make the detail have its own navigation controller, like in the Master Detail template. When the split view collapses it calls showViewController on the master navigation controller and when it detects a controller of class UINavigationController it sets allow nested navigation controllers true and hides the navigation bar. This way you get to keep the detail navigation so when you rotate to landscape and separate it can use the existing navigation again.
I'm building a share extension for my iOS app and I can't use the default SLComposeServiceViewController, so I created (in the storyboard) a basic UIViewController and embedded in a navigation controller. I get to present it, dismiss it etc but it's always full screen. I would like to make it look more like a dialog.
I have tried using self.preferredContentSize on my view controller, tried Use Preferred Explicit Size on the navigation controller in Interface Builder, but it doesn't work.
This can be done easily and directly using the storyboard but is not immediately obvious. There is no need for multiple view controllers.
Create your own view controller class inheriting from UIViewController.
In the MainInterface.storyboard change the class of the view controller to your new class
In the storyboard you can simply draw your UI - but here is the trick. You need to understand that the storyboard view will fill the screen and by default the view has already been created with a clear background. You simply need to create a view inside of the main view. You can set auto layout constraints to size this view and position it (e.g. centered horizontally and vertically). You can also use size classes to cause this inner view to fill the screen on compact layouts. Connect the controls from the inner view to your view controller in the usual way by control-dragging
In you custom view controller you can refer to self.extensionContext to read and complete the share action. Refer to the code in the template ShareViewExtension
Ok I spent a long time trying to figure this out. For whatever reason you can't set the view size like you can with the action extension. It will always go full screen (even on iPad). So a way around this is to make multiple view controllers. Make the first view controller hidden so the user doesn't notice that there is a full screen view controller present (And yes, in a share extension the first hidden view controller actually hides completely so the user doesn't even know it was presented). Then present your actual view controller using the hidden view controller. This way you can present it any way you like and set the size etc.
In my case I actually made my hidden view controller have a UIEffectView so I can have a nice blur animation in the background and then present my actual view controller over it.
Here is a picture:
I have a bunch of UIViewControllers subclasses (let's call them MainForm, DetailForm, MoreMinorDetails). Basically the idea is that AppDelegate class instantiates MainForm, user presses some type of button on MainForm and DetailForm comes up. Then on a button on the DetailForm launches MoreMinorDetails. And of course, I should be able to go back down to the MainForm.
Note that there aren't any UINavigationController objects anywhere in sight.
What is the accepted pattern to move between UIViewControllers in a manner described above?
Or am I going about it in the wrong way?
I'll be happy with either XCode or MonoTouch based explanation.
You can use a UINavigationController and hide the navigation bar:
self.navigationController.navigationBar.hidden = YES;
Then in your button's action just push the next view controller:
-(void)buttonAction:(id)sender
{
NextViewController *nextViewController = [[NextViewController alloc] init];
[self.navigationController pushViewController:nextViewController animated:YES];
}
To go back, use
-(void)goBack
{
[self.navigationController popViewControllerAnimated:YES];
}
To go to a certain view controller (you have to know exactly when it was pushed onto the navigation controller's stack):
-(void)goToViewController
{
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
}
Or to pop to your root view controller
[self.navigationController popToRootViewControllerAnimated:YES];
This way, you will obtain the UINavigationController's functionality and keep all the space in the view.
AngryHacker,
My simple suggestion is to follow zoul one. I think the simplest way to achieve what you want it' to create a UINavigationController and use it as a containment controller for other controllers.
So, the way could be create a UINavigationController in the AppDelegate and set it as the rootViewController for your window. When you create a UINavigationController you can pass to it a root controller (in this case MainForm).
In MT it looks like the following (do not trust the code because I've written it by hand)
private UINavigationController navController;
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
navController = new UINavigationController(new MainForm());
window.RootViewController = navController;
window.MakeKeyAndVisible ();
return true;
}
Now, when you launch the app you will see the MainForm's view and will able to allow navigation among different controllers.
For example, within MainForm you can go to DetailForm like:
this.NavigationController.PushViewController(new DetailForm(), true);
The same applies within DetailForm to MoreMinorDetails.
To go one step back, for example from MoreMinorDetails to DetailForm use
this.NavigationController.PopViewControllerAnimated(false);
To go to the the root controller (MainForm) within DetailForm or MoreMinorDetails use
this.NavigationController.PopToRootViewControllerAnimated(false);
About the space, it's not a problem. I guess you have two ways. The first is to move the bar items you have created within the navigation controller bar. In each controller you can decide what buttons make visible or not. The second is to hide completely the navigation bar and use the button you've already created.
In both ways you can attach actions to these buttons and allow the navigation between controllers. Furthermore, if you choose the first you can also hide the back button for your navigation bar.
A simple note to take in mind is the following:
Since the navigation bar is unique for a UINavigationController, the bar will maintains its state for all the controllers you push in the navigation controller. To explain the concept suppose you have two controllers, say A and B. You first push A and in its ViewWillAppear method you hide a button. When you push B, the button still remains not visible. If you want to unhide the button in B, you can play with its ViewWillAppear method (like before) and so on...
If you don't want to play with UINavigationController you should take a look to new view controller containment functionality provided by UIViewController class. This applies only from iOS >= 5. You can obtain the same effect of UINavigationController mechanism but it could be more difficult to achieve.
Hope that helps.
I am developering in iOS 5.1 and is pretty happy with these methods in UISplitViewControllerDelegate
splitViewController:willHideViewController:withBarButtonItem:forPopoverController
splitViewController:willShowViewController:invalidatingBarButtonItem:
however, now I notice that these two methods will be only called when the device is rotating and thus the orientation changes. What I am trying to do is to segue(replace segue) my detail view controller to another one. In the new detail view controller, I will always hide the master view controller even in landscape and therefore I need the button.
Without the delegate being called of these two methods, how can I get the button?
If you are hiding your master view controller even in landscape (by means of split view controller delegate), the splitViewController:willHideViewController:withBarButtonItem:forPopoverController: will be called, so you can safely put your code there.