Observing state changes and handling events in Kanzi Android framework (droidfw)

Observing state changes

You can implement KanziViewListener to listen for state changes in KanziView. Use this to inject custom initialization and un-initialization logic.

For example:

  • Use the KanziViewListener.onAttachedToWindow callback to access domain, register Kanzi Engine Java plugins or manually setup the view’s node tree.

    view.addListener(new KanziViewListener() {
       ...
    
       @Override
       public void onAttachedToWindow(View view, Domain domain)
       {
             // Register a plugin.
             domain.registerPlugin(new MyPlugin());
    
             // Manually setup the node tree.
             // Instantiate a node.
             ObjectRef<TextBlock2D> text = TextBlock2D.create(domain, "text");
             // Set as root of the view.
             ((KanziView) view).setRoot(text.get());
             // Set properties on a node.
             text.get().setProperty(TextBox2D.TextProperty, "Hello Kanzi!");
    
    view.addListener(object : KanziViewListener {
       ...
    
       override fun onAttachedToWindow(view: View, domain: Domain) {
             // Register a plugin.
             domain.registerPlugin(MyPlugin())
    
             // Manually setup the node tree.
             // Instantiate a node.
             val text = TextBlock2D.create(domain, "text")
             // Set as root of the view.
             (view as KanziView).root = text.get()
             // Set properties on a node.
             text.get().setProperty(TextBox2D.TextProperty, "Hello Kanzi!")
    
  • Use the KanziViewListener.onStartupPrefabLoaded callback to access and modify the node tree instantiated from the startup prefab that you have configured.

    view.addListener(new KanziViewListener() {
       ...
    
       @Override
       public void onStartupPrefabLoaded(View view, Domain domain)
       {
             // Look up a child node starting from the root.
             TextBox2D text = ((KanziView)view).getRoot().lookupNode("#Text");
             // Set properties on a node.
             text.setProperty(TextBox2D.TextProperty, "Hello world!");
    
    view.addListener(object : KanziViewListener {
       ...
    
       override fun onStartupPrefabLoaded(view: View, domain: Domain) {
             // Look up a child node starting from the root.
             val text = (view as KanziView).root.lookupNode<TextBox2D>("#Text")
             // Set properties on a node.
             text.setProperty(TextBox2D.TextProperty, "Hello world!")
    

To learn more about Kanzi Engine Java plugins, see Creating Kanzi Engine Java plugins.

Handling input

By default, KanziSurfaceView and KanziTextureView handle input events. If you want Kanzi Engine to process events of an arbitrary view that uses KanziViewAdapter, you must manually forward such input events. To do this, use these interfaces:

All Kanzi views by default set focusableInTouchMode to True, unless otherwise set programmatically or through layout attributes. This makes them gain and keep focus when clicked on. See Android touch mode.

Handling input from the Android Automotive rotary controller

By default, KanziSurfaceView and KanziTextureView handle the rotary controller input.

Rotary action

How Kanzi handles the actions

../../../_images/rotary-input-nudge.png
  • Nudge up

  • Nudge down

  • Nudge left

  • Nudge right

Kanzi Android framework (droidfw) handles these actions as corresponding arrow key events.

Kanzi does not support and ignores input from diagonal nudges.

../../../_images/rotary-input-center.png

Center button

Kanzi Android framework (droidfw) tries to enable the direct manipulation mode for the focused Kanzi view. If Kanzi Android framework (droidfw) cannot enable the direct manipulation mode, it forwards the key event to Kanzi Engine. Kanzi Engine translates the key code KeyEvent.KEYCODE_DPAD_CENTER of the rotary center button to the Enter logical key. See Direct manipulation mode.

../../../_images/rotary-input-back.png

Back button

Kanzi Android framework (droidfw) forwards the key event to Kanzi Engine. If Kanzi Engine does not consume the event, Kanzi Android framework (droidfw) disables the direct manipulation mode for the Kanzi view.

../../../_images/rotary-input-rotate.png
  • Rotate counterclockwise

  • Rotate clockwise

Android sends a generic motion event containing the direction of rotation and the number of presses.

Kanzi views forward all generic motion events to KanziViewAdapter.handleGenericMotionEvent.

KanziViewAdapter determines whether the event comes from the rotary controller and checks whether a Kanzi view is in direct manipulation mode. If the Kanzi view is in direct manipulation mode, the Kanzi view forwards the rotation information to Kanzi Engine. Kanzi Engine translates:

  • Clockwise rotation into the Tab key event

  • Counterclockwise rotation into the BackTab key event

To disable the default rotary controller input handling, use one of these approaches:

  • In the layout file, for the Kanzi view element, set the rotaryHandlingEnabled attribute to false:

    <com.rightware.kanzi.KanziSurfaceView
        android:id="@+id/rotaryview"
        app:name="Rotary"
        app:kzbPathList="rotary.kzb"
        app:startupPrefabUrl="kzb://rotary/StartupPrefab"
        app:rotaryHandlingEnabled="false"/>
    
  • In the activity code, pass false to the KanziViewAdapter.setRotaryHandlingEnabled function call:

    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.activity_main);
        mView = findViewById(R.id.rotaryview);
        mView.getAdapter().setRotaryHandlingEnabled(false);
    }
    

Handling orientation change

When the screen orientation changes, an Android application, by default, destroys and recreates the activity. This allows an application to use an alternate layout for portrait and landscape screens, but it also means that you lose all internal Kanzi states.

You can override this by adding the android:configChanges="orientation" property to the AndroidManifest.xml file. With this option, the activity is no longer destroyed on orientation changes, instead onConfigurationChanged() is called on the activity. Forward this event manually to KanziView.handleOrientationChange. This option avoids recreating the Kanzi controls and therefore all internal state is retained. See Android configuration changes.

Handling the Android lifecycle

While KanziSurfaceView and KanziTextureView handle window and surface events by default, an arbitrary view using KanziViewAdapter must manually forward the window and surface events it wants Kanzi to process, through the KanziViewAdapter.handleAttachedToWindow, KanziViewAdapter.handleSurfaceCreated, KanziViewAdapter.handleSurfaceChanged, KanziViewAdapter.handleSurfaceDestroyed, and KanziViewAdapter.handleDetachedFromWindow interfaces.

Handling the user-visibility of views

Kanzi Android framework (droidfw) automatically and continuously tracks whether each connected view is visible to the user, and does not render the surface of hidden views.

To check whether a view is visible to the user, Kanzi Android framework (droidfw) considers:

  • The visibility state of the view

  • The visibility state of all ancestors of the view

  • The alpha of the view

  • The effectively visible portion of the view computed through View.getGlobalVisibleRect()

An arbitrary view using KanziViewAdapter must manually forward visibility events that it wants Kanzi to process through the KanziViewAdapter.handleVisibilityChange interface.