Give your layout groups some smarts. This DynamicLayoutGroup
group switches orientation automatically between landscape and portrait layouts. It acts like a VerticalLayoutGroup (screenshots below) or a HorizontalLayoutGroup depending the current aspect ratio of the screen.
The Why
These screenshots are from an upcoming 2.0 update to Fourtex Zen. The game shipped with a fixed landscape orientation. We recently moved to Unity 5 and decided that updating Fourtex Zen would be a good way to learn the new UI system. We wanted the game playable regardless of screen orientation. The poem panels stack the poetry text in portrait and place it side-by-side in landscape (there are 64 poems given as in-game rewards).
The Code
The DynamicLayoutGroup
class inherits directly from the Unity 5 HorizontalOrVerticalLayoutGroup
base class and provides a simple mechanism to determine screen orientation and shift its layout accordingly. It can be used anywhere you would normally use a VerticalLayoutGroup
or HorizontalLayoutGroup
.
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;
using System.Collections.Generic;
namespace SDD.UI {
/// <summary>
/// Layout group switches orientation automatically between landscape and
/// portrait layouts so it either acts like a VerticalLayoutGroup or a
/// HorizontalLayoutGroup.
/// </summary>
[AddComponentMenu("Layout/Dynamic Layout Group", 150)]
public class DynamicLayoutGroup : HorizontalOrVerticalLayoutGroup {
/// <summary>
/// When is the layout vertical? In portrait or landscape?
/// </summary>
[SerializeField]
public ScreenOrientation verticalWhen = ScreenOrientation.Portrait;
public bool IsVertical { get { return GetIsVertical(); }}
private bool GetIsVertical() {
bool isVertical;
if (UnityEngine.Screen.width > UnityEngine.Screen.height) {
//orientation = ScreenOrientation.Landscape;
isVertical = (verticalWhen == ScreenOrientation.Landscape) ? true : false;
}
else {
//orientation = ScreenOrientation.Portrait;
isVertical = (verticalWhen == ScreenOrientation.Portrait) ? true : false;
}
//Log.Debug(string.Format("DynamicLayoutGroup.OnRectTransformDimensionsChange() isVertical={0}a, ID={1}", isVertical, GetInstanceID()));
return isVertical;
}
public override void CalculateLayoutInputHorizontal() {
//Log.Debug(string.Format("DynamicLayoutGroup.CalculateLayoutInputHorizontal() IsVertical={0}, ID={1}", IsVertical, GetInstanceID()));
base.CalculateLayoutInputHorizontal();
CalcAlongAxis(0, isVertical: IsVertical);
}
public override void CalculateLayoutInputVertical() {
//Log.Debug(string.Format("DynamicLayoutGroup.CalculateLayoutInputVertical() IsVertical={0}, ID={1}", IsVertical, GetInstanceID()));
CalcAlongAxis(1, isVertical: IsVertical);
}
public override void SetLayoutHorizontal() {
//Log.Debug(string.Format("DynamicLayoutGroup.SetLayoutHorizontal() IsVertical={0}, ID={1}", IsVertical, GetInstanceID()));
SetChildrenAlongAxis(0, isVertical: IsVertical);
}
public override void SetLayoutVertical() {
//Log.Debug(string.Format("DynamicLayoutGroup.SetLayoutVertical() IsVertical={0}, ID={1}", IsVertical, GetInstanceID()));
SetChildrenAlongAxis(1, isVertical: IsVertical);
}
}
}
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
namespace SDD.UI {
/// <summary>
/// Override the Unity UI custom editor for HorizontalOrVerticalLayoutGroup
/// and do exactly nothing. The only purpose of this class is to expose the
/// public ```VerticalWhen```. The inherited editor prevents editing new
/// publics in descendant classes without doing a full widget layout here
/// (too much work!).
/// </summary>
/// <remarks>
/// Place in ```Editor``` folder
/// </remarks>
[CustomEditor(typeof(SDD.UI.DynamicLayoutGroup), true)]
[CanEditMultipleObjects]
public class DynamicLayoutGroupEditor : UnityEditor.Editor {
}
}
namespace SDD {
/// <summary>
/// Orientation of the screen regardless of which way is up
/// </summary>
public enum ScreenOrientation {
Landscape,
Portrait
}
This article originally appeared on SaltyDog.digital