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