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