VerticalGridFragment.java revision 9020c0aec57b4e8994d66b7cd1a89c225e9bfa11
1739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout/*
2739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * Copyright (C) 2014 The Android Open Source Project
3739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout *
4739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * in compliance with the License. You may obtain a copy of the License at
6739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout *
7739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * http://www.apache.org/licenses/LICENSE-2.0
8739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout *
9739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * Unless required by applicable law or agreed to in writing, software distributed under the License
10739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * or implied. See the License for the specific language governing permissions and limitations under
12739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * the License.
13739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout */
14739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutpackage android.support.v17.leanback.app;
15739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
16739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.support.v17.leanback.R;
17e34cae48707e70442aca13e1b4ab55757292828dDake Guimport android.support.v17.leanback.widget.Row;
18739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.support.v17.leanback.widget.VerticalGridPresenter;
19739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.support.v17.leanback.widget.ObjectAdapter;
20739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.support.v17.leanback.widget.OnItemClickedListener;
21739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.support.v17.leanback.widget.OnItemSelectedListener;
22739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.support.v17.leanback.widget.SearchOrbView;
23739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.app.Fragment;
24739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.graphics.drawable.Drawable;
25739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.os.Bundle;
2625aacd3f5896ec09053739cc731bdbab3a6f2b81Jerome Poichetimport android.util.Log;
27739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.view.LayoutInflater;
28739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.view.View;
29739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.view.ViewGroup;
309020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stoutimport android.view.ViewGroup.MarginLayoutParams;
31739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.widget.ImageView;
32739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.widget.TextView;
33739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
34739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout/**
35739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * Leanback fragment for a vertical grid.
36739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout *
37739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * Renders a vertical grid of objects given a {@link VerticalGridPresenter} and
38739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * an {@link ObjectAdapter}.
39739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout */
40739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutpublic class VerticalGridFragment extends Fragment {
41739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private static final String TAG = "VerticalGridFragment";
42739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private static boolean DEBUG = false;
43739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
44dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    // TODO: remove Params
45739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private Params mParams;
46dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout
479020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout    private BrowseFrameLayout mBrowseFrame;
48dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    private String mTitle;
49dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    private Drawable mBadgeDrawable;
50739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private ObjectAdapter mAdapter;
51739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private VerticalGridPresenter mGridPresenter;
52739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private VerticalGridPresenter.ViewHolder mGridViewHolder;
53739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private OnItemSelectedListener mOnItemSelectedListener;
54739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private OnItemClickedListener mOnItemClickedListener;
55a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn    private View.OnClickListener mExternalOnSearchClickedListener;
56739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private int mSelectedPosition = -1;
57739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
58739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private ImageView mBadgeView;
59739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private TextView mTitleView;
60739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private ViewGroup mBrowseTitle;
61739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private SearchOrbView mSearchOrbView;
62e34cae48707e70442aca13e1b4ab55757292828dDake Gu    private boolean mShowingTitle = true;
63e34cae48707e70442aca13e1b4ab55757292828dDake Gu
64e34cae48707e70442aca13e1b4ab55757292828dDake Gu    // transition related
65e34cae48707e70442aca13e1b4ab55757292828dDake Gu    private static TransitionHelper sTransitionHelper = TransitionHelper.getInstance();
66e34cae48707e70442aca13e1b4ab55757292828dDake Gu    private Object mTitleTransition;
67e34cae48707e70442aca13e1b4ab55757292828dDake Gu    private Object mSceneWithTitle;
68e34cae48707e70442aca13e1b4ab55757292828dDake Gu    private Object mSceneWithoutTitle;
69739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
70dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    @Deprecated
71739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public static class Params {
72739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        private String mTitle;
73739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        private Drawable mBadgeDrawable;
74739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
75739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        /**
76739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout         * Sets the badge image.
77739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout         */
78739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        public void setBadgeImage(Drawable drawable) {
79739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            mBadgeDrawable = drawable;
80739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
81739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
82739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        /**
83739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout         * Returns the badge image.
84739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout         */
85739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        public Drawable getBadgeImage() {
86739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            return mBadgeDrawable;
87739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
88739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
89739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        /**
90739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout         * Sets a title for the browse fragment.
91739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout         */
92739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        public void setTitle(String title) {
93739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            mTitle = title;
94739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
95739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
96739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        /**
97739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout         * Returns the title for the browse fragment.
98739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout         */
99739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        public String getTitle() {
100739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            return mTitle;
101739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
102739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
103739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
104739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
105739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Set fragment parameters.
106dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     * @deprecated Use methods on the fragment directly.
107739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
108dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    @Deprecated
109739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void setParams(Params params) {
110739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mParams = params;
111739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        setBadgeDrawable(mParams.mBadgeDrawable);
112739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        setTitle(mParams.mTitle);
113739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
114739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
115739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
116739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Returns fragment parameters.
117dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     * @deprecated Use methods on the fragment directly.
118739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
119dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    @Deprecated
120739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public Params getParams() {
121739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        return mParams;
122739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
123739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
124739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
125dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     * Sets the badge drawable displayed in the title area.
126dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     */
127dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    public void setBadgeDrawable(Drawable drawable) {
128dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout        if (drawable != mBadgeDrawable) {
129dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout            mBadgeDrawable = drawable;
130dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout            setBadgeViewImage();
131dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout        }
132dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    }
133dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout
134dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    /**
135dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     * Returns the badge drawable.
136dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     */
137dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    public Drawable getBadgeDrawable() {
138dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout        return mBadgeDrawable;
139dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    }
140dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout
141dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    /**
142dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     * Sets a title for the fragment.
143dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     */
144dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    public void setTitle(String title) {
145dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout        mTitle = title;
146dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout        if (mTitleView != null) {
147dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout            mTitleView.setText(mTitle);
148dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout        }
149dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    }
150dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout
151dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    /**
152dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     * Returns the title for the fragment.
153dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     */
154dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    public String getTitle() {
155dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout        return mTitle;
156dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    }
157dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout
158dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    /**
159dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     * Sets the grid presenter.
160739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
161739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void setGridPresenter(VerticalGridPresenter gridPresenter) {
162739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        if (gridPresenter == null) {
163739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            throw new IllegalArgumentException("Grid presenter may not be null");
164739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
165739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mGridPresenter = gridPresenter;
166e34cae48707e70442aca13e1b4ab55757292828dDake Gu        mGridPresenter.setOnItemSelectedListener(mRowSelectedListener);
167739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        if (mOnItemClickedListener != null) {
168739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            mGridPresenter.setOnItemClickedListener(mOnItemClickedListener);
169739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
170739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
171739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
172739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
173739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Returns the grid presenter.
174739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
175739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public VerticalGridPresenter getGridPresenter() {
176739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        return mGridPresenter;
177739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
178739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
179739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
180739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Sets the object adapter for the fragment.
181739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
182739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void setAdapter(ObjectAdapter adapter) {
183739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mAdapter = adapter;
184739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        updateAdapter();
185739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
186739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
187739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
188739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Returns the object adapter.
189739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
190739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public ObjectAdapter getAdapter() {
191739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        return mAdapter;
192739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
193739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
194e34cae48707e70442aca13e1b4ab55757292828dDake Gu    final private OnItemSelectedListener mRowSelectedListener = new OnItemSelectedListener() {
195e34cae48707e70442aca13e1b4ab55757292828dDake Gu        @Override
196e34cae48707e70442aca13e1b4ab55757292828dDake Gu        public void onItemSelected(Object item, Row row) {
197e34cae48707e70442aca13e1b4ab55757292828dDake Gu            int position = mGridViewHolder.getGridView().getSelectedPosition();
198e34cae48707e70442aca13e1b4ab55757292828dDake Gu            if (DEBUG) Log.v(TAG, "row selected position " + position);
199e34cae48707e70442aca13e1b4ab55757292828dDake Gu            onRowSelected(position);
200e34cae48707e70442aca13e1b4ab55757292828dDake Gu            if (mOnItemSelectedListener != null) {
201e34cae48707e70442aca13e1b4ab55757292828dDake Gu                mOnItemSelectedListener.onItemSelected(item, row);
202e34cae48707e70442aca13e1b4ab55757292828dDake Gu            }
203e34cae48707e70442aca13e1b4ab55757292828dDake Gu        }
204e34cae48707e70442aca13e1b4ab55757292828dDake Gu    };
205e34cae48707e70442aca13e1b4ab55757292828dDake Gu
206739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
207739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Sets an item selection listener.
208739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
209739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void setOnItemSelectedListener(OnItemSelectedListener listener) {
210739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mOnItemSelectedListener = listener;
211739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
212739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
213e34cae48707e70442aca13e1b4ab55757292828dDake Gu    private void onRowSelected(int position) {
214e34cae48707e70442aca13e1b4ab55757292828dDake Gu        if (position != mSelectedPosition) {
215e34cae48707e70442aca13e1b4ab55757292828dDake Gu            if (!mGridViewHolder.getGridView().hasPreviousViewInSameRow(position)) {
216e34cae48707e70442aca13e1b4ab55757292828dDake Gu                // if has no sibling in front of it,  show title
217e34cae48707e70442aca13e1b4ab55757292828dDake Gu                if (!mShowingTitle) {
218e34cae48707e70442aca13e1b4ab55757292828dDake Gu                    sTransitionHelper.runTransition(mSceneWithTitle, mTitleTransition);
219e34cae48707e70442aca13e1b4ab55757292828dDake Gu                    mShowingTitle = true;
220e34cae48707e70442aca13e1b4ab55757292828dDake Gu                }
221e34cae48707e70442aca13e1b4ab55757292828dDake Gu            } else if (mShowingTitle) {
222e34cae48707e70442aca13e1b4ab55757292828dDake Gu                sTransitionHelper.runTransition(mSceneWithoutTitle, mTitleTransition);
223e34cae48707e70442aca13e1b4ab55757292828dDake Gu                mShowingTitle = false;
224e34cae48707e70442aca13e1b4ab55757292828dDake Gu            }
225e34cae48707e70442aca13e1b4ab55757292828dDake Gu            mSelectedPosition = position;
226e34cae48707e70442aca13e1b4ab55757292828dDake Gu        }
227e34cae48707e70442aca13e1b4ab55757292828dDake Gu    }
228739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
229739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
230739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Sets an item clicked listener.
231739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
232739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void setOnItemClickedListener(OnItemClickedListener listener) {
233739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mOnItemClickedListener = listener;
234739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        if (mGridPresenter != null) {
235739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            mGridPresenter.setOnItemClickedListener(mOnItemClickedListener);
236739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
237739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
238739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
239739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
240739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Returns the item clicked listener.
241739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
242739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public OnItemClickedListener getOnItemClickedListener() {
243739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        return mOnItemClickedListener;
244739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
245739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
246a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn    /**
247a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn     * Sets a click listener for the search affordance.
248a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn     *
249a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn     * The presence of a listener will change the visibility of the search affordance in the
250a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn     * title area. When set to non-null the title area will contain a call to search action.
251a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn     *
252a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn     * The listener onClick method will be invoked when the user click on the search action.
253a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn     *
254a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn     * @param listener The listener.
255a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn     */
256a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn    public void setOnSearchClickedListener(View.OnClickListener listener) {
257a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn        mExternalOnSearchClickedListener = listener;
258a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn        if (mSearchOrbView != null) {
259a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn            mSearchOrbView.setOnOrbClickedListener(listener);
260a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn        }
261a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn    }
262a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn
263dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    private void setBadgeViewImage() {
264739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        if (mBadgeView == null) {
265739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            return;
266739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
267dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout        mBadgeView.setImageDrawable(mBadgeDrawable);
268dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout        if (mBadgeDrawable != null) {
269739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            mBadgeView.setVisibility(View.VISIBLE);
270dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout            mTitleView.setVisibility(View.GONE);
271739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        } else {
272739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            mBadgeView.setVisibility(View.GONE);
273dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout            mTitleView.setVisibility(View.VISIBLE);
274739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
275739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
276739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
2779020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout    private final BrowseFrameLayout.OnFocusSearchListener mOnFocusSearchListener =
2789020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout            new BrowseFrameLayout.OnFocusSearchListener() {
2799020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout        @Override
2809020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout        public View onFocusSearch(View focused, int direction) {
2819020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout            if (DEBUG) Log.v(TAG, "onFocusSearch focused " + focused + " + direction " + direction);
2829020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout
2839020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout            if (focused == mSearchOrbView && (
2849020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout                    direction == View.FOCUS_DOWN || direction == View.FOCUS_RIGHT)) {
2859020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout                return mGridViewHolder.view;
2869020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout
2879020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout            } else if (focused != mSearchOrbView && mSearchOrbView.getVisibility() == View.VISIBLE
2889020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout                    && direction == View.FOCUS_UP) {
2899020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout                return mSearchOrbView;
2909020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout
2919020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout            } else {
2929020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout                return null;
2939020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout            }
2949020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout        }
2959020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout    };
2969020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout
297739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    @Override
298739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public View onCreateView(LayoutInflater inflater, ViewGroup container,
299739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            Bundle savedInstanceState) {
300e34cae48707e70442aca13e1b4ab55757292828dDake Gu        ViewGroup root = (ViewGroup) inflater.inflate(R.layout.lb_vertical_grid_fragment,
301e34cae48707e70442aca13e1b4ab55757292828dDake Gu                container, false);
302739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
3039020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout        mBrowseFrame = (BrowseFrameLayout) root.findViewById(R.id.browse_frame);
3049020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout        mBrowseFrame.setOnFocusSearchListener(mOnFocusSearchListener);
3059020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout
306739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mBrowseTitle = (ViewGroup) root.findViewById(R.id.browse_title_group);
307739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mBadgeView = (ImageView) mBrowseTitle.findViewById(R.id.browse_badge);
308739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mTitleView = (TextView) mBrowseTitle.findViewById(R.id.browse_title);
309739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mSearchOrbView = (SearchOrbView) mBrowseTitle.findViewById(R.id.browse_orb);
310a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn        if (mExternalOnSearchClickedListener != null) {
311a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn            mSearchOrbView.setOnOrbClickedListener(mExternalOnSearchClickedListener);
312a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn        }
313739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
314dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout        setBadgeViewImage();
315dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout        mTitleView.setText(mTitle);
316739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
317e34cae48707e70442aca13e1b4ab55757292828dDake Gu        mSceneWithTitle = sTransitionHelper.createScene(root, new Runnable() {
318e34cae48707e70442aca13e1b4ab55757292828dDake Gu            @Override
319e34cae48707e70442aca13e1b4ab55757292828dDake Gu            public void run() {
3209020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout                showTitle(true);
321e34cae48707e70442aca13e1b4ab55757292828dDake Gu            }
322e34cae48707e70442aca13e1b4ab55757292828dDake Gu        });
323e34cae48707e70442aca13e1b4ab55757292828dDake Gu        mSceneWithoutTitle = sTransitionHelper.createScene(root, new Runnable() {
324e34cae48707e70442aca13e1b4ab55757292828dDake Gu            @Override
325e34cae48707e70442aca13e1b4ab55757292828dDake Gu            public void run() {
3269020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout                showTitle(false);
327e34cae48707e70442aca13e1b4ab55757292828dDake Gu            }
328e34cae48707e70442aca13e1b4ab55757292828dDake Gu        });
329e34cae48707e70442aca13e1b4ab55757292828dDake Gu        mTitleTransition = sTransitionHelper.createTransitionSet(false);
330e34cae48707e70442aca13e1b4ab55757292828dDake Gu        Object fade = sTransitionHelper.createFadeTransition(
331e34cae48707e70442aca13e1b4ab55757292828dDake Gu                TransitionHelper.FADE_IN | TransitionHelper.FADE_OUT);
332e34cae48707e70442aca13e1b4ab55757292828dDake Gu        Object changeBounds = sTransitionHelper.createChangeBounds(false);
333e34cae48707e70442aca13e1b4ab55757292828dDake Gu        sTransitionHelper.addTransition(mTitleTransition, fade);
334e34cae48707e70442aca13e1b4ab55757292828dDake Gu        sTransitionHelper.addTransition(mTitleTransition, changeBounds);
335e34cae48707e70442aca13e1b4ab55757292828dDake Gu        sTransitionHelper.excludeChildren(mTitleTransition, R.id.browse_grid_dock, true);
336739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        return root;
337739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
338739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
3399020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout    private void showTitle(boolean show) {
3409020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout        MarginLayoutParams lp = (MarginLayoutParams) mBrowseTitle.getLayoutParams();
3419020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout        lp.topMargin = show ? 0 : -mBrowseTitle.getHeight();
3429020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout        mBrowseTitle.setLayoutParams(lp);
3439020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout    }
3449020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout
345739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    @Override
346739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void onViewCreated(View view, Bundle savedInstanceState) {
347739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        ViewGroup gridDock = (ViewGroup) view.findViewById(R.id.browse_grid_dock);
348739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mGridViewHolder = mGridPresenter.onCreateViewHolder(gridDock);
349739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        gridDock.addView(mGridViewHolder.view);
350739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
351739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        updateAdapter();
352739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
353739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
354739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    @Override
355739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void onStart() {
356739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        super.onStart();
357739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mGridViewHolder.getGridView().requestFocus();
358739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
359739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
360739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    @Override
361739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void onDestroyView() {
362739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        super.onDestroyView();
363739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mGridViewHolder = null;
364739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
365739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
366739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
367739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Sets the selected item position.
368739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
369739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void setSelectedPosition(int position) {
370739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mSelectedPosition = position;
371739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        if(mGridViewHolder != null && mGridViewHolder.getGridView().getAdapter() != null) {
372739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            mGridViewHolder.getGridView().setSelectedPositionSmooth(position);
373739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
374739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
375739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
376739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private void updateAdapter() {
377739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        if (mGridViewHolder != null) {
378739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            mGridPresenter.onBindViewHolder(mGridViewHolder, mAdapter);
379739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            if (mSelectedPosition != -1) {
380739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout                mGridViewHolder.getGridView().setSelectedPosition(mSelectedPosition);
381739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            }
382739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
383739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
384739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout}
385