ControlBarPresenter.java revision 7ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
12 * the License.
13 */
14package android.support.v17.leanback.widget;
15
16import android.support.v17.leanback.R;
17import android.util.SparseArray;
18import android.view.LayoutInflater;
19import android.view.View;
20import android.view.ViewGroup;
21import android.widget.LinearLayout;
22
23/**
24 * A presenter that assumes a LinearLayout container for a series
25 * of control buttons backed by objects of type {@link Action}.
26 *
27 * Different layouts may be passed to the presenter constructor.
28 * The layout must contain a view with id control_bar.
29 */
30class ControlBarPresenter extends Presenter {
31
32    private static final int MAX_CONTROLS = 7;
33
34    /**
35     * The data type expected by this presenter.
36     */
37    static class BoundData {
38        /**
39         * Adapter containing objects of type {@link Action}.
40         */
41        ObjectAdapter adapter;
42
43        /**
44         * The presenter to be used for the adapter objects.
45         */
46        Presenter presenter;
47    }
48
49    /**
50     * A ViewHolder for an actions bar.
51     */
52    class ViewHolder extends Presenter.ViewHolder {
53        ObjectAdapter mAdapter;
54        Presenter mPresenter;
55        LinearLayout mControlBar;
56        SparseArray<Presenter.ViewHolder> mViewHolders =
57                new SparseArray<Presenter.ViewHolder>();
58        ObjectAdapter.DataObserver mDataObserver;
59
60        /**
61         * Constructor for the ViewHolder.
62         */
63        ViewHolder(View rootView) {
64            super(rootView);
65            mControlBar = (LinearLayout) rootView.findViewById(R.id.control_bar);
66            if (mControlBar == null) {
67                throw new IllegalStateException("Couldn't find control_bar");
68            }
69            mDataObserver = new ObjectAdapter.DataObserver() {
70                @Override
71                public void onChanged() {
72                    showControls(mAdapter, mPresenter);
73                }
74                @Override
75                public void onItemRangeChanged(int positionStart, int itemCount) {
76                    for (int i = 0; i < itemCount; i++) {
77                        bindControlToAction(positionStart + i, mAdapter, mPresenter);
78                    }
79                }
80            };
81        }
82
83        void showControls(ObjectAdapter adapter, Presenter presenter) {
84            View focusedChild = mControlBar.getFocusedChild();
85            mControlBar.removeAllViews();
86            for (int position = 0; position < adapter.size() && position < MAX_CONTROLS;
87                    position++) {
88                bindControlToAction(position, adapter, presenter);
89            }
90            if (focusedChild != null) {
91                focusedChild.requestFocus();
92            }
93        }
94
95        void bindControlToAction(final int position, ObjectAdapter adapter, Presenter presenter) {
96            Presenter.ViewHolder vh = mViewHolders.get(position);
97            Object item = adapter.get(position);
98            if (vh == null) {
99                vh = presenter.onCreateViewHolder(mControlBar);
100                mViewHolders.put(position, vh);
101                presenter.setOnClickListener(vh, new View.OnClickListener() {
102                    @Override
103                    public void onClick(View v) {
104                        Object item = getAdapter().get(position);
105                        if (mOnActionClickedListener != null && item instanceof Action) {
106                            mOnActionClickedListener.onActionClicked((Action) item);
107                        }
108                    }
109                });
110            }
111            if (vh.view.getParent() == null) {
112                mControlBar.addView(vh.view);
113            }
114            presenter.onBindViewHolder(vh, item);
115        }
116
117        ObjectAdapter getAdapter() {
118            return mAdapter;
119        }
120    }
121
122    private OnActionClickedListener mOnActionClickedListener;
123    private int mLayoutResourceId;
124
125    /**
126     * Constructor for a ControlBarPresenter.
127     *
128     * @param layoutResourceId The resource id of the layout for this presenter.
129     */
130    public ControlBarPresenter(int layoutResourceId) {
131        mLayoutResourceId = layoutResourceId;
132    }
133
134    /**
135     * Returns the layout resource id.
136     */
137    public int getLayoutResourceId() {
138        return mLayoutResourceId;
139    }
140
141    /**
142     * Sets the listener for {@link Action} click events.
143     */
144    public void setOnActionClickedListener(OnActionClickedListener listener) {
145        mOnActionClickedListener = listener;
146    }
147
148    /**
149     * Gets the listener for {@link Action} click events.
150     */
151    public OnActionClickedListener getOnActionClickedListener() {
152        return mOnActionClickedListener;
153    }
154
155    @Override
156    public Presenter.ViewHolder onCreateViewHolder(ViewGroup parent) {
157        View v = LayoutInflater.from(parent.getContext())
158            .inflate(getLayoutResourceId(), parent, false);
159        return new ViewHolder(v);
160    }
161
162    @Override
163    public void onBindViewHolder(Presenter.ViewHolder holder, Object item) {
164        ViewHolder vh = (ViewHolder) holder;
165        BoundData data = (BoundData) item;
166        if (vh.mAdapter != data.adapter) {
167            vh.mAdapter = data.adapter;
168            vh.mAdapter.registerObserver(vh.mDataObserver);
169        }
170        vh.mPresenter = data.presenter;
171        vh.showControls(vh.mAdapter, vh.mPresenter);
172    }
173
174    @Override
175    public void onUnbindViewHolder(Presenter.ViewHolder holder) {
176        ViewHolder vh = (ViewHolder) holder;
177        vh.mAdapter.unregisterObserver(vh.mDataObserver);
178        vh.mAdapter = null;
179    }
180}
181