VerticalGridFragment.java revision 4c0f3062b5edd9750351068f46e5270bb220091d
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;
18731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stoutimport android.support.v17.leanback.widget.TitleView;
19739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.support.v17.leanback.widget.VerticalGridPresenter;
20739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.support.v17.leanback.widget.ObjectAdapter;
21739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.support.v17.leanback.widget.OnItemClickedListener;
22739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.support.v17.leanback.widget.OnItemSelectedListener;
23739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.support.v17.leanback.widget.SearchOrbView;
24739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.app.Fragment;
25739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.graphics.drawable.Drawable;
26739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.os.Bundle;
2725aacd3f5896ec09053739cc731bdbab3a6f2b81Jerome Poichetimport android.util.Log;
28739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.view.LayoutInflater;
29739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.view.View;
30739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.view.ViewGroup;
319020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stoutimport android.view.ViewGroup.MarginLayoutParams;
32739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.widget.ImageView;
33739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.widget.TextView;
34739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
35739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout/**
364c0f3062b5edd9750351068f46e5270bb220091dTim Kilbourn * A fragment for creating leanback vertical grids.
37739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout *
384c0f3062b5edd9750351068f46e5270bb220091dTim Kilbourn * <p>Renders a vertical grid of objects given a {@link VerticalGridPresenter} and
39739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * an {@link ObjectAdapter}.
40739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout */
41739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutpublic class VerticalGridFragment extends Fragment {
42739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private static final String TAG = "VerticalGridFragment";
43739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private static boolean DEBUG = false;
44739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
459020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout    private BrowseFrameLayout mBrowseFrame;
46dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    private String mTitle;
47dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    private Drawable mBadgeDrawable;
48739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private ObjectAdapter mAdapter;
49739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private VerticalGridPresenter mGridPresenter;
50739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private VerticalGridPresenter.ViewHolder mGridViewHolder;
51739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private OnItemSelectedListener mOnItemSelectedListener;
52739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private OnItemClickedListener mOnItemClickedListener;
53a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn    private View.OnClickListener mExternalOnSearchClickedListener;
54739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private int mSelectedPosition = -1;
55739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
56731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout    private TitleView mTitleView;
57731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout    private int mSearchAffordanceColor;
58731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout    private boolean mSearchAffordanceColorSet;
59e34cae48707e70442aca13e1b4ab55757292828dDake Gu    private boolean mShowingTitle = true;
60e34cae48707e70442aca13e1b4ab55757292828dDake Gu
61e34cae48707e70442aca13e1b4ab55757292828dDake Gu    // transition related
62e34cae48707e70442aca13e1b4ab55757292828dDake Gu    private static TransitionHelper sTransitionHelper = TransitionHelper.getInstance();
63731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout    private Object mTitleUpTransition;
64731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout    private Object mTitleDownTransition;
65e34cae48707e70442aca13e1b4ab55757292828dDake Gu    private Object mSceneWithTitle;
66e34cae48707e70442aca13e1b4ab55757292828dDake Gu    private Object mSceneWithoutTitle;
67739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
68739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
69dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     * Sets the badge drawable displayed in the title area.
70dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     */
71dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    public void setBadgeDrawable(Drawable drawable) {
72dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout        if (drawable != mBadgeDrawable) {
73dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout            mBadgeDrawable = drawable;
74731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout            if (mTitleView != null) {
75731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout                mTitleView.setBadgeDrawable(drawable);
76731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout            }
77dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout        }
78dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    }
79dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout
80dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    /**
81dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     * Returns the badge drawable.
82dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     */
83dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    public Drawable getBadgeDrawable() {
84dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout        return mBadgeDrawable;
85dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    }
86dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout
87dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    /**
88dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     * Sets a title for the fragment.
89dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     */
90dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    public void setTitle(String title) {
91dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout        mTitle = title;
92dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout        if (mTitleView != null) {
93731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout            mTitleView.setTitle(mTitle);
94dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout        }
95dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    }
96dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout
97dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    /**
98dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     * Returns the title for the fragment.
99dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     */
100dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    public String getTitle() {
101dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout        return mTitle;
102dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    }
103dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout
104dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout    /**
105dfb60d0af5d49da05c584d74245c616263f26b65Craig Stout     * Sets the grid presenter.
106739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
107739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void setGridPresenter(VerticalGridPresenter gridPresenter) {
108739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        if (gridPresenter == null) {
109739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            throw new IllegalArgumentException("Grid presenter may not be null");
110739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
111739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mGridPresenter = gridPresenter;
112e34cae48707e70442aca13e1b4ab55757292828dDake Gu        mGridPresenter.setOnItemSelectedListener(mRowSelectedListener);
113739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        if (mOnItemClickedListener != null) {
114739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            mGridPresenter.setOnItemClickedListener(mOnItemClickedListener);
115739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
116739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
117739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
118739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
119739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Returns the grid presenter.
120739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
121739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public VerticalGridPresenter getGridPresenter() {
122739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        return mGridPresenter;
123739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
124739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
125739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
126739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Sets the object adapter for the fragment.
127739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
128739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void setAdapter(ObjectAdapter adapter) {
129739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mAdapter = adapter;
130739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        updateAdapter();
131739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
132739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
133739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
134739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Returns the object adapter.
135739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
136739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public ObjectAdapter getAdapter() {
137739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        return mAdapter;
138739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
139739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
140e34cae48707e70442aca13e1b4ab55757292828dDake Gu    final private OnItemSelectedListener mRowSelectedListener = new OnItemSelectedListener() {
141e34cae48707e70442aca13e1b4ab55757292828dDake Gu        @Override
142e34cae48707e70442aca13e1b4ab55757292828dDake Gu        public void onItemSelected(Object item, Row row) {
143e34cae48707e70442aca13e1b4ab55757292828dDake Gu            int position = mGridViewHolder.getGridView().getSelectedPosition();
144e34cae48707e70442aca13e1b4ab55757292828dDake Gu            if (DEBUG) Log.v(TAG, "row selected position " + position);
145e34cae48707e70442aca13e1b4ab55757292828dDake Gu            onRowSelected(position);
146e34cae48707e70442aca13e1b4ab55757292828dDake Gu            if (mOnItemSelectedListener != null) {
147e34cae48707e70442aca13e1b4ab55757292828dDake Gu                mOnItemSelectedListener.onItemSelected(item, row);
148e34cae48707e70442aca13e1b4ab55757292828dDake Gu            }
149e34cae48707e70442aca13e1b4ab55757292828dDake Gu        }
150e34cae48707e70442aca13e1b4ab55757292828dDake Gu    };
151e34cae48707e70442aca13e1b4ab55757292828dDake Gu
152739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
153739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Sets an item selection listener.
154739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
155739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void setOnItemSelectedListener(OnItemSelectedListener listener) {
156739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mOnItemSelectedListener = listener;
157739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
158739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
159e34cae48707e70442aca13e1b4ab55757292828dDake Gu    private void onRowSelected(int position) {
160e34cae48707e70442aca13e1b4ab55757292828dDake Gu        if (position != mSelectedPosition) {
161e34cae48707e70442aca13e1b4ab55757292828dDake Gu            if (!mGridViewHolder.getGridView().hasPreviousViewInSameRow(position)) {
162e34cae48707e70442aca13e1b4ab55757292828dDake Gu                // if has no sibling in front of it,  show title
163e34cae48707e70442aca13e1b4ab55757292828dDake Gu                if (!mShowingTitle) {
164731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout                    sTransitionHelper.runTransition(mSceneWithTitle, mTitleDownTransition);
165e34cae48707e70442aca13e1b4ab55757292828dDake Gu                    mShowingTitle = true;
166e34cae48707e70442aca13e1b4ab55757292828dDake Gu                }
167e34cae48707e70442aca13e1b4ab55757292828dDake Gu            } else if (mShowingTitle) {
168731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout                sTransitionHelper.runTransition(mSceneWithoutTitle, mTitleUpTransition);
169e34cae48707e70442aca13e1b4ab55757292828dDake Gu                mShowingTitle = false;
170e34cae48707e70442aca13e1b4ab55757292828dDake Gu            }
171e34cae48707e70442aca13e1b4ab55757292828dDake Gu            mSelectedPosition = position;
172e34cae48707e70442aca13e1b4ab55757292828dDake Gu        }
173e34cae48707e70442aca13e1b4ab55757292828dDake Gu    }
174739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
175739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
176739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Sets an item clicked listener.
177739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
178739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void setOnItemClickedListener(OnItemClickedListener listener) {
179739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mOnItemClickedListener = listener;
180739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        if (mGridPresenter != null) {
181739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            mGridPresenter.setOnItemClickedListener(mOnItemClickedListener);
182739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
183739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
184739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
185739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
186739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Returns the item clicked listener.
187739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
188739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public OnItemClickedListener getOnItemClickedListener() {
189739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        return mOnItemClickedListener;
190739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
191739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
192a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn    /**
193a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn     * Sets a click listener for the search affordance.
194a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn     *
1954c0f3062b5edd9750351068f46e5270bb220091dTim Kilbourn     * <p>The presence of a listener will change the visibility of the search
1964c0f3062b5edd9750351068f46e5270bb220091dTim Kilbourn     * affordance in the title area. When set to non-null, the title area will
1974c0f3062b5edd9750351068f46e5270bb220091dTim Kilbourn     * contain a call to search action.
198a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn     *
1994c0f3062b5edd9750351068f46e5270bb220091dTim Kilbourn     * <p>The listener's onClick method will be invoked when the user clicks on
2004c0f3062b5edd9750351068f46e5270bb220091dTim Kilbourn     * the search action.
201a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn     *
2024c0f3062b5edd9750351068f46e5270bb220091dTim Kilbourn     * @param listener The listener to invoke when the search affordance is
2034c0f3062b5edd9750351068f46e5270bb220091dTim Kilbourn     *        clicked, or null to hide the search affordance.
204a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn     */
205a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn    public void setOnSearchClickedListener(View.OnClickListener listener) {
206a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn        mExternalOnSearchClickedListener = listener;
207731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout        if (mTitleView != null) {
208731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout            mTitleView.setOnSearchClickedListener(listener);
209731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout        }
210731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout    }
211731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout
212731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout    /**
213731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout     * Sets the color used to draw the search affordance.
214731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout     */
215731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout    public void setSearchAffordanceColor(int color) {
216731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout        mSearchAffordanceColor = color;
217731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout        mSearchAffordanceColorSet = true;
218731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout        if (mTitleView != null) {
219731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout            mTitleView.setSearchAffordanceColor(mSearchAffordanceColor);
220a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn        }
221a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn    }
222a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn
223731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout    /**
224731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout     * Returns the color used to draw the search affordance.
225731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout     */
226731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout    public int getSearchAffordanceColor() {
227731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout        if (mSearchAffordanceColorSet) {
228731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout            return mSearchAffordanceColor;
229739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
230731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout        if (mTitleView == null) {
231731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout            throw new IllegalStateException("Fragment views not yet created");
232739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
233731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout        return mTitleView.getSearchAffordanceColor();
234739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
235739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
236731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout
2379020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout    private final BrowseFrameLayout.OnFocusSearchListener mOnFocusSearchListener =
2389020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout            new BrowseFrameLayout.OnFocusSearchListener() {
2399020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout        @Override
2409020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout        public View onFocusSearch(View focused, int direction) {
2419020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout            if (DEBUG) Log.v(TAG, "onFocusSearch focused " + focused + " + direction " + direction);
2429020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout
243731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout            final View searchOrbView = mTitleView.getSearchAffordanceView();
244731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout            if (focused == searchOrbView && (
2459020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout                    direction == View.FOCUS_DOWN || direction == View.FOCUS_RIGHT)) {
2469020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout                return mGridViewHolder.view;
2479020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout
248731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout            } else if (focused != searchOrbView && searchOrbView.getVisibility() == View.VISIBLE
2499020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout                    && direction == View.FOCUS_UP) {
250731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout                return searchOrbView;
2519020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout
2529020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout            } else {
2539020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout                return null;
2549020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout            }
2559020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout        }
2569020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout    };
2579020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout
258739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    @Override
259739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public View onCreateView(LayoutInflater inflater, ViewGroup container,
260739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            Bundle savedInstanceState) {
261e34cae48707e70442aca13e1b4ab55757292828dDake Gu        ViewGroup root = (ViewGroup) inflater.inflate(R.layout.lb_vertical_grid_fragment,
262e34cae48707e70442aca13e1b4ab55757292828dDake Gu                container, false);
263739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
2649020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout        mBrowseFrame = (BrowseFrameLayout) root.findViewById(R.id.browse_frame);
2659020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout        mBrowseFrame.setOnFocusSearchListener(mOnFocusSearchListener);
2669020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout
267731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout        mTitleView = (TitleView) root.findViewById(R.id.browse_title_group);
268731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout        mTitleView.setBadgeDrawable(mBadgeDrawable);
269731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout        mTitleView.setTitle(mTitle);
270731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout        if (mSearchAffordanceColorSet) {
271731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout            mTitleView.setSearchAffordanceColor(mSearchAffordanceColor);
272731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout        }
273a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn        if (mExternalOnSearchClickedListener != null) {
274731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout            mTitleView.setOnSearchClickedListener(mExternalOnSearchClickedListener);
275a8d3588c80a232042474aca55a69df78c8ac8cb3Tim Kilbourn        }
276739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
277e34cae48707e70442aca13e1b4ab55757292828dDake Gu        mSceneWithTitle = sTransitionHelper.createScene(root, new Runnable() {
278e34cae48707e70442aca13e1b4ab55757292828dDake Gu            @Override
279e34cae48707e70442aca13e1b4ab55757292828dDake Gu            public void run() {
280731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout                TitleTransitionHelper.showTitle(mTitleView, true);
281e34cae48707e70442aca13e1b4ab55757292828dDake Gu            }
282e34cae48707e70442aca13e1b4ab55757292828dDake Gu        });
283e34cae48707e70442aca13e1b4ab55757292828dDake Gu        mSceneWithoutTitle = sTransitionHelper.createScene(root, new Runnable() {
284e34cae48707e70442aca13e1b4ab55757292828dDake Gu            @Override
285e34cae48707e70442aca13e1b4ab55757292828dDake Gu            public void run() {
286731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout                TitleTransitionHelper.showTitle(mTitleView, false);
287e34cae48707e70442aca13e1b4ab55757292828dDake Gu            }
288e34cae48707e70442aca13e1b4ab55757292828dDake Gu        });
289731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout        mTitleUpTransition = TitleTransitionHelper.createTransitionTitleUp(sTransitionHelper);
290731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout        mTitleDownTransition = TitleTransitionHelper.createTransitionTitleDown(sTransitionHelper);
291731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout        sTransitionHelper.excludeChildren(mTitleUpTransition, R.id.browse_grid_dock, true);
292731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout        sTransitionHelper.excludeChildren(mTitleDownTransition, R.id.browse_grid_dock, true);
293739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
294731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout        return root;
2959020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout    }
2969020c0aec57b4e8994d66b7cd1a89c225e9bfa11Craig Stout
297739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    @Override
298739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void onViewCreated(View view, Bundle savedInstanceState) {
299739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        ViewGroup gridDock = (ViewGroup) view.findViewById(R.id.browse_grid_dock);
300739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mGridViewHolder = mGridPresenter.onCreateViewHolder(gridDock);
301739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        gridDock.addView(mGridViewHolder.view);
302739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
303739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        updateAdapter();
304739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
305739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
306739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    @Override
307739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void onStart() {
308739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        super.onStart();
309739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mGridViewHolder.getGridView().requestFocus();
310739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
311739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
312739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    @Override
313739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void onDestroyView() {
314739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        super.onDestroyView();
315739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mGridViewHolder = null;
316739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
317739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
318739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
319739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Sets the selected item position.
320739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
321739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void setSelectedPosition(int position) {
322739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        mSelectedPosition = position;
323739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        if(mGridViewHolder != null && mGridViewHolder.getGridView().getAdapter() != null) {
324739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            mGridViewHolder.getGridView().setSelectedPositionSmooth(position);
325739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
326739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
327739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
328739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private void updateAdapter() {
329739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        if (mGridViewHolder != null) {
330739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            mGridPresenter.onBindViewHolder(mGridViewHolder, mAdapter);
331739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            if (mSelectedPosition != -1) {
332739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout                mGridViewHolder.getGridView().setSelectedPosition(mSelectedPosition);
333739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            }
334739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
335739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
336739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout}
337