android TV - Creating a Catalog Browser,Providing a Card View

desaco發表於2016-01-19

> Building TV Playback Apps

 The Android framework provides classes for building user interfaces for these types of apps with the v17 leanback support library. This library provides a framework of classes for creating an efficient and familiar interface for browsing and playing media files with minimal coding. The classes are designed to be extended and customized so you can create an experience that is unique to your app.

>Creating a Catalog Browser

 A media app that runs on a TV needs to allow users to browse its content offerings, make a selection, and start playing content.  the v17 leanback support library to implement a user interface for browsing music or videos from your app's media catalog.

 how to create a layout that contains a BrowseFragment object:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/main_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:name="com.example.android.tvleanback.ui.MainFragment"
        android:id="@+id/main_browse_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</FrameLayout>
public class MainFragment extends BrowseFragment implements
        LoaderManager.LoaderCallbacks<HashMap<String, List<Movie>>> {

...

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        loadVideoData();

        prepareBackgroundManager();
        setupUIElements();
        setupEventListeners();
    }
...

    private void prepareBackgroundManager() {
        mBackgroundManager = BackgroundManager.getInstance(getActivity());
        mBackgroundManager.attach(getActivity().getWindow());
        mDefaultBackground = getResources()
            .getDrawable(R.drawable.default_background);
        mMetrics = new DisplayMetrics();
        getActivity().getWindowManager().getDefaultDisplay().getMetrics(mMetrics);
    }

    private void setupUIElements() {
        setBadgeDrawable(getActivity().getResources()
            .getDrawable(R.drawable.videos_by_google_banner));
        // Badge, when set, takes precedent over title
        setTitle(getString(R.string.browse_title));
        setHeadersState(HEADERS_ENABLED);
        setHeadersTransitionOnBackEnabled(true);
        // set headers background color
        setBrandColor(getResources().getColor(R.color.fastlane_background));
        // set search icon color
        setSearchAffordanceColor(getResources().getColor(R.color.search_opaque));
    }

    private void loadVideoData() {
        VideoProvider.setContext(getActivity());
        mVideosUrl = getActivity().getResources().getString(R.string.catalog_url);
        getLoaderManager().initLoader(0, null, this);
    }

    private void setupEventListeners() {
        setOnSearchClickedListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                Intent intent = new Intent(getActivity(), SearchActivity.class);
                startActivity(intent);
            }
        });

        setOnItemViewClickedListener(new ItemViewClickedListener());
        setOnItemViewSelectedListener(new ItemViewSelectedListener());
    }
...

 In the sample above, the private method setupUIElements() calls several of the BrowseFragment methods to style the media catalog browser:

  • setBadgeDrawable() places the specified drawable resource in the upper-right corner of the browse fragment, as shown in figures 1 and 2. This method replaces the title string with the drawable resource, ifsetTitle() is also called. The drawable resource should be 52dps tall.
  • setTitle() sets the title string in the upper-right corner of the browse fragment, unlesssetBadgeDrawable() is called.
  • setHeadersState() and setHeadersTransitionOnBackEnabled() hide or disable the headers. See Hide or Disable Headers for more information.
  • setBrandColor() sets the background color for UI elements in the browse fragment, specifically the header section background color, with the specified color value.
  • setSearchAffordanceColor() sets the color of the search icon with the specified color value. The search icon appears in the upper-left corner of the browse fragment, as shown in figures 1 and 2.

 > Use a Presenter and implement the abstract methods to create, bind, and unbind the view holder. The following example shows how to bind the viewholder with two views, an ImageView and a TextView.

public class IconHeaderItemPresenter extends Presenter {
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup) {
        LayoutInflater inflater = (LayoutInflater) viewGroup.getContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View view = inflater.inflate(R.layout.icon_header_item, null);

        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, Object o) {
        HeaderItem headerItem = ((ListRow) o).getHeaderItem();
        View rootView = viewHolder.view;

        ImageView iconView = (ImageView) rootView.findViewById(R.id.header_icon);
        Drawable icon = rootView.getResources().getDrawable(R.drawable.ic_action_video, null);
        iconView.setImageDrawable(icon);

        TextView label = (TextView) rootView.findViewById(R.id.header_label);
        label.setText(headerItem.getName());
    }

    @Override
    public void onUnbindViewHolder(ViewHolder viewHolder) {
    // no op
    }
}
However, an easier way to combine a TextView with a drawable resource is to use the TextView.drawableLeft attribute. Doing it this way, you don't need the ImageViewshown here.

> The Leanback support library provides a BackgroundManager class for changing the background of your TV app activity. 

protected void updateBackground(Drawable drawable) {
    BackgroundManager.getInstance(this).setDrawable(drawable);
}
>
protected void clearBackground() {
    BackgroundManager.getInstance(this).setDrawable(mDefaultBackground);
}

protected OnItemViewSelectedListener getDefaultItemViewSelectedListener() {
    return new OnItemViewSelectedListener() {
        @Override
        public void onItemSelected(Object item, Row row) {
            if (item instanceof Movie ) {
                Drawable background = ((Movie)item).getBackdropDrawable();
                updateBackground(background);
            } else {
                clearBackground();
            }
        }
    };
}

Note: The implementation above is a simple example shown for purposes of illustration. When creating this function in your own app, you should consider running the background update action in a separate thread for better performance. In addition, if you are planning on updating the background in response to users scrolling through items, consider adding a time to delay a background image update until the user settles on an item. This technique avoids excessive background image updates.

> Providing a Card View

 you create the card views for your media items and present them in the browse fragment.

 The BaseCardView class and subclasses display the meta data associated with a media item. The ImageCardView class used in this lesson displays an image for the content along with the media item's title.

>In the Presenter, implement an onCreateViewHolder() callback that creates a view holder that can be used to display a content item.

@Override
public class CardPresenter extends Presenter {

    private Context mContext;
    private static int CARD_WIDTH = 313;
    private static int CARD_HEIGHT = 176;
    private Drawable mDefaultCardImage;

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent) {
        mContext = parent.getContext();
        mDefaultCardImage = mContext.getResources().getDrawable(R.drawable.movie);
...

In the onCreateViewHolder() method, create a card view for content items. The sample below uses anImageCardView.

When a card is selected, the default behavior expands it to a larger size. If you want to designate a different color for the selected card, call setSelected() as shown here.

...
    ImageCardView cardView = new ImageCardView(mContext) {
        @Override
        public void setSelected(boolean selected) {
            int selected_background = mContext.getResources().getColor(R.color.detail_background);
            int default_background = mContext.getResources().getColor(R.color.default_background);
            int color = selected ? selected_background : default_background;
            findViewById(R.id.info_field).setBackgroundColor(color);
            super.setSelected(selected);
        }
    };

相關文章