How to add keyboard support on facebook litho

179 Views Asked by At

I am trying to use facebook litho to build the android app for TV.

We need to support keyboard events(up/down/left/right) to control the navigation.

I can intercept keyboard events by onKeyDown in the activity, but I don't know how to update the component's status from activity.

1

There are 1 best solutions below

0
On

Overview

I have solved a similar problem, which is to re-render the top-level Litho component when an external action occurs by doing the following:

  1. storing a reference to the LithoView created in my Activities onCreate method
  2. define some kind of object to track the state across renders, this must contain any state needed to render your component tree. this will be a @Prop on your top-level component
  3. create an initial state in onCreate and derive my initial component from this
  4. when I receive a callback, compute the new state object and create a new Component instance from this
  5. call LithoView#setComponent(Component) with that instance

This is essentially an implementation of the MVI approach as explained here for Android with Mosby, though the example shown is highly simplified.

Example:

Activity:

public class CounterActivity extends Activity {
    private LithoView lithoView; // 1: keeps the same LithoView instance for the entirety of the Activity
    private ComponentContext c;
    private State currentState; // 2: remembers the current State

    static class State {
        private int counter;

        State(int count) {
            this.counter = count;
        }

        public int getCounter() {
            return counter;
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        c = new ComponentContext(this);
        // 3: create the initial UI state (note: you probably need to use savedInstanceState or some other external state here)
        setState(getInitialApplicationState());
    }

    // 4: A silly example of an Activity-level callback to drive state updates
    @Override
    public void onBackPressed() {
        setState(new State(currentState.getCounter() + 1));
    }

    // This will store the new state in the Activity and update the component accordingly
    private void setState(State newState) {
        currentState = newState;
        updateView(newState);
    }

    // There is a 1:1 mapping between State and UI
    private Component componentForState(State state) {
        return CounterComponent.create(c).state(state).build();
    }

    // 5: set the Component on the LithoView for the current state
    private void updateView(State currentState) {
        Component contentComponent = componentForState(currentState);
        if (lithoView == null) {
            lithoView = LithoView.create(this, contentComponent);
            setContentView(lithoView);
        } else {
            lithoView.setComponent(contentComponent);
        }
    }

    private State getInitialApplicationState() {
        return new State(0);
    }
}

Spec:

@LayoutSpec
public class CounterComponentSpec {
    @OnCreateLayout
    static ComponentLayout onCreateLayout(
            ComponentContext c,
            @Prop CounterActivity.State state) {
        return Text.create(c)
                .text("Count: " + state.getCounter())
                .textSizeSp(44f)
                .buildWithLayout();
    }
}