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