VerticalGridSupportFragment.java revision 70acb0c19be3831a2080e4f902324de16bfbf62e
1/* This file is auto-generated from VerticalGridFragment.java.  DO NOT MODIFY. */
2
3/*
4 * Copyright (C) 2014 The Android Open Source Project
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
7 * in compliance with the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software distributed under the License
12 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13 * or implied. See the License for the specific language governing permissions and limitations under
14 * the License.
15 */
16package android.support.v17.leanback.app;
17
18import android.support.annotation.ColorInt;
19import android.support.v17.leanback.R;
20import android.support.v17.leanback.transition.TransitionHelper;
21import android.support.v17.leanback.widget.BrowseFrameLayout;
22import android.support.v17.leanback.widget.OnChildLaidOutListener;
23import android.support.v17.leanback.widget.OnItemViewClickedListener;
24import android.support.v17.leanback.widget.OnItemViewSelectedListener;
25import android.support.v17.leanback.widget.Presenter;
26import android.support.v17.leanback.widget.Row;
27import android.support.v17.leanback.widget.RowPresenter;
28import android.support.v17.leanback.widget.TitleView;
29import android.support.v17.leanback.widget.VerticalGridPresenter;
30import android.support.v17.leanback.widget.ObjectAdapter;
31import android.support.v17.leanback.widget.SearchOrbView;
32import android.support.v4.view.ViewCompat;
33import android.support.v4.app.Fragment;
34import android.content.Context;
35import android.graphics.drawable.Drawable;
36import android.os.Bundle;
37import android.util.Log;
38import android.view.LayoutInflater;
39import android.view.View;
40import android.view.ViewGroup;
41import android.view.ViewGroup.MarginLayoutParams;
42import android.widget.ImageView;
43import android.widget.TextView;
44
45/**
46 * A fragment for creating leanback vertical grids.
47 *
48 * <p>Renders a vertical grid of objects given a {@link VerticalGridPresenter} and
49 * an {@link ObjectAdapter}.
50 */
51public class VerticalGridSupportFragment extends Fragment {
52    private static final String TAG = "VerticalGridSupportFragment";
53    private static boolean DEBUG = false;
54
55    private BrowseFrameLayout mBrowseFrame;
56    private String mTitle;
57    private Drawable mBadgeDrawable;
58    private ObjectAdapter mAdapter;
59    private VerticalGridPresenter mGridPresenter;
60    private VerticalGridPresenter.ViewHolder mGridViewHolder;
61    private OnItemViewSelectedListener mOnItemViewSelectedListener;
62    private OnItemViewClickedListener mOnItemViewClickedListener;
63    private View.OnClickListener mExternalOnSearchClickedListener;
64    private int mSelectedPosition = -1;
65
66    private TitleView mTitleView;
67    private SearchOrbView.Colors mSearchAffordanceColors;
68    private boolean mSearchAffordanceColorSet;
69    private boolean mShowingTitle = true;
70
71    // transition related
72    private static TransitionHelper sTransitionHelper = TransitionHelper.getInstance();
73    private Object mTitleUpTransition;
74    private Object mTitleDownTransition;
75    private Object mSceneWithTitle;
76    private Object mSceneWithoutTitle;
77
78    /**
79     * Sets the badge drawable displayed in the title area.
80     */
81    public void setBadgeDrawable(Drawable drawable) {
82        if (drawable != mBadgeDrawable) {
83            mBadgeDrawable = drawable;
84            if (mTitleView != null) {
85                mTitleView.setBadgeDrawable(drawable);
86            }
87        }
88    }
89
90    /**
91     * Returns the badge drawable.
92     */
93    public Drawable getBadgeDrawable() {
94        return mBadgeDrawable;
95    }
96
97    /**
98     * Sets a title for the fragment.
99     */
100    public void setTitle(String title) {
101        mTitle = title;
102        if (mTitleView != null) {
103            mTitleView.setTitle(mTitle);
104        }
105    }
106
107    /**
108     * Returns the title for the fragment.
109     */
110    public String getTitle() {
111        return mTitle;
112    }
113
114    /**
115     * Sets the grid presenter.
116     */
117    public void setGridPresenter(VerticalGridPresenter gridPresenter) {
118        if (gridPresenter == null) {
119            throw new IllegalArgumentException("Grid presenter may not be null");
120        }
121        mGridPresenter = gridPresenter;
122        mGridPresenter.setOnItemViewSelectedListener(mViewSelectedListener);
123        if (mOnItemViewClickedListener != null) {
124            mGridPresenter.setOnItemViewClickedListener(mOnItemViewClickedListener);
125        }
126    }
127
128    /**
129     * Returns the grid presenter.
130     */
131    public VerticalGridPresenter getGridPresenter() {
132        return mGridPresenter;
133    }
134
135    /**
136     * Sets the object adapter for the fragment.
137     */
138    public void setAdapter(ObjectAdapter adapter) {
139        mAdapter = adapter;
140        updateAdapter();
141    }
142
143    /**
144     * Returns the object adapter.
145     */
146    public ObjectAdapter getAdapter() {
147        return mAdapter;
148    }
149
150    final private OnItemViewSelectedListener mViewSelectedListener =
151            new OnItemViewSelectedListener() {
152        @Override
153        public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
154                RowPresenter.ViewHolder rowViewHolder, Row row) {
155            int position = mGridViewHolder.getGridView().getSelectedPosition();
156            if (DEBUG) Log.v(TAG, "grid selected position " + position);
157            gridOnItemSelected(position);
158            if (mOnItemViewSelectedListener != null) {
159                mOnItemViewSelectedListener.onItemSelected(itemViewHolder, item,
160                        rowViewHolder, row);
161            }
162        }
163    };
164
165    final private OnChildLaidOutListener mChildLaidOutListener =
166            new OnChildLaidOutListener() {
167        @Override
168        public void onChildLaidOut(ViewGroup parent, View view, int position, long id) {
169            if (position == 0) {
170                showOrHideTitle();
171            }
172        }
173    };
174
175    /**
176     * Sets an item selection listener.
177     */
178    public void setOnItemViewSelectedListener(OnItemViewSelectedListener listener) {
179        mOnItemViewSelectedListener = listener;
180    }
181
182    private void gridOnItemSelected(int position) {
183        if (position != mSelectedPosition) {
184            mSelectedPosition = position;
185            showOrHideTitle();
186        }
187    }
188
189    private void showOrHideTitle() {
190        if (mGridViewHolder.getGridView().findViewHolderForAdapterPosition(mSelectedPosition)
191                == null) {
192            return;
193        }
194        if (!mGridViewHolder.getGridView().hasPreviousViewInSameRow(mSelectedPosition)) {
195            // if has no sibling in front of it,  show title
196            if (!mShowingTitle) {
197                sTransitionHelper.runTransition(mSceneWithTitle, mTitleDownTransition);
198                mShowingTitle = true;
199            }
200        } else if (mShowingTitle) {
201            sTransitionHelper.runTransition(mSceneWithoutTitle, mTitleUpTransition);
202            mShowingTitle = false;
203        }
204    }
205
206    /**
207     * Sets an item clicked listener.
208     */
209    public void setOnItemViewClickedListener(OnItemViewClickedListener listener) {
210        mOnItemViewClickedListener = listener;
211        if (mGridPresenter != null) {
212            mGridPresenter.setOnItemViewClickedListener(mOnItemViewClickedListener);
213        }
214    }
215
216    /**
217     * Returns the item clicked listener.
218     */
219    public OnItemViewClickedListener getOnItemViewClickedListener() {
220        return mOnItemViewClickedListener;
221    }
222
223    /**
224     * Sets a click listener for the search affordance.
225     *
226     * <p>The presence of a listener will change the visibility of the search
227     * affordance in the title area. When set to non-null, the title area will
228     * contain a call to search action.
229     *
230     * <p>The listener's onClick method will be invoked when the user clicks on
231     * the search action.
232     *
233     * @param listener The listener to invoke when the search affordance is
234     *        clicked, or null to hide the search affordance.
235     */
236    public void setOnSearchClickedListener(View.OnClickListener listener) {
237        mExternalOnSearchClickedListener = listener;
238        if (mTitleView != null) {
239            mTitleView.setOnSearchClickedListener(listener);
240        }
241    }
242
243    /**
244     * Sets the {@link SearchOrbView.Colors} used to draw the search affordance.
245     */
246    public void setSearchAffordanceColors(SearchOrbView.Colors colors) {
247        mSearchAffordanceColors = colors;
248        mSearchAffordanceColorSet = true;
249        if (mTitleView != null) {
250            mTitleView.setSearchAffordanceColors(mSearchAffordanceColors);
251        }
252    }
253
254    /**
255     * Returns the {@link SearchOrbView.Colors} used to draw the search affordance.
256     */
257    public SearchOrbView.Colors getSearchAffordanceColors() {
258        if (mSearchAffordanceColorSet) {
259            return mSearchAffordanceColors;
260        }
261        if (mTitleView == null) {
262            throw new IllegalStateException("Fragment views not yet created");
263        }
264        return mTitleView.getSearchAffordanceColors();
265    }
266
267    /**
268     * Sets the color used to draw the search affordance.
269     * A default brighter color will be set by the framework.
270     *
271     * @param color The color to use for the search affordance.
272     */
273    public void setSearchAffordanceColor(@ColorInt int color) {
274        setSearchAffordanceColors(new SearchOrbView.Colors(color));
275    }
276
277    /**
278     * Returns the color used to draw the search affordance.
279     */
280    @ColorInt
281    public int getSearchAffordanceColor() {
282        return getSearchAffordanceColors().color;
283    }
284
285    private final BrowseFrameLayout.OnFocusSearchListener mOnFocusSearchListener =
286            new BrowseFrameLayout.OnFocusSearchListener() {
287        @Override
288        public View onFocusSearch(View focused, int direction) {
289            if (DEBUG) Log.v(TAG, "onFocusSearch focused " + focused + " + direction " + direction);
290
291            final View searchOrbView = mTitleView.getSearchAffordanceView();
292            final boolean isRtl = ViewCompat.getLayoutDirection(focused) ==
293                    View.LAYOUT_DIRECTION_RTL;
294            final int forward = isRtl ? View.FOCUS_LEFT : View.FOCUS_RIGHT;
295            if (focused == searchOrbView && (
296                    direction == View.FOCUS_DOWN || direction == forward)) {
297                return mGridViewHolder.view;
298
299            } else if (focused != searchOrbView && searchOrbView.getVisibility() == View.VISIBLE
300                    && direction == View.FOCUS_UP) {
301                return searchOrbView;
302
303            } else {
304                return null;
305            }
306        }
307    };
308
309    @Override
310    public View onCreateView(LayoutInflater inflater, ViewGroup container,
311            Bundle savedInstanceState) {
312        ViewGroup root = (ViewGroup) inflater.inflate(R.layout.lb_vertical_grid_fragment,
313                container, false);
314
315        mBrowseFrame = (BrowseFrameLayout) root.findViewById(R.id.browse_frame);
316        mBrowseFrame.setOnFocusSearchListener(mOnFocusSearchListener);
317
318        mTitleView = (TitleView) root.findViewById(R.id.browse_title_group);
319        mTitleView.setBadgeDrawable(mBadgeDrawable);
320        mTitleView.setTitle(mTitle);
321        if (mSearchAffordanceColorSet) {
322            mTitleView.setSearchAffordanceColors(mSearchAffordanceColors);
323        }
324        if (mExternalOnSearchClickedListener != null) {
325            mTitleView.setOnSearchClickedListener(mExternalOnSearchClickedListener);
326        }
327
328        mSceneWithTitle = sTransitionHelper.createScene(root, new Runnable() {
329            @Override
330            public void run() {
331                mTitleView.setVisibility(View.VISIBLE);
332            }
333        });
334        mSceneWithoutTitle = sTransitionHelper.createScene(root, new Runnable() {
335            @Override
336            public void run() {
337                mTitleView.setVisibility(View.INVISIBLE);
338            }
339        });
340        Context context = getActivity();
341        mTitleUpTransition = sTransitionHelper.loadTransition(context, R.transition.lb_title_out);
342        mTitleDownTransition = sTransitionHelper.loadTransition(context, R.transition.lb_title_in);
343
344        return root;
345    }
346
347    @Override
348    public void onViewCreated(View view, Bundle savedInstanceState) {
349        ViewGroup gridDock = (ViewGroup) view.findViewById(R.id.browse_grid_dock);
350        mGridViewHolder = mGridPresenter.onCreateViewHolder(gridDock);
351        gridDock.addView(mGridViewHolder.view);
352        mGridViewHolder.getGridView().setOnChildLaidOutListener(mChildLaidOutListener);
353
354        updateAdapter();
355    }
356
357    @Override
358    public void onStart() {
359        super.onStart();
360        mGridViewHolder.getGridView().requestFocus();
361    }
362
363    @Override
364    public void onPause() {
365        mTitleView.enableAnimation(false);
366        super.onPause();
367    }
368
369    @Override
370    public void onResume() {
371        super.onResume();
372        mTitleView.enableAnimation(true);
373    }
374
375    @Override
376    public void onDestroyView() {
377        super.onDestroyView();
378        mGridViewHolder = null;
379    }
380
381    /**
382     * Sets the selected item position.
383     */
384    public void setSelectedPosition(int position) {
385        mSelectedPosition = position;
386        if(mGridViewHolder != null && mGridViewHolder.getGridView().getAdapter() != null) {
387            mGridViewHolder.getGridView().setSelectedPositionSmooth(position);
388        }
389    }
390
391    private void updateAdapter() {
392        if (mGridViewHolder != null) {
393            mGridPresenter.onBindViewHolder(mGridViewHolder, mAdapter);
394            if (mSelectedPosition != -1) {
395                mGridViewHolder.getGridView().setSelectedPosition(mSelectedPosition);
396            }
397        }
398    }
399}
400