ControlBarPresenter.java revision aa67105babce5fb14e1f39b57d4c84ce634afa62
17ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout/*
27ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * Copyright (C) 2014 The Android Open Source Project
37ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout *
47ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
57ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * in compliance with the License. You may obtain a copy of the License at
67ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout *
77ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * http://www.apache.org/licenses/LICENSE-2.0
87ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout *
97ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * Unless required by applicable law or agreed to in writing, software distributed under the License
107ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
117ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * or implied. See the License for the specific language governing permissions and limitations under
127ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * the License.
137ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout */
147ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutpackage android.support.v17.leanback.widget;
157ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
16aa93f6777233b789feb14d95d900b158d0ac4841Craig Stoutimport android.content.Context;
177ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.support.v17.leanback.R;
187ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.util.SparseArray;
197ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.view.LayoutInflater;
207ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.view.View;
217ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.view.ViewGroup;
227ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.widget.LinearLayout;
237ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
247ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout/**
257ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * A presenter that assumes a LinearLayout container for a series
267ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * of control buttons backed by objects of type {@link Action}.
277ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout *
287ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * Different layouts may be passed to the presenter constructor.
297ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * The layout must contain a view with id control_bar.
307ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout */
317ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutclass ControlBarPresenter extends Presenter {
327ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
337ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    private static final int MAX_CONTROLS = 7;
347ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
357ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    /**
367ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     * The data type expected by this presenter.
377ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     */
387ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    static class BoundData {
397ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        /**
407ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout         * Adapter containing objects of type {@link Action}.
417ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout         */
427ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        ObjectAdapter adapter;
437ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
447ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        /**
457ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout         * The presenter to be used for the adapter objects.
467ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout         */
477ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        Presenter presenter;
487ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
497ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
507ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    /**
517ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     * A ViewHolder for an actions bar.
527ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     */
537ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    class ViewHolder extends Presenter.ViewHolder {
547ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        ObjectAdapter mAdapter;
557ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        Presenter mPresenter;
56aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout        ControlBar mControlBar;
577ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        SparseArray<Presenter.ViewHolder> mViewHolders =
587ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                new SparseArray<Presenter.ViewHolder>();
597ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        ObjectAdapter.DataObserver mDataObserver;
607ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
617ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        /**
627ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout         * Constructor for the ViewHolder.
637ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout         */
647ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        ViewHolder(View rootView) {
657ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            super(rootView);
66aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout            mControlBar = (ControlBar) rootView.findViewById(R.id.control_bar);
677ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            if (mControlBar == null) {
687ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                throw new IllegalStateException("Couldn't find control_bar");
697ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            }
704cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout            mControlBar.setOnChildFocusedListener(new ControlBar.OnChildFocusedListener() {
714cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                @Override
724cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                public void onChildFocusedListener(View child, View focused) {
734cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                    if (mOnItemViewSelectedListener == null) {
744cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                        return;
754cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                    }
764cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                    for (int position = 0; position < mViewHolders.size(); position++) {
774cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                        if (mViewHolders.get(position).view == child) {
784cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                            mOnItemViewSelectedListener.onItemSelected(
79aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                                    mViewHolders.get(position), getDisplayedAdapter().get(position),
804cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                                            null, null);
814cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                            break;
824cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                        }
834cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                    }
844cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                }
854cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout            });
867ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            mDataObserver = new ObjectAdapter.DataObserver() {
877ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                @Override
887ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                public void onChanged() {
89aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                    if (mAdapter == getDisplayedAdapter()) {
90aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                        showControls(mPresenter);
91aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                    }
927ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                }
937ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                @Override
947ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                public void onItemRangeChanged(int positionStart, int itemCount) {
95aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                    if (mAdapter == getDisplayedAdapter()) {
96aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                        for (int i = 0; i < itemCount; i++) {
97aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                            bindControlToAction(positionStart + i, mPresenter);
98aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                        }
997ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                    }
1007ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                }
1017ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            };
1027ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        }
1037ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
104aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout        int getChildMarginFromCenter(Context context, int numControls) {
105aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout            // Includes margin between icons plus two times half the icon width.
106aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout            return getChildMarginDefault(context) + getControlIconWidth(context);
107aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout        }
108aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout
109aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        void showControls(Presenter presenter) {
1107ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            View focusedChild = mControlBar.getFocusedChild();
111aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            ObjectAdapter adapter = getDisplayedAdapter();
1127ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            mControlBar.removeAllViews();
1137ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            for (int position = 0; position < adapter.size() && position < MAX_CONTROLS;
1147ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                    position++) {
1157ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                bindControlToAction(position, adapter, presenter);
1167ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            }
1177ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            if (focusedChild != null) {
1187ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                focusedChild.requestFocus();
1197ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            }
120aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout            mControlBar.setChildMarginFromCenter(
121aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout                    getChildMarginFromCenter(mControlBar.getContext(), adapter.size()));
1227ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        }
1237ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
124aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        void bindControlToAction(int position, Presenter presenter) {
125aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            bindControlToAction(position, getDisplayedAdapter(), presenter);
126aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        }
127aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout
128aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        private void bindControlToAction(final int position,
129aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                ObjectAdapter adapter, Presenter presenter) {
1307ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            Presenter.ViewHolder vh = mViewHolders.get(position);
1317ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            Object item = adapter.get(position);
1327ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            if (vh == null) {
1337ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                vh = presenter.onCreateViewHolder(mControlBar);
1347ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                mViewHolders.put(position, vh);
1357ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                presenter.setOnClickListener(vh, new View.OnClickListener() {
1367ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                    @Override
1377ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                    public void onClick(View v) {
138aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                        Object item = getDisplayedAdapter().get(position);
1397ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                        if (mOnActionClickedListener != null && item instanceof Action) {
1407ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                            mOnActionClickedListener.onActionClicked((Action) item);
1417ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                        }
1427ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                    }
1437ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                });
1447ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            }
1457ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            if (vh.view.getParent() == null) {
1467ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                mControlBar.addView(vh.view);
1477ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            }
1487ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            presenter.onBindViewHolder(vh, item);
1497ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        }
1507ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
151aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        /**
152aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout         * Returns the adapter currently bound to the displayed controls.
153aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout         * May be overridden in a subclass.
154aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout         */
155aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        ObjectAdapter getDisplayedAdapter() {
1567ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            return mAdapter;
1577ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        }
1587ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
1597ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
1607ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    private OnActionClickedListener mOnActionClickedListener;
1614cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout    private OnItemViewSelectedListener mOnItemViewSelectedListener;
1627ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    private int mLayoutResourceId;
163aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout    private static int sChildMarginDefault;
164aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout    private static int sControlIconWidth;
1657ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
1667ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    /**
1677ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     * Constructor for a ControlBarPresenter.
1687ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     *
1697ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     * @param layoutResourceId The resource id of the layout for this presenter.
1707ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     */
1717ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    public ControlBarPresenter(int layoutResourceId) {
1727ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        mLayoutResourceId = layoutResourceId;
1737ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
1747ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
1757ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    /**
1767ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     * Returns the layout resource id.
1777ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     */
1787ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    public int getLayoutResourceId() {
1797ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        return mLayoutResourceId;
1807ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
1817ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
1827ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    /**
1837ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     * Sets the listener for {@link Action} click events.
1847ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     */
1857ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    public void setOnActionClickedListener(OnActionClickedListener listener) {
1867ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        mOnActionClickedListener = listener;
1877ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
1887ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
1897ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    /**
1907ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     * Gets the listener for {@link Action} click events.
1917ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     */
1927ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    public OnActionClickedListener getOnActionClickedListener() {
1937ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        return mOnActionClickedListener;
1947ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
1957ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
1964cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout    /**
1974cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout     * Sets the listener for item selection.  When this listener is invoked,
1984cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout     *  the rowViewHolder and row are always null.
1994cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout     */
2004cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout    public void setOnItemViewSelectedListener(OnItemViewSelectedListener listener) {
2014cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout        mOnItemViewSelectedListener = listener;
2024cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout    }
2034cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout
2044cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout    /**
2054cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout     * Gets the listener for item selection.
2064cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout     */
2074cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout    public OnItemViewSelectedListener getOnItemViewSelectedListener() {
2084cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout        return mOnItemViewSelectedListener;
2094cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout    }
2104cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout
2117ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    @Override
2127ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    public Presenter.ViewHolder onCreateViewHolder(ViewGroup parent) {
2137ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        View v = LayoutInflater.from(parent.getContext())
2147ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            .inflate(getLayoutResourceId(), parent, false);
2157ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        return new ViewHolder(v);
2167ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
2177ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
2187ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    @Override
2197ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    public void onBindViewHolder(Presenter.ViewHolder holder, Object item) {
2207ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        ViewHolder vh = (ViewHolder) holder;
2217ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        BoundData data = (BoundData) item;
2227ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        if (vh.mAdapter != data.adapter) {
2237ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            vh.mAdapter = data.adapter;
2247ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            vh.mAdapter.registerObserver(vh.mDataObserver);
2257ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        }
2267ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        vh.mPresenter = data.presenter;
227aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        vh.showControls(vh.mPresenter);
2287ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
2297ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
2307ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    @Override
2317ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    public void onUnbindViewHolder(Presenter.ViewHolder holder) {
2327ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        ViewHolder vh = (ViewHolder) holder;
2337ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        vh.mAdapter.unregisterObserver(vh.mDataObserver);
2347ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        vh.mAdapter = null;
2357ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
236aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout
237aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout    int getChildMarginDefault(Context context) {
238aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout        if (sChildMarginDefault == 0) {
239aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout            sChildMarginDefault = context.getResources().getDimensionPixelSize(
240aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout                    R.dimen.lb_playback_controls_child_margin_default);
241aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout        }
242aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout        return sChildMarginDefault;
243aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout    }
244aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout
245aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout    int getControlIconWidth(Context context) {
246aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout        if (sControlIconWidth == 0) {
247aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout            sControlIconWidth = context.getResources().getDimensionPixelSize(
248aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout                    R.dimen.lb_control_icon_width);
249aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout        }
250aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout        return sControlIconWidth;
251aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout    }
2527ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout}
253