In the previous episode of this series we discussed how to create the main interface of our Leanback-enabled project through the BrowseFragment. Now let’s take a closer look into 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 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:
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 close look at the customizing the CardPresenter as an example:
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:
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).
In the next episode of this series we’ll make a further step towards fully understanding how a Leanback-enabled project works, moving to the second step of the user journey: building and displaying the details of specific content using the DetailsFragment.
Stay tuned!
Mario Viviani (@mariuxtheone)