I want to display a UIViewController this way, that is: an upper viewcontroller slides out with a left-to-right animation and the lower one displays. Then, when you click the left button, this viewcontroller covers the other one again.
This is a very common UX pattern and I see lots of people doing it with third party components (eg. SWRevealViewController).
The question is: if I don't want to do it with a third party library, how can I do it?
IMO: Apple has stated that it's more of a design anti-pattern and appeal to popularity shouldn't be considered a good argument for this kind of design.
What you're looking for is a UIViewController containment and transitioning. Create a UIViewController class that accepts a, say, menuViewController (the lower one in your case) and an array of view controllers that can be displayed by tapping menu items.
Grab all the titles from the collection of view controllers and display them in menu view controller. Next by tapping the items in menu just use
- transitionFromViewController:toViewController:duration:options:animations:completion:
method for animating the transition between chosen view controllers.
It not so trivial to make, that's why people suggest to use some 3rd-party library.
But basically you want to create container view controller, add there your menu and main view controller above it and handle gesture recognition.
Related
(I have read other questions and answers on this topic, but most are very old and do not relate to iOS 9 or 10.)
The app design calls for the top half of the display to always contain the same content. (An image being edited by the user.)
The bottom half of the display needs a UITableView. When a UITableViewCell is tapped, the bottom section needs to transition to a new UIViewController with slide-on animation, similar to how UINavigationController push segues work.
Problem: only the bottom view needs to transition to the new view controller(s), and back again. The upper half of the view hierarchy needs to remain unaffected. For this reason, I can't place everything inside a UINavigationController, and I can't have a UINavigationBar at the top of the screen.
Question: what approach should I take in such a situation, where I need only one UIView hierarchy to transition in push-segue fashion, but not anything else? Thanks.
Edited with Solution
Solution follows, for those following along at home.
Yes, you can actually use a UINavigationController for the bottom half.
If you are using Storyboards, the easiest way to do this is to use a container view for each part of the screen which you then can embed a UIViewController in for the top part and a UINavigationController in for the bottom part. If you are doing this programmatically, just add the view controllers as child view controllers to your app's initial view controller (see this answer for more info) which is essentially what the Storyboard will do for you automatically when using a container view.
As a child view controller, the UINavigationController will act independently from the top UIViewController and should behave as expected.
I recommend the programatic approach for the following reasons:
It helps you understand the inner workings of child/parent view controllers much better which will likely save you a significant amount of debugging time down the line.
It makes adding/removing/swapping child view controllers as simple as a few lines of code. Trying to do this with Storyboards is notoriously hacky and cumbersome.
It's much easier to keep track of changes using GIT (most mid-size/larger companies actually prohibit Storyboards for this very reason)
If you want change in part of the screen you can use container view. For details refer Swift - How to link two view controllers into one container view and switch between them using segmented control?
You can use multiple view in one view controller and can give animation like push or pop to show or hide it.
Second approach is you can use Container View which will give exact effect like navigation stack.
Basically what I want to do is depicted in the image below:
However this only loads the middle and third interface, the first is hidden both from swiping onto and in the circle indicators at the bottom.
I'd like to be able to load the second interface and swipe left for the first and swipe right for the third. Is there a way to achieve this?
Building my first Apple Watch app over here :)
Looks like there is a concept of UINavigationController-ish behaviour built into the WKInterfacesController.
Take a look at: pushControllerWithName(_:context:)
And from some docs I found here:
Hierarchical. This style is suited for apps with more complex data models or apps whose data is more hierarchical. A hierarchical interface always starts with a single root interface controller. In that interface controller, you provide controls that, when tapped, push new interface controllers onto the screen.
EDIT:
Looking into this some more. WatchKit is currently very limited by the looks.
The best solutions I could come up with was to add the three InterfaceController, with segues is between. Left -> Main -> Right.
Then assign a custom SKInterfaceController for Main:
class InterfaceController: WKInterfaceController {
override init() {
super.init()
becomeCurrentPage()
}
}
This creates an annoying animation in the beginning where you will see "Left" on start and how "Main" is animated pushed in. I don't see any better way to do this at this early stage of WatchKit.
The placement of the ViewControllers have no real "physical" meaning.
A segue (the arrows) simply defines a way to navigate from "this" ViewController to another one.
http://www.raywenderlich.com/81880/storyboards-tutorial-swift-part-2
It is possible to create as many segues from one ViewController to other ViewControllers as needed. You can name these segues, and trigger the one you want from storyboard send events or code for specific events (like swipe gestures).
To get the animation of actually sliding the view to the left would require a custom transition:
http://mathewsanders.com/animated-transitions-in-swift/
I would like to make similar effect that Facebook app has. So I would like to create navigation slide-out effect.
But when I place UIViewController with menu beneath parent UIViewController with content and then I move parent view aside my menu doesnt show up. Everything I can see is black screen. But menu frame is in the right position.
Any sugestion what should I do?
Content view will be separate UIViewControllers.
I was in the same situation than you and finally I used a custom class which is inspired on FaceBook and Wunderlist apps and is really simple to add into the project:
https://github.com/John-Lluch/SWRevealViewController
The child view controller is always above parent view controller's view.
I think the old and the new view controllers should be siblings and use a parent view controller to add them both.
In fact, the child controllers of native UINavigationController are siblings rather than child-parent relationship.
I would urge you not to do this on your own but to use one of the many libraries out there that have been heavily tested by many contributors. One of the good ones is MMDrawerController but there are many others. Take a look at cococontrols for many more examples.
I've previously implemented a similar mechanic to this using custom transitions, which were introduced in iOS7. For example: could present the menu modally, but using a custom transition have it appear from the left and only take up a proportion of the screen.
Using custom interactive transitions will also allow you to use a pan gesture recogniser to drag your main view controller back on top of your menu - like in the Facebook app.
Here's a good tutorial on Custom Transitions: http://www.thinkandbuild.it/ios7-custom-transitions/
There's a particular control which I'm trying to build properly. I refer to it as an ImageTile. It's basically a little square box, which, when the user taps it, will present the user (via an action sheet in a popover) the option of selecting an image from the library, or taking a photo. Depending on the response, I then either present the UIImagePickerController inside a popover (for selecting an image) or modally (for taking a new picture). Once they take/select the image, I have a modal view which appears and allows them to edit the picture in a few simple ways. When they finish editing, the modal dismisses, and the original ImageTile, rather than being a blank square box, gets filled up with the user's edited image.
The issue is that this ImageTile control is going to be used profusely throughout several different parts of the application, across numerous View Controller hierarchies, and so on... and I really want it to be a basically totally self-contained unit, such that whenever I stick an ImageTile inside a UIView onscreen, all the above functionality is handled by the ImageTile itself.
Initially, I made it a UIViewController subclass (so it could present modals etc), and just added its view as a subview of a "holder" view onscreen. I know this isn't recommended, as the controller isn't part of the VC hierarchy then... and also, I wound up with some really weird behavior regarding things like autorotation, especially when the camera was involved.
What's the "right" way to implement something like this?
I think what you've done by making it a UIViewController subclass is correct. You should just use the methods that UIViewController exposes for adding child view controllers, such as - addChildViewController:.
You will also note that Interface Builder has a Container View object designed specifically for holding a place in the hierarchy for a child View Controller:
I have a UIViewController having two parts:
a UIView
a bar having multiple drop down menus arranged horizontally and having thumbnail images at the top
Because second part is little complex I've decided it to be a UIViewController but now I have some concerns:
Because I have drop down menu, menu will exceeds the bounds of the bar. How can I handle it?
Is it a good way to have a UIViewController inside a UIViewController?
How can I implement a drop down menu? As far I know IOS doesn't have drop down menus.
To use a controller within another controller, you employ a custom container view controller.
See Creating Custom Container View Controllers section of the View Controller Programming Guide for iOS.
Also see the appropriate Implementing a Container Controller section of the UIViewController Class Reference.
Also refer to the WWDC 2011 video, Implementing UIViewController Containment
In iOS 6, you can set up storyboards with container views that automatically employ embed segues, saving you from needing to explicitly call addChildViewController and the like, if you're using storyboards. Check out the "container view" object in Interface Builder. If you're going to be changing the child controller, you'll have to employ the API referred to in the above links, but for the configuration of the first child, you can set that up in Interface Builder in iOS 6.
In this case, setting up a controller containment could be the right way. The only limitation is that it works for iOS 5 and greater.
Here, what you have to do:
// add as child VC
[self addChildViewController:_barViewController];
// add it to container view, calls willMoveToParentViewController for us
[_containerView addSubview:_barViewController.view];
// notify it that move is done
[_barViewController didMoveToParentViewController:self];
Here, you can find additional info Containing ViewControllers. Obviosly Apple doc is your friend. In addition, if you search for "uiviewcontroller containment" you can find a lot of tuts out there.
If your app needs to target devices where iOS 5 is not the minimum, you should rely on a UIViewController and two different views.
About drop down menus, in my opinion they don't work so well with touch interfaces. There are some alternatives, for example an instance of the UISegmentedControl class. Here you can read Apple UI design guidelines about segmented controls: http://developer.apple.com/library/ios/#documentation/userexperience/conceptual/mobilehig/UIElementGuidelines/UIElementGuidelines.html#//apple_ref/doc/uid/TP40006556-CH13-SW1. If you explain a little bit more about your desired UI functionality we could offer you a better alternative from the user experience point of view.
If you insist with drop down menus, there are some third party control libraries available out there; for example: http://www.cocoacontrols.com/