HeadersFragment.java revision d7618ab69ef591dd5342b9481c4954bfc7e9110c
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.os.Bundle; 18import android.support.v17.leanback.R; 19import android.support.v17.leanback.widget.FocusHighlightHelper; 20import android.support.v17.leanback.widget.ItemBridgeAdapter; 21import android.support.v17.leanback.widget.PresenterSelector; 22import android.support.v17.leanback.widget.OnItemSelectedListener; 23import android.support.v17.leanback.widget.Row; 24import android.support.v17.leanback.widget.RowHeaderPresenter; 25import android.support.v17.leanback.widget.SinglePresenterSelector; 26import android.support.v17.leanback.widget.VerticalGridView; 27import android.util.TypedValue; 28import android.view.View; 29import android.view.ViewGroup; 30import android.view.View.OnLayoutChangeListener; 31import android.widget.FrameLayout; 32 33/** 34 * An internal fragment containing a list of row headers. 35 */ 36public class HeadersFragment extends BaseRowFragment { 37 38 interface OnHeaderClickedListener { 39 void onHeaderClicked(); 40 } 41 42 private OnItemSelectedListener mOnItemSelectedListener; 43 private OnHeaderClickedListener mOnHeaderClickedListener; 44 private boolean mHeadersEnabled = true; 45 private boolean mHeadersGone = false; 46 private int mBackgroundColor; 47 private boolean mBackgroundColorSet; 48 49 private static final PresenterSelector sHeaderPresenter = new SinglePresenterSelector( 50 new RowHeaderPresenter(R.layout.lb_header)); 51 52 public HeadersFragment() { 53 setPresenterSelector(sHeaderPresenter); 54 } 55 56 public void setOnHeaderClickedListener(OnHeaderClickedListener listener) { 57 mOnHeaderClickedListener = listener; 58 } 59 60 public void setOnItemSelectedListener(OnItemSelectedListener listener) { 61 mOnItemSelectedListener = listener; 62 } 63 64 @Override 65 protected void onRowSelected(ViewGroup parent, View view, int position, long id) { 66 if (mOnItemSelectedListener != null) { 67 if (position >= 0) { 68 Row row = (Row) getAdapter().get(position); 69 mOnItemSelectedListener.onItemSelected(null, row); 70 } else { 71 mOnItemSelectedListener.onItemSelected(null, null); 72 } 73 } 74 } 75 76 private final ItemBridgeAdapter.AdapterListener mAdapterListener = 77 new ItemBridgeAdapter.AdapterListener() { 78 @Override 79 public void onCreate(ItemBridgeAdapter.ViewHolder viewHolder) { 80 View headerView = viewHolder.getViewHolder().view; 81 headerView.setOnClickListener(new View.OnClickListener() { 82 @Override 83 public void onClick(View v) { 84 if (mOnHeaderClickedListener != null) { 85 mOnHeaderClickedListener.onHeaderClicked(); 86 } 87 } 88 }); 89 headerView.setFocusable(true); 90 headerView.setFocusableInTouchMode(true); 91 if (mWrapper != null) { 92 viewHolder.itemView.addOnLayoutChangeListener(sLayoutChangeListener); 93 } else { 94 headerView.addOnLayoutChangeListener(sLayoutChangeListener); 95 } 96 } 97 98 }; 99 100 private static OnLayoutChangeListener sLayoutChangeListener = new OnLayoutChangeListener() { 101 @Override 102 public void onLayoutChange(View v, int left, int top, int right, int bottom, 103 int oldLeft, int oldTop, int oldRight, int oldBottom) { 104 v.setPivotX(0); 105 v.setPivotY(v.getMeasuredHeight() / 2); 106 } 107 }; 108 109 @Override 110 protected int getLayoutResourceId() { 111 return R.layout.lb_headers_fragment; 112 } 113 114 @Override 115 public void onViewCreated(View view, Bundle savedInstanceState) { 116 super.onViewCreated(view, savedInstanceState); 117 final VerticalGridView listView = getVerticalGridView(); 118 if (listView == null) { 119 return; 120 } 121 if (getBridgeAdapter() != null) { 122 FocusHighlightHelper.setupHeaderItemFocusHighlight(listView); 123 } 124 listView.setBackgroundColor(getBackgroundColor()); 125 updateListViewVisibility(); 126 } 127 128 private void updateListViewVisibility() { 129 final VerticalGridView listView = getVerticalGridView(); 130 if (listView != null) { 131 listView.setVisibility(mHeadersGone ? View.GONE : View.VISIBLE); 132 if (!mHeadersGone) { 133 if (mHeadersEnabled) { 134 listView.setChildrenVisibility(View.VISIBLE); 135 } else { 136 listView.setChildrenVisibility(View.INVISIBLE); 137 } 138 } 139 } 140 } 141 142 void setHeadersEnabled(boolean enabled) { 143 mHeadersEnabled = enabled; 144 updateListViewVisibility(); 145 } 146 147 void setHeadersGone(boolean gone) { 148 mHeadersGone = gone; 149 updateListViewVisibility(); 150 } 151 152 // Wrapper needed because of conflict between RecyclerView's use of alpha 153 // for ADD animations, and RowHeaderPresnter's use of alpha for selected level. 154 private final ItemBridgeAdapter.Wrapper mWrapper = new ItemBridgeAdapter.Wrapper() { 155 @Override 156 public void wrap(View wrapper, View wrapped) { 157 ((FrameLayout) wrapper).addView(wrapped); 158 } 159 160 @Override 161 public View createWrapper(View root) { 162 return new FrameLayout(root.getContext()); 163 } 164 }; 165 @Override 166 protected void updateAdapter() { 167 super.updateAdapter(); 168 ItemBridgeAdapter adapter = getBridgeAdapter(); 169 if (adapter != null) { 170 adapter.setAdapterListener(mAdapterListener); 171 adapter.setWrapper(mWrapper); 172 } 173 if (adapter != null && getVerticalGridView() != null) { 174 FocusHighlightHelper.setupHeaderItemFocusHighlight(getVerticalGridView()); 175 } 176 } 177 178 void setBackgroundColor(int color) { 179 mBackgroundColor = color; 180 mBackgroundColorSet = true; 181 182 if (getVerticalGridView() != null) { 183 getVerticalGridView().setBackgroundColor(mBackgroundColor); 184 } 185 } 186 187 int getBackgroundColor() { 188 if (getActivity() == null) { 189 throw new IllegalStateException("Activity must be attached"); 190 } 191 192 if (mBackgroundColorSet) { 193 return mBackgroundColor; 194 } 195 196 TypedValue outValue = new TypedValue(); 197 getActivity().getTheme().resolveAttribute(R.attr.defaultBrandColor, outValue, true); 198 return getResources().getColor(outValue.resourceId); 199 } 200} 201