Developer Console

Step 4: Edit the User Interface Through Presenters (Fire TV)

Let's explore the Presenter class. The Presenter class allows us to define the look and feel of our Leanback-enabled app without editing the underlying data structure.

The Presenter Class

The Leanback template we created was built following a custom version of the common development pattern, Model-view-controller (MVC), in which the Presenter class acts as the View. The Presenters are passed to the ArrayObjectAdapter as arguments and define how the content of the Adapter should be displayed

The Leanback approach provides a variety of predefined Presenters:

  • CardPresenter defines singular content
  • ListRowPresenter defines how various content in a row should be displayed and arranged
  • DetailsDescriptionPresenter defines the UI of the DetailsFragment.

Implementing the Presenters are quite similar: they all follow the ViewHolder pattern and are mostly composed by Custom Views with methods to set the fields of the views.

Let's take a closer look at the customizing the CardPresenter as an example.

Customizing the CardPresenter

In the BrowseFragment, we see that the CardPresenter defines the UI of a single item of the adapter.

public class MainFragment extends BrowseFragment {

        CardPresenter cardPresenter = new CardPresenter();

        //Create the adapter for the row and add all the movies
        ArrayObjectAdapter listRowAdapter
			= new ArrayObjectAdapter(cardPresenter);

    }

The highlighted view in the previous image is a custom view called ImageCardView and is used in the CardPresenter to define the UI of a single component.

Let's analyze how views are initialized in the CardPresenter.

public class CardPresenter extends Presenter {

	public ViewHolder onCreateViewHolder(ViewGroup parent) {
   	...

  	ImageCardView cardView = new ImageCardView(parent.getContext);
    	cardView.setFocusable(true);
   	cardView.setFocusableInTouchMode(true);
    	return new ViewHolder(cardView);

   ...
  }
}

There are two things to notice here:

  1. As we mentioned before, the CardPresenter is built on the ViewHolder pattern. This ensures views are correctly recycled and memory is not wasted.
  2. The CardView is set to SetFocusable(true) and setFocusableInTouchMode(true). Although there is no existing touch interaction on a TV screen, this step is necessary because this is how Android currently manages the focus-ability of views.

Now, let's take a look at how the components of the ImageCardView (and of the Presenter) are set:

public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
    Movie movie = (Movie) item;
    ImageCardView cardView = (ImageCardView) viewHolder.view;
	if (movie.getCardImageUrl() != null) {
        		cardView.setTitleText(movie.getTitle());
        		cardView.setContentText(movie.getDescription());
			Glide.with(viewHolder.view.getContext())
                		.load(movie.getCardImageUrl())
                		.centerCrop()
				.into(cardView.getMainImageView());
    }
}

In this example, we use our own custom class "Movie" to retrieve the information we want to display.

The cardView is retrieved from the ViewHolder, then we have the simple setters setTitleText() and setContentText(), to edit the main fields of the view.

To retrieve the image for the thumbnail, Leanback automatically uses the Glide library (but you can easily replace it with the image loading library of your choice).

Next Steps

Continue on to the next step: Step 5: Provide the Details of the App Content Through the DetailsFragment.


Last updated: Oct 29, 2020