A drop-in UIViewController subclass that automatically manages switching between different view layouts for portrait and landscape orientations, without the need to maintain view state across two different view hierarchies.
- You want to support portrait and landscape modes in your app.
- Having just one view layout for both portrait and landscape doesn't give good results.
- Create two distinct view hierarchies: one for portrait and one for landscape.
- On orientation change, set
this.view
to either your portrait view, or your landscape view. - On load, perform your initialisation on both views: Big Overhead.
- Whenever your view/app state changes, sync the state across both views: Big Overhead.
- Create two distinct view hierarchies: one for portrait and one for landscape.
- Extract just the layout information from the two view versions: use the original two view hierarchies as a layout template.
- Maintain one single view hierarchy: no double handling, no state syncing.
- On orientation change, simply apply the layout information we extracted to our single view hierarchy, to achieve the new layout.
In summary, we skip the double handling by keeping just one view, not two views we need to sync. When the orientation changes, we just rearrange the view, using the layout we extracted from our original two views.
- Set the superclass for your view controller to TPMultiLayoutViewController.
- In Interface Builder, create two different views: one for portrait orientation, and one for landscape orientation.
- Attach your portrait orientation root view to the "portraitView" outlet, and the landscape orientation root view to the "landscapeView" outlet.
- Attach one of the views (whichever you prefer) to the "view" outlet, and connect any actions and outlets from that view.
-
Currently, only
frame
,bounds
,hidden
andautoresizingMask
attributes are assigned, but this can be easily extended. SeeattributesForView:
andapplyAttributes:toView:
for details. -
Both layouts should have the same hierarchical structure.
-
Views are matched to their counterparts in the other layout by searching for similarities, in the following order:
- Tag
- Class, target and action (for UIControl)
- Title or image (for UIButton)
- Title (for UILabel)
- Text or placeholder (for UITextField)
- Class
-
If you wish a view to be ignored by TPMultiLayoutViewController, assign it a negative tag.
-
You can register view classes TPMultiLayoutViewController should not descend into by calling
[TPMultiLayoutViewContoller registerViewClassToIgnore:yourclass];
A good place to do this is in your class' -(void)initialize method.
If you experience odd behaviour, check the log for "Couldn't find match..." messages. If a view cannot be matched to its counterpart, try setting the same tag for both views.
This code is licensed under the terms of the MIT license.
Michael Tyson
A Tasty Pixel