In most situations, the default behavior of focus management for You.i React Native apps should meet your needs, but there may be times when it does not. The following advanced focus management topics cover the fundamentals required to understand how You.i Platform focus management works and how to override default behavior.
Advanced focus management topics require knowledge of C++.
You don’t need to be aware of these key terms if you use the default focus behavior offered by Facebook React Native because it handles most things related to focus navigation. However, if you want to override the default behavior, or work on a unique use case with You.i React Native, knowledge of these terms will be helpful.
Consider the following important terms and concepts when working with You.i Platform focus management:
The following diagram shows the process of creating a SceneTree from an After Effects file.
A SceneTree contains a group of objects arranged in an hierarchical order for use in rendering. Each object has a spatial and logical relation between other objects.
The scene tree can be seen at runtime using the Scene Tree Viewer option in the Debug panel. The following code snippet shows a typical SceneTree:
<CYIStackView name="StackView" drawParent="Main" WorldBB="x: 0, y: 0, w: 1881, h: 1534" CompositeOpacity="1" LocalOpacity="1" Visibility="Visible" X="400" Y="400" >
<CYIPerspectiveCameraSceneNode name="Camera 1" drawParent="StackView" WorldBB="x: 400, y: 400, w: 0, h: 0" CompositeOpacity="1" LocalOpacity="1" Visibility="Visible" X="400" Y="400" Target="No Target Specified" UpVector="(0,-1,0)" NearPlane="0.1" FarPlane="20000" FOV="13.5071" >
</CYIPerspectiveCameraSceneNode>
<CYISceneView name="StreamingView" drawParent="StackView" WorldBB="x: 19.55, y: 22.01, w: 760.9, h: 711" CompositeOpacity="1" LocalOpacity="1" Visibility="Hidden" X="400" Y="400" >
<FocusView name="FocusableItem" drawParent="StreamingView" WorldBB="x: 22.5, y: 24.01, w: 200, h: 200" CompositeOpacity="1" LocalOpacity="1" Visibility="Visible" X="122.495" Y="124.008" >
<CYISceneNode name="Black Solid 1" drawParent="FocusableItem" WorldBB="x: 22.5, y: 24.01, w: 200, h: 200" CompositeOpacity="1" LocalOpacity="1" Visibility="Visible" X="100" Y="100" >
</CYISceneNode>
<CYISceneNode name="White Solid 1" drawParent="FocusableItem" WorldBB="x: 32.5, y: 34.01, w: 180, h: 180" CompositeOpacity="1" LocalOpacity="1" Visibility="Visible" X="100" Y="100" >
</CYISceneNode>
<CYISceneNode name="Medium Purple Solid 1" drawParent="FocusableItem" WorldBB="x: 22.5, y: 24.01, w: 200, h: 200" CompositeOpacity="0" LocalOpacity="0" Visibility="Visible" X="100" Y="100" >
</CYISceneNode>
<CYIAtlasTextSceneNode name="Placeholder-Text" drawParent="FocusableItem" WorldBB="x: 122.5, y: 124, w: 0, h: 0" CompositeOpacity="1" LocalOpacity="1" Visibility="Visible" X="100" Y="100" text="">
</CYIAtlasTextSceneNode>
</FocusView>
<FocusView name="FocusableItem" drawParent="StreamingView" WorldBB="x: 580.5, y: 368, w: 200, h: 200" CompositeOpacity="1" LocalOpacity="1" Visibility="Visible" X="680.495" Y="468.008" >
<CYISceneNode name="Black Solid 1" drawParent="FocusableItem" WorldBB="x: 580.5, y: 368, w: 200, h: 200" CompositeOpacity="1" LocalOpacity="1" Visibility="Visible" X="100" Y="100" >
</CYISceneNode>
<CYISceneNode name="White Solid 1" drawParent="FocusableItem" WorldBB="x: 590.5, y: 378, w: 180, h: 180" CompositeOpacity="1" LocalOpacity="1" Visibility="Visible" X="100" Y="100" >
</CYISceneNode>
<CYISceneNode name="Medium Purple Solid 1" drawParent="FocusableItem" WorldBB="x: 580.5, y: 368, w: 200, h: 200" CompositeOpacity="0" LocalOpacity="0" Visibility="Visible" X="100" Y="100" >
</CYISceneNode>
<CYIAtlasTextSceneNode name="Placeholder-Text" drawParent="FocusableItem" WorldBB="x: 680.5, y: 468, w: 0, h: 0" CompositeOpacity="1" LocalOpacity="1" Visibility="Visible" X="100" Y="100" text="">
</CYIAtlasTextSceneNode>
</FocusView>
Refer to the following diagram to see a visual representation of the SceneTree showing all the logical relationships:
The objects that are part of SceneTree are called SceneNodes. A SceneNode, which has the CYISceneNode class, is the basis of all visual elements that you see on screen, such as buttons, views, images, and so on. Using CYISceneNode class, a SceneNode gives required functionality for input, signals, and animation.
Some the important tasks a SceneNode can do are:
nodes can be detached and placed anywhere in the scene tree
Scene nodes provide parent/child relationships and inherit properties such as, clipping, opacity, and visibility.
By default, the root of a SceneTree is a focus root. Therefore, when focus enters a focus root, focus is constrained to its descendants until:
When focus leaves a focus root, focus returns to the last view that had focus in the parent focus root.
If that view is no longer focusable, another view in the parent focus root is given focus.
If no views in the parent focus root are focusable, focus leaves that focus root.
If there are no focusable views, focus is cleared using CYISceneManager::ClearFocus()
.
For more information, see the Focus Manager module.
SceneViews have timelines that play an important part in defining its interactivity and visual behavior. Also, there are dedicated Focus timelines for the UI component used in a scene.
Marker | What it does |
---|---|
FocusIn | Plays the animation on a view when the focus is gained. |
FocusOut | Plays the animation on a view when the focus is lost. |
You don’t need to be aware of these rules if you are using the default focus behavior offered by Facebook React Native because it takes care of most things related to focus navigation. However, if you want to override the default behavior, or work on a unique use case using You.i React Native, knowledge of these rules may be helpful.
Before working on focus management for a view, you should be aware of the rules for deciding if it can be focused or not. The first two are mandatory. The remaining ones may apply depending on circumstances:
Before moving focus to a particular view, you must ensure that the view is focusable using CYISceneView::IsFocusable()
.
It returns either True
or False
.
Once it is confirmed that a view is focusable (that is, IsFocusable()=True
), other rules can be verified.
Ensure that the view you want to focus does not already have focus.
See the following code snippet for using IsFocusable()
:
if (!pView->IsFocusable())
{
YI_LOGE("ViewName", "View is not focusable");
}
Once you know that the view is focusable and that the node that has the view is visible, you need to verify that the view is reachable from the SceneManager; that is, the presence of SceneView on the staged screen.
To do this, use CYISceneManager::IsReachable()
.
See the following code snippet for using IsReachable()
:
if (!pView->GetSceneManger()->IsReachable())
{
YI_LOGE("View Name", "View is not visible");
}
Consider the following points related to focus management rules:
A focusable view should be able to visually indicate that it has received focus. The focus timeline should have an animation that makes it easy for the user to see when the view has gained focus. For example, the following animation shows the highlighting of buttons when they receive focus:
Once the view receives focus, You.i TV recommends that it perform some action. For example, the button at the bottom of the screen opens a new screen after it receives focus:
A view within another view never receives focus. For example, the bigger view (H) contains a smaller view (I) within it. The smaller view (I) never gets focus.