HeadersFragment.java revision 9652881bb6af5a2b76f89d683bd420336f4bf463
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 15package android.support.v17.leanback.app; 16 17import android.graphics.Color; 18import android.graphics.drawable.Drawable; 19import android.graphics.drawable.GradientDrawable; 20import android.os.Bundle; 21import android.support.v17.leanback.R; 22import android.support.v17.leanback.widget.FocusHighlightHelper; 23import android.support.v17.leanback.widget.ItemBridgeAdapter; 24import android.support.v17.leanback.widget.PresenterSelector; 25import android.support.v17.leanback.widget.OnItemSelectedListener; 26import android.support.v17.leanback.widget.Row; 27import android.support.v17.leanback.widget.RowHeaderPresenter; 28import android.support.v17.leanback.widget.SinglePresenterSelector; 29import android.support.v17.leanback.widget.VerticalGridView; 30import android.util.TypedValue; 31import android.view.View; 32import android.view.ViewGroup; 33import android.view.View.OnLayoutChangeListener; 34import android.widget.FrameLayout; 35 36/** 37 * An internal fragment containing a list of row headers. 38 */ 39public class HeadersFragment extends BaseRowFragment { 40 41 interface OnHeaderClickedListener { 42 void onHeaderClicked(); 43 } 44 45 private OnItemSelectedListener mOnItemSelectedListener; 46 private OnHeaderClickedListener mOnHeaderClickedListener; 47 private boolean mHeadersEnabled = true; 48 private boolean mHeadersGone = false; 49 private int mBackgroundColor; 50 private boolean mBackgroundColorSet; 51 52 private static final PresenterSelector sHeaderPresenter = new SinglePresenterSelector( 53 new RowHeaderPresenter(R.layout.lb_header)); 54 55 public HeadersFragment() { 56 setPresenterSelector(sHeaderPresenter); 57 } 58 59 public void setOnHeaderClickedListener(OnHeaderClickedListener listener) { 60 mOnHeaderClickedListener = listener; 61 } 62 63 public void setOnItemSelectedListener(OnItemSelectedListener listener) { 64 mOnItemSelectedListener = listener; 65 } 66 67 @Override 68 protected VerticalGridView findGridViewFromRoot(View view) { 69 return (VerticalGridView) view.findViewById(R.id.browse_headers); 70 } 71 72 @Override 73 protected void onRowSelected(ViewGroup parent, View view, int position, long id) { 74 if (mOnItemSelectedListener != null) { 75 if (position >= 0) { 76 Row row = (Row) getAdapter().get(position); 77 mOnItemSelectedListener.onItemSelected(null, row); 78 } else { 79 mOnItemSelectedListener.onItemSelected(null, null); 80 } 81 } 82 } 83 84 private final ItemBridgeAdapter.AdapterListener mAdapterListener = 85 new ItemBridgeAdapter.AdapterListener() { 86 @Override 87 public void onCreate(ItemBridgeAdapter.ViewHolder viewHolder) { 88 View headerView = viewHolder.getViewHolder().view; 89 headerView.setOnClickListener(new View.OnClickListener() { 90 @Override 91 public void onClick(View v) { 92 if (mOnHeaderClickedListener != null) { 93 mOnHeaderClickedListener.onHeaderClicked(); 94 } 95 } 96 }); 97 headerView.setFocusable(true); 98 headerView.setFocusableInTouchMode(true); 99 if (mWrapper != null) { 100 viewHolder.itemView.addOnLayoutChangeListener(sLayoutChangeListener); 101 } else { 102 headerView.addOnLayoutChangeListener(sLayoutChangeListener); 103 } 104 } 105 106 }; 107 108 private static OnLayoutChangeListener sLayoutChangeListener = new OnLayoutChangeListener() { 109 @Override 110 public void onLayoutChange(View v, int left, int top, int right, int bottom, 111 int oldLeft, int oldTop, int oldRight, int oldBottom) { 112 v.setPivotX(0); 113 v.setPivotY(v.getMeasuredHeight() / 2); 114 } 115 }; 116 117 @Override 118 protected int getLayoutResourceId() { 119 return R.layout.lb_headers_fragment; 120 } 121 122 @Override 123 public void onViewCreated(View view, Bundle savedInstanceState) { 124 super.onViewCreated(view, savedInstanceState); 125 final VerticalGridView listView = getVerticalGridView(); 126 if (listView == null) { 127 return; 128 } 129 if (getBridgeAdapter() != null) { 130 FocusHighlightHelper.setupHeaderItemFocusHighlight(listView); 131 } 132 view.setBackgroundColor(getBackgroundColor()); 133 if (mBackgroundColorSet) { 134 updateFadingEdgeToBrandColor(); 135 } 136 updateListViewVisibility(); 137 } 138 139 private void updateListViewVisibility() { 140 final VerticalGridView listView = getVerticalGridView(); 141 if (listView != null) { 142 getView().setVisibility(mHeadersGone ? View.GONE : View.VISIBLE); 143 if (!mHeadersGone) { 144 if (mHeadersEnabled) { 145 listView.setChildrenVisibility(View.VISIBLE); 146 } else { 147 listView.setChildrenVisibility(View.INVISIBLE); 148 } 149 } 150 } 151 } 152 153 void setHeadersEnabled(boolean enabled) { 154 mHeadersEnabled = enabled; 155 updateListViewVisibility(); 156 } 157 158 void setHeadersGone(boolean gone) { 159 mHeadersGone = gone; 160 updateListViewVisibility(); 161 } 162 163 // Wrapper needed because of conflict between RecyclerView's use of alpha 164 // for ADD animations, and RowHeaderPresnter's use of alpha for selected level. 165 private final ItemBridgeAdapter.Wrapper mWrapper = new ItemBridgeAdapter.Wrapper() { 166 @Override 167 public void wrap(View wrapper, View wrapped) { 168 ((FrameLayout) wrapper).addView(wrapped); 169 } 170 171 @Override 172 public View createWrapper(View root) { 173 return new FrameLayout(root.getContext()); 174 } 175 }; 176 @Override 177 protected void updateAdapter() { 178 super.updateAdapter(); 179 ItemBridgeAdapter adapter = getBridgeAdapter(); 180 if (adapter != null) { 181 adapter.setAdapterListener(mAdapterListener); 182 adapter.setWrapper(mWrapper); 183 } 184 if (adapter != null && getVerticalGridView() != null) { 185 FocusHighlightHelper.setupHeaderItemFocusHighlight(getVerticalGridView()); 186 } 187 } 188 189 void setBackgroundColor(int color) { 190 mBackgroundColor = color; 191 mBackgroundColorSet = true; 192 193 if (getView() != null) { 194 getView().setBackgroundColor(mBackgroundColor); 195 updateFadingEdgeToBrandColor(); 196 } 197 } 198 199 private void updateFadingEdgeToBrandColor() { 200 View fadingView = getView().findViewById(R.id.fade_out_edge); 201 Drawable background = fadingView.getBackground(); 202 if (background instanceof GradientDrawable) { 203 background.mutate(); 204 ((GradientDrawable) background).setColors( 205 new int[]{Color.TRANSPARENT,mBackgroundColor}); 206 } 207 } 208 209 int getBackgroundColor() { 210 if (getActivity() == null) { 211 throw new IllegalStateException("Activity must be attached"); 212 } 213 214 if (mBackgroundColorSet) { 215 return mBackgroundColor; 216 } 217 218 TypedValue outValue = new TypedValue(); 219 getActivity().getTheme().resolveAttribute(R.attr.defaultBrandColor, outValue, true); 220 return getResources().getColor(outValue.resourceId); 221 } 222} 223