How can I synchronize custom transitions for multiple child view controllers? - ios

I have a container UIViewController (DuoContainerController) which contains two child controllers:
HeaderController - contains a label, and can change its height
BodyController - a normal UINavigationController
My goal is to perform custom interactive transitions between controllers in the BodyController, and have the HeaderController animate various properties (in this example height and label text) in sync with the transitions of the BodyController.
Controllers pushed onto the BodyController have a custom transition, which I am currently managing in DuoContainerController. For sake of simplicity, it's just a fade, but I would also like to know how to make individual subviews in each controller do something like transition in from the right when pushing and transition out to the bottom when popping.
I think I need to do something with UIViewControllerTransitionCoordinator, but the documentation is light, and I can't find any examples like what I'm trying to do here. It's not clear if it's meant for something like this, or just simple stuff like dismissing a decoration view.
I set up a skeleton project to test out this problem at the following link. It sets up three child controllers in the body, which perform an interactive fade transition.
https://github.com/GoldenJoe/TransitionTest
To recap, I want to do the following:
Change the HeaderController's height and text in sync with the child controller transitions.
Make the label for the child controllers translate in/out during the transition, rather than just make the entire view fade.
Bonus - Any architecture recommendations for delegation and animator implementation would be appreciated.

Related

Transitioning to an already contained UIViewController

I have a vertical UIScrollView with several 'cards', nested UIViewControllers (via container views), each with their own state. Some of these cards can be expanded to take up the entire screen (what I'd effectively consider a full view controller transition) and later collapsed back to its original size. Ideally, we'd be segueing into these views, but apparently, transitioning into an already displayed view controller triggers an assertion. I'm currently experimenting with just changing the parent UIScrollView's contentOffset and any given card's bounds property upon expand/collapse, but this is proving to be a bit of a p.i.t.a. from several angles.
Is there any way to utilize a proper UIViewController transition for this?
Is there any way to utilize a proper UIViewController transition for this?
Consider instantiating a new instance of the same type of view controller, configuring it with the same data, and transitioning to that instead. That way you don't have to mess around with removing the controller from the container and putting it back later.

Subclass UICollectionViewTransitionLayout for automatic UINavigationViewController transition animation

Is it possible to subclass UICollectionViewTransitionLayout to change the automatic (e.g. non-interactive) animation when pushing/popping a view controller onto/off a UINavigationController stack?
Apples documentation and some articles in the internet suggest it should be possible:
If you want to provide more than just a linear transition from the old to new layout over time, you need to subclass and provide the layout attributes for items yourself
…but I didn’t find a way yet.
I would like to use UICollectionViewController’s useLayoutToLayoutNavigationTransitions to push one collection view controller on top of another (using the same data source). The two view controllers use different subclasses of UICollectionViewLayout which I want to transition using custom UICollectionViewLayoutAttributes that need to be keyframed and modified by the transitionProgress.
I was hoping, just implementing collectionView:transitionLayoutForOldLayout:newLayout: would do the trick, but that method only is called when transitioning interactively.
The best way I could come up with for the pushing is to call startInteractiveTransitionToCollectionViewLayout:completion: on the UICollectionView and pushing the new view controller without animation in the completion handler. For popping the view controller I would hook into -viewWillDisappear: of the view controller and check for the current view controller in the stack; if it is not there, I could again perform startInteractiveTransitionToCollectionViewLayout:completion:
Somehow I guess there is a better way…

A permanent navigation bar with UI elements

Our app has some upper view, that is visible all the time.
This bar has a UITextField, UIButtons, side scroller, and segment control, and they are dynamic.
When you hit them, the view behind them(full screen) is changing.
I was thinking about navigation control, or tab bar, but seems that they can't have a text field and a scroller on them.
So my main thought was to create some COSTUM view of my own.
Question is , how can I create a view in storyboard, and add it as a constant view, than create some other views(+viewcontrollers) that will be changed according to that upper bar?
I want to create 5 views in storyboard, and switch between them according to the bar.
Sounds like a job for a containment view controller to me. I've used technique many times to both create a set of static controls on the screen which you describe and inject reusable content into an app in several locations.
The basic concept is:
Setup you Heads Up Display(HUD) with all the UI you want (this will be your base UIViewController).
Create a UIView in it and call it your contentView or something of the like. This is where all your dynamic content will appear.
Then your backing view controller adds another UIViewController as a child and tell it to show it's view in the contentView you specified.
Your view controller continues to remove and add children putting their content into the contentView as needed.
If you are unfamiliar with the technique there are many tutorials(by NSCookbook) of do a web search for "view controller containment tutorial". There is also a good WWDC (2011) video introducing the concept Session 102 - Implementing UIViewController Containment.

Do I need a ViewController container or a composite view?

I need to implement an accordion control for iOS. By accordion, I mean a UI like this:
I see two basic ways to do this, but I'm not sure which one to choose.
Method #1: Create a ViewController container, something like a UITabBarController, except that instead of showing tabs at the bottom, I draw a vertical stack of buttons, and when you tap one, the corresponding panel opens and shows the corresponding view controller's view.
Method #2: Create a composite view, add a bunch of views directly to it, and show/hide them as needed.
How do I choose here? What would make me want to treat the sub-units as view controllers vs views?
Generally speaking, if I can avoid it I try not to subclass UIView and instead do everything within UIViewController subclasses. A controller is usually required anyway (model/view glue code, user interaction, delegate stuff, notification handling, etc.), so if no custom drawing is needed it is usually possible to do without a UIView subclass.
In your case I could envision one reusable UIViewController subclass that represents a list entry. It has the following responsibilities:
Create two alternate view hierarchies (collapsed/button, expanded/panel)
Toggle between the view hierarchies in reaction to user interaction (with/without animation)
And another UIViewController subclass that represents the entire list. It has the following responsibilities:
Override the appropriate methods from UIViewController to make it into a container VC
Add/remove child VCs as appropriate to the internal model
Possibly adjust the container view in reaction to collapse/expand events in its child VCs

What’s a good way to create an overlay view that would stay on top?

I’d like to create a small overlay view that would float on top of all the others. I need the view to accept touches and I need it to stay in place even during transitions between the underlying views. What I have tried so far:
Standalone view inserted into the key UIWindow. The obvious downside is that the view is not attached to any view controller, which means handling (at least?) rotation events by hand.
UIViewController containment, have a “root” view controller that would contain the floating view and all navigation would be done underneath it. This is very much a “first-class-citizen” solution, but presenting a modal view controller overlaps the floating view.
Second UIWindow with a root view controller containing the floating view. This goes against Apple recommendations and I had some trouble filtering which events should go to which window.
Does anyone have a working solution that doesn’t require too much brittle hacking?
In the end I have followed Jonathan’s suggestion and implemented the overlay as a separate view inserted into the key window. The view has an associated controller object (a subclass of NSObject, not UIViewController), and this controller takes care of the rotation logic. That way the view implementing the actual overlay object doesn’t need to care about rotation events at all.

Resources