• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // CHECKSTYLE:OFF Generated code
2 /* This file is auto-generated from HeadersSupportFragment.java.  DO NOT MODIFY. */
3 
4 /*
5  * Copyright (C) 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software distributed under the License
13  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14  * or implied. See the License for the specific language governing permissions and limitations under
15  * the License.
16  */
17 
18 package android.support.v17.leanback.app;
19 
20 import android.content.Context;
21 import android.graphics.Color;
22 import android.graphics.drawable.ColorDrawable;
23 import android.graphics.drawable.Drawable;
24 import android.graphics.drawable.GradientDrawable;
25 import android.os.Bundle;
26 import android.support.v17.leanback.R;
27 import android.support.v17.leanback.widget.ClassPresenterSelector;
28 import android.support.v17.leanback.widget.DividerPresenter;
29 import android.support.v17.leanback.widget.DividerRow;
30 import android.support.v17.leanback.widget.FocusHighlightHelper;
31 import android.support.v17.leanback.widget.HorizontalGridView;
32 import android.support.v17.leanback.widget.ItemBridgeAdapter;
33 import android.support.v17.leanback.widget.PresenterSelector;
34 import android.support.v17.leanback.widget.Row;
35 import android.support.v17.leanback.widget.RowHeaderPresenter;
36 import android.support.v17.leanback.widget.SectionRow;
37 import android.support.v17.leanback.widget.VerticalGridView;
38 import android.support.v7.widget.RecyclerView;
39 import android.view.View;
40 import android.view.View.OnLayoutChangeListener;
41 import android.view.ViewGroup;
42 import android.widget.FrameLayout;
43 
44 /**
45  * An fragment containing a list of row headers. Implementation must support three types of rows:
46  * <ul>
47  *     <li>{@link DividerRow} rendered by {@link DividerPresenter}.</li>
48  *     <li>{@link Row} rendered by {@link RowHeaderPresenter}.</li>
49  *     <li>{@link SectionRow} rendered by {@link RowHeaderPresenter}.</li>
50  * </ul>
51  * Use {@link #setPresenterSelector(PresenterSelector)} in subclass constructor to customize
52  * Presenters. App may override {@link BrowseFragment#onCreateHeadersFragment()}.
53  */
54 public class HeadersFragment extends BaseRowFragment {
55 
56     /**
57      * Interface definition for a callback to be invoked when a header item is clicked.
58      */
59     public interface OnHeaderClickedListener {
60         /**
61          * Called when a header item has been clicked.
62          *
63          * @param viewHolder Row ViewHolder object corresponding to the selected Header.
64          * @param row Row object corresponding to the selected Header.
65          */
onHeaderClicked(RowHeaderPresenter.ViewHolder viewHolder, Row row)66         void onHeaderClicked(RowHeaderPresenter.ViewHolder viewHolder, Row row);
67     }
68 
69     /**
70      * Interface definition for a callback to be invoked when a header item is selected.
71      */
72     public interface OnHeaderViewSelectedListener {
73         /**
74          * Called when a header item has been selected.
75          *
76          * @param viewHolder Row ViewHolder object corresponding to the selected Header.
77          * @param row Row object corresponding to the selected Header.
78          */
onHeaderSelected(RowHeaderPresenter.ViewHolder viewHolder, Row row)79         void onHeaderSelected(RowHeaderPresenter.ViewHolder viewHolder, Row row);
80     }
81 
82     private OnHeaderViewSelectedListener mOnHeaderViewSelectedListener;
83     OnHeaderClickedListener mOnHeaderClickedListener;
84     private boolean mHeadersEnabled = true;
85     private boolean mHeadersGone = false;
86     private int mBackgroundColor;
87     private boolean mBackgroundColorSet;
88 
89     private static final PresenterSelector sHeaderPresenter = new ClassPresenterSelector()
90             .addClassPresenter(DividerRow.class, new DividerPresenter())
91             .addClassPresenter(SectionRow.class,
92                     new RowHeaderPresenter(R.layout.lb_section_header, false))
93             .addClassPresenter(Row.class, new RowHeaderPresenter(R.layout.lb_header));
94 
HeadersFragment()95     public HeadersFragment() {
96         setPresenterSelector(sHeaderPresenter);
97         FocusHighlightHelper.setupHeaderItemFocusHighlight(getBridgeAdapter());
98     }
99 
setOnHeaderClickedListener(OnHeaderClickedListener listener)100     public void setOnHeaderClickedListener(OnHeaderClickedListener listener) {
101         mOnHeaderClickedListener = listener;
102     }
103 
setOnHeaderViewSelectedListener(OnHeaderViewSelectedListener listener)104     public void setOnHeaderViewSelectedListener(OnHeaderViewSelectedListener listener) {
105         mOnHeaderViewSelectedListener = listener;
106     }
107 
108     @Override
findGridViewFromRoot(View view)109     VerticalGridView findGridViewFromRoot(View view) {
110         return (VerticalGridView) view.findViewById(R.id.browse_headers);
111     }
112 
113     @Override
onRowSelected(RecyclerView parent, RecyclerView.ViewHolder viewHolder, int position, int subposition)114     void onRowSelected(RecyclerView parent, RecyclerView.ViewHolder viewHolder,
115             int position, int subposition) {
116         if (mOnHeaderViewSelectedListener != null) {
117             if (viewHolder != null && position >= 0) {
118                 ItemBridgeAdapter.ViewHolder vh = (ItemBridgeAdapter.ViewHolder) viewHolder;
119                 mOnHeaderViewSelectedListener.onHeaderSelected(
120                         (RowHeaderPresenter.ViewHolder) vh.getViewHolder(), (Row) vh.getItem());
121             } else {
122                 mOnHeaderViewSelectedListener.onHeaderSelected(null, null);
123             }
124         }
125     }
126 
127     private final ItemBridgeAdapter.AdapterListener mAdapterListener =
128             new ItemBridgeAdapter.AdapterListener() {
129         @Override
130         public void onCreate(final ItemBridgeAdapter.ViewHolder viewHolder) {
131             View headerView = viewHolder.getViewHolder().view;
132             headerView.setOnClickListener(new View.OnClickListener() {
133                 @Override
134                 public void onClick(View v) {
135                     if (mOnHeaderClickedListener != null) {
136                         mOnHeaderClickedListener.onHeaderClicked(
137                                 (RowHeaderPresenter.ViewHolder) viewHolder.getViewHolder(),
138                                 (Row) viewHolder.getItem());
139                     }
140                 }
141             });
142             if (mWrapper != null) {
143                 viewHolder.itemView.addOnLayoutChangeListener(sLayoutChangeListener);
144             } else {
145                 headerView.addOnLayoutChangeListener(sLayoutChangeListener);
146             }
147         }
148 
149     };
150 
151     static OnLayoutChangeListener sLayoutChangeListener = new OnLayoutChangeListener() {
152         @Override
153         public void onLayoutChange(View v, int left, int top, int right, int bottom,
154             int oldLeft, int oldTop, int oldRight, int oldBottom) {
155             v.setPivotX(v.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? v.getWidth() : 0);
156             v.setPivotY(v.getMeasuredHeight() / 2);
157         }
158     };
159 
160     @Override
getLayoutResourceId()161     int getLayoutResourceId() {
162         return R.layout.lb_headers_fragment;
163     }
164 
165     @Override
onViewCreated(View view, Bundle savedInstanceState)166     public void onViewCreated(View view, Bundle savedInstanceState) {
167         super.onViewCreated(view, savedInstanceState);
168         final VerticalGridView listView = getVerticalGridView();
169         if (listView == null) {
170             return;
171         }
172         if (mBackgroundColorSet) {
173             listView.setBackgroundColor(mBackgroundColor);
174             updateFadingEdgeToBrandColor(mBackgroundColor);
175         } else {
176             Drawable d = listView.getBackground();
177             if (d instanceof ColorDrawable) {
178                 updateFadingEdgeToBrandColor(((ColorDrawable) d).getColor());
179             }
180         }
181         updateListViewVisibility();
182     }
183 
updateListViewVisibility()184     private void updateListViewVisibility() {
185         final VerticalGridView listView = getVerticalGridView();
186         if (listView != null) {
187             getView().setVisibility(mHeadersGone ? View.GONE : View.VISIBLE);
188             if (!mHeadersGone) {
189                 if (mHeadersEnabled) {
190                     listView.setChildrenVisibility(View.VISIBLE);
191                 } else {
192                     listView.setChildrenVisibility(View.INVISIBLE);
193                 }
194             }
195         }
196     }
197 
setHeadersEnabled(boolean enabled)198     void setHeadersEnabled(boolean enabled) {
199         mHeadersEnabled = enabled;
200         updateListViewVisibility();
201     }
202 
setHeadersGone(boolean gone)203     void setHeadersGone(boolean gone) {
204         mHeadersGone = gone;
205         updateListViewVisibility();
206     }
207 
208     static class NoOverlappingFrameLayout extends FrameLayout {
209 
NoOverlappingFrameLayout(Context context)210         public NoOverlappingFrameLayout(Context context) {
211             super(context);
212         }
213 
214         /**
215          * Avoid creating hardware layer for header dock.
216          */
217         @Override
hasOverlappingRendering()218         public boolean hasOverlappingRendering() {
219             return false;
220         }
221     }
222 
223     // Wrapper needed because of conflict between RecyclerView's use of alpha
224     // for ADD animations, and RowHeaderPresenter's use of alpha for selected level.
225     final ItemBridgeAdapter.Wrapper mWrapper = new ItemBridgeAdapter.Wrapper() {
226         @Override
227         public void wrap(View wrapper, View wrapped) {
228             ((FrameLayout) wrapper).addView(wrapped);
229         }
230 
231         @Override
232         public View createWrapper(View root) {
233             return new NoOverlappingFrameLayout(root.getContext());
234         }
235     };
236     @Override
updateAdapter()237     void updateAdapter() {
238         super.updateAdapter();
239         ItemBridgeAdapter adapter = getBridgeAdapter();
240         adapter.setAdapterListener(mAdapterListener);
241         adapter.setWrapper(mWrapper);
242     }
243 
setBackgroundColor(int color)244     void setBackgroundColor(int color) {
245         mBackgroundColor = color;
246         mBackgroundColorSet = true;
247 
248         if (getVerticalGridView() != null) {
249             getVerticalGridView().setBackgroundColor(mBackgroundColor);
250             updateFadingEdgeToBrandColor(mBackgroundColor);
251         }
252     }
253 
updateFadingEdgeToBrandColor(int backgroundColor)254     private void updateFadingEdgeToBrandColor(int backgroundColor) {
255         View fadingView = getView().findViewById(R.id.fade_out_edge);
256         Drawable background = fadingView.getBackground();
257         if (background instanceof GradientDrawable) {
258             background.mutate();
259             ((GradientDrawable) background).setColors(
260                     new int[] {Color.TRANSPARENT, backgroundColor});
261         }
262     }
263 
264     @Override
onTransitionStart()265     public void onTransitionStart() {
266         super.onTransitionStart();
267         if (!mHeadersEnabled) {
268             // When enabling headers fragment,  the RowHeaderView gets a focus but
269             // isShown() is still false because its parent is INVISIBLE, accessibility
270             // event is not sent.
271             // Workaround is: prevent focus to a child view during transition and put
272             // focus on it after transition is done.
273             final VerticalGridView listView = getVerticalGridView();
274             if (listView != null) {
275                 listView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
276                 if (listView.hasFocus()) {
277                     listView.requestFocus();
278                 }
279             }
280         }
281     }
282 
283     @Override
onTransitionEnd()284     public void onTransitionEnd() {
285         if (mHeadersEnabled) {
286             final VerticalGridView listView = getVerticalGridView();
287             if (listView != null) {
288                 listView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
289                 if (listView.hasFocus()) {
290                     listView.requestFocus();
291                 }
292             }
293         }
294         super.onTransitionEnd();
295     }
296 
isScrolling()297     public boolean isScrolling() {
298         return getVerticalGridView().getScrollState()
299                 != HorizontalGridView.SCROLL_STATE_IDLE;
300     }
301 }
302