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 */ 14package android.support.v17.leanback.app; 15 16import android.support.v17.leanback.R; 17import android.support.v17.leanback.transition.TransitionHelper; 18import android.support.v17.leanback.widget.BrowseFrameLayout; 19import android.support.v17.leanback.widget.OnChildLaidOutListener; 20import android.support.v17.leanback.widget.OnItemViewClickedListener; 21import android.support.v17.leanback.widget.OnItemViewSelectedListener; 22import android.support.v17.leanback.widget.Presenter; 23import android.support.v17.leanback.widget.Row; 24import android.support.v17.leanback.widget.RowPresenter; 25import android.support.v17.leanback.widget.VerticalGridPresenter; 26import android.support.v17.leanback.widget.ObjectAdapter; 27import android.os.Bundle; 28import android.util.Log; 29import android.view.LayoutInflater; 30import android.view.View; 31import android.view.ViewGroup; 32 33/** 34 * A fragment for creating leanback vertical grids. 35 * 36 * <p>Renders a vertical grid of objects given a {@link VerticalGridPresenter} and 37 * an {@link ObjectAdapter}. 38 */ 39public class VerticalGridFragment extends BaseFragment { 40 private static final String TAG = "VerticalGridFragment"; 41 private static boolean DEBUG = false; 42 43 private ObjectAdapter mAdapter; 44 private VerticalGridPresenter mGridPresenter; 45 private VerticalGridPresenter.ViewHolder mGridViewHolder; 46 private OnItemViewSelectedListener mOnItemViewSelectedListener; 47 private OnItemViewClickedListener mOnItemViewClickedListener; 48 private Object mSceneAfterEntranceTransition; 49 private int mSelectedPosition = -1; 50 51 /** 52 * Sets the grid presenter. 53 */ 54 public void setGridPresenter(VerticalGridPresenter gridPresenter) { 55 if (gridPresenter == null) { 56 throw new IllegalArgumentException("Grid presenter may not be null"); 57 } 58 mGridPresenter = gridPresenter; 59 mGridPresenter.setOnItemViewSelectedListener(mViewSelectedListener); 60 if (mOnItemViewClickedListener != null) { 61 mGridPresenter.setOnItemViewClickedListener(mOnItemViewClickedListener); 62 } 63 } 64 65 /** 66 * Returns the grid presenter. 67 */ 68 public VerticalGridPresenter getGridPresenter() { 69 return mGridPresenter; 70 } 71 72 /** 73 * Sets the object adapter for the fragment. 74 */ 75 public void setAdapter(ObjectAdapter adapter) { 76 mAdapter = adapter; 77 updateAdapter(); 78 } 79 80 /** 81 * Returns the object adapter. 82 */ 83 public ObjectAdapter getAdapter() { 84 return mAdapter; 85 } 86 87 final private OnItemViewSelectedListener mViewSelectedListener = 88 new OnItemViewSelectedListener() { 89 @Override 90 public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, 91 RowPresenter.ViewHolder rowViewHolder, Row row) { 92 int position = mGridViewHolder.getGridView().getSelectedPosition(); 93 if (DEBUG) Log.v(TAG, "grid selected position " + position); 94 gridOnItemSelected(position); 95 if (mOnItemViewSelectedListener != null) { 96 mOnItemViewSelectedListener.onItemSelected(itemViewHolder, item, 97 rowViewHolder, row); 98 } 99 } 100 }; 101 102 final private OnChildLaidOutListener mChildLaidOutListener = 103 new OnChildLaidOutListener() { 104 @Override 105 public void onChildLaidOut(ViewGroup parent, View view, int position, long id) { 106 if (position == 0) { 107 showOrHideTitle(); 108 } 109 } 110 }; 111 112 /** 113 * Sets an item selection listener. 114 */ 115 public void setOnItemViewSelectedListener(OnItemViewSelectedListener listener) { 116 mOnItemViewSelectedListener = listener; 117 } 118 119 private void gridOnItemSelected(int position) { 120 if (position != mSelectedPosition) { 121 mSelectedPosition = position; 122 showOrHideTitle(); 123 } 124 } 125 126 private void showOrHideTitle() { 127 if (mGridViewHolder.getGridView().findViewHolderForAdapterPosition(mSelectedPosition) 128 == null) { 129 return; 130 } 131 if (!mGridViewHolder.getGridView().hasPreviousViewInSameRow(mSelectedPosition)) { 132 showTitle(true); 133 } else { 134 showTitle(false); 135 } 136 } 137 138 /** 139 * Sets an item clicked listener. 140 */ 141 public void setOnItemViewClickedListener(OnItemViewClickedListener listener) { 142 mOnItemViewClickedListener = listener; 143 if (mGridPresenter != null) { 144 mGridPresenter.setOnItemViewClickedListener(mOnItemViewClickedListener); 145 } 146 } 147 148 /** 149 * Returns the item clicked listener. 150 */ 151 public OnItemViewClickedListener getOnItemViewClickedListener() { 152 return mOnItemViewClickedListener; 153 } 154 155 @Override 156 public View onCreateView(LayoutInflater inflater, ViewGroup container, 157 Bundle savedInstanceState) { 158 ViewGroup root = (ViewGroup) inflater.inflate(R.layout.lb_vertical_grid_fragment, 159 container, false); 160 ViewGroup gridFrame = (ViewGroup) root.findViewById(R.id.grid_frame); 161 installTitleView(inflater, gridFrame, savedInstanceState); 162 getProgressBarManager().setRootView(root); 163 return root; 164 } 165 166 @Override 167 public void onViewCreated(View view, Bundle savedInstanceState) { 168 super.onViewCreated(view, savedInstanceState); 169 ViewGroup gridDock = (ViewGroup) view.findViewById(R.id.browse_grid_dock); 170 mGridViewHolder = mGridPresenter.onCreateViewHolder(gridDock); 171 gridDock.addView(mGridViewHolder.view); 172 mGridViewHolder.getGridView().setOnChildLaidOutListener(mChildLaidOutListener); 173 174 mSceneAfterEntranceTransition = TransitionHelper.createScene(gridDock, new Runnable() { 175 @Override 176 public void run() { 177 setEntranceTransitionState(true); 178 } 179 }); 180 181 updateAdapter(); 182 } 183 184 private void setupFocusSearchListener() { 185 BrowseFrameLayout browseFrameLayout = (BrowseFrameLayout) getView().findViewById( 186 R.id.grid_frame); 187 browseFrameLayout.setOnFocusSearchListener(getTitleHelper().getOnFocusSearchListener()); 188 } 189 190 @Override 191 public void onStart() { 192 super.onStart(); 193 setupFocusSearchListener(); 194 if (isEntranceTransitionEnabled()) { 195 setEntranceTransitionState(false); 196 } 197 } 198 199 @Override 200 public void onDestroyView() { 201 super.onDestroyView(); 202 mGridViewHolder = null; 203 } 204 205 /** 206 * Sets the selected item position. 207 */ 208 public void setSelectedPosition(int position) { 209 mSelectedPosition = position; 210 if(mGridViewHolder != null && mGridViewHolder.getGridView().getAdapter() != null) { 211 mGridViewHolder.getGridView().setSelectedPositionSmooth(position); 212 } 213 } 214 215 private void updateAdapter() { 216 if (mGridViewHolder != null) { 217 mGridPresenter.onBindViewHolder(mGridViewHolder, mAdapter); 218 if (mSelectedPosition != -1) { 219 mGridViewHolder.getGridView().setSelectedPosition(mSelectedPosition); 220 } 221 } 222 } 223 224 @Override 225 protected Object createEntranceTransition() { 226 return TransitionHelper.loadTransition(getActivity(), 227 R.transition.lb_vertical_grid_entrance_transition); 228 } 229 230 @Override 231 protected void runEntranceTransition(Object entranceTransition) { 232 TransitionHelper.runTransition(mSceneAfterEntranceTransition, entranceTransition); 233 } 234 235 void setEntranceTransitionState(boolean afterTransition) { 236 mGridPresenter.setEntranceTransitionState(mGridViewHolder, afterTransition); 237 } 238} 239