VerticalGridPresenter.java revision 739e3805bf2785e6773aede5e2e1643f537305f9
1739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout/* 2739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * Copyright (C) 2014 The Android Open Source Project 3739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * 4739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * in compliance with the License. You may obtain a copy of the License at 6739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * 7739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * http://www.apache.org/licenses/LICENSE-2.0 8739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * 9739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * Unless required by applicable law or agreed to in writing, software distributed under the License 10739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * or implied. See the License for the specific language governing permissions and limitations under 12739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * the License. 13739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout */ 14739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutpackage android.support.v17.leanback.widget; 15739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 16739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.support.v17.leanback.R; 17739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.view.LayoutInflater; 18739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.view.View; 19739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.view.ViewGroup; 20739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.util.Log; 21739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 22739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout/** 23739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * A presenter that renders objects in a vertical grid. 24739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * 25739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout */ 26739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutpublic class VerticalGridPresenter extends Presenter { 27739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout private static final String TAG = "GridPresenter"; 28739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout private static final boolean DEBUG = false; 29739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 30739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout public static class ViewHolder extends Presenter.ViewHolder { 31739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout final ItemBridgeAdapter mItemBridgeAdapter = new ItemBridgeAdapter(); 32739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout final VerticalGridView mGridView; 33739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout boolean mInitialized; 34739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 35739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout public ViewHolder(VerticalGridView view) { 36739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout super(view); 37739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout mGridView = view; 38739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 39739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 40739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout public VerticalGridView getGridView() { 41739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout return mGridView; 42739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 43739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 44739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 45739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout private int mNumColumns = -1; 46739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout private int mZoomFactor; 47739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout private OnItemSelectedListener mOnItemSelectedListener; 48739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout private OnItemClickedListener mOnItemClickedListener; 49739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 50739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout public VerticalGridPresenter() { 51739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout this(FocusHighlight.ZOOM_FACTOR_MEDIUM); 52739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 53739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 54739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout public VerticalGridPresenter(int zoomFactor) { 55739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout mZoomFactor = zoomFactor; 56739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 57739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 58739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout /** 59739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * Sets the number of columns in the vertical grid. 60739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout */ 61739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout public void setNumberOfColumns(int numColumns) { 62739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout if (numColumns < 0) { 63739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout throw new IllegalArgumentException("Invalid number of columns"); 64739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 65739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout if (mNumColumns != numColumns) { 66739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout mNumColumns = numColumns; 67739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 68739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 69739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 70739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout /** 71739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * Returns the number of columns in the vertical grid. 72739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout */ 73739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout public int getNumberOfColumns() { 74739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout return mNumColumns; 75739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 76739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 77739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout @Override 78739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout public final ViewHolder onCreateViewHolder(ViewGroup parent) { 79739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout ViewHolder vh = createGridViewHolder(parent); 80739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout vh.mInitialized = false; 81739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout initializeGridViewHolder(vh); 82739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout if (!vh.mInitialized) { 83739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout throw new RuntimeException("super.initializeGridViewHolder() must be called"); 84739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 85739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout return vh; 86739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 87739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 88739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout /** 89739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * Subclass may override this to inflate a different layout. 90739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout */ 91739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout protected ViewHolder createGridViewHolder(ViewGroup parent) { 92739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout View root = LayoutInflater.from(parent.getContext()).inflate( 93739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout R.layout.lb_browse_grid, parent, false); 94739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout return new ViewHolder((VerticalGridView) root.findViewById(R.id.browse_grid)); 95739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 96739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 97739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout protected void initializeGridViewHolder(ViewHolder vh) { 98739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout if (mNumColumns == -1) { 99739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout throw new IllegalStateException("Number of columns must be set"); 100739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 101739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout if (DEBUG) Log.v(TAG, "mNumColumns " + mNumColumns); 102739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout vh.getGridView().setNumColumns(mNumColumns); 103739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout vh.mInitialized = true; 104739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 105739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout FocusHighlightHelper.setupBrowseItemFocusHighlight(vh.mItemBridgeAdapter, mZoomFactor); 106739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 107739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout final ViewHolder gridViewHolder = vh; 108739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout vh.getGridView().setOnChildSelectedListener(new OnChildSelectedListener() { 109739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout @Override 110739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout public void onChildSelected(ViewGroup parent, View view, int position, long id) { 111739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout selectChildView(gridViewHolder, view); 112739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 113739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout }); 114739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 115739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout vh.mItemBridgeAdapter.setAdapterListener(new ItemBridgeAdapter.AdapterListener() { 116739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout @Override 117739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout public void onCreate(final ItemBridgeAdapter.ViewHolder itemViewHolder) { 118739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout // Only when having an OnItemClickListner, we attach the OnClickListener. 119739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout if (getOnItemClickedListener() != null) { 120739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout final View itemView = itemViewHolder.getViewHolder().view; 121739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout itemView.setOnClickListener(new View.OnClickListener() { 122739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout @Override 123739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout public void onClick(View view) { 124739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout if (getOnItemClickedListener() != null) { 125739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout // Row is always null 126739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout getOnItemClickedListener().onItemClicked(itemViewHolder.mItem, null); 127739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 128739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 129739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout }); 130739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 131739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 132739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout }); 133739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 134739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 135739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout @Override 136739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) { 137739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout if (DEBUG) Log.v(TAG, "onBindViewHolder " + item); 138739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout ViewHolder vh = (ViewHolder) viewHolder; 139739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout vh.mItemBridgeAdapter.setAdapter((ObjectAdapter) item); 140739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout vh.getGridView().setAdapter(vh.mItemBridgeAdapter); 141739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 142739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 143739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout @Override 144739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) { 145739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout if (DEBUG) Log.v(TAG, "onUnbindViewHolder"); 146739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout ViewHolder vh = (ViewHolder) viewHolder; 147739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout vh.mItemBridgeAdapter.setAdapter(null); 148739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout vh.getGridView().setAdapter(null); 149739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 150739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 151739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout /** 152739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * Sets the item selected listener. 153739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * Since this is a grid the row parameter is always null. 154739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout */ 155739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout public final void setOnItemSelectedListener(OnItemSelectedListener listener) { 156739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout mOnItemSelectedListener = listener; 157739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 158739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 159739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout /** 160739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * Returns the item selected listener. 161739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout */ 162739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout public final OnItemSelectedListener getOnItemSelectedListener() { 163739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout return mOnItemSelectedListener; 164739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 165739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 166739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout /** 167739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * Sets the item clicked listener. 168739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * OnItemClickedListener will override {@link View.OnClickListener} that 169739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * item presenter sets during {@link Presenter#onCreateViewHolder(ViewGroup)}. 170739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * So in general, developer should choose one of the listeners but not both. 171739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout */ 172739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout public final void setOnItemClickedListener(OnItemClickedListener listener) { 173739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout mOnItemClickedListener = listener; 174739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 175739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 176739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout /** 177739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * Returns the item clicked listener. 178739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout */ 179739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout public final OnItemClickedListener getOnItemClickedListener() { 180739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout return mOnItemClickedListener; 181739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 182739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 183739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout private void selectChildView(ViewHolder vh, View view) { 184739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout if (getOnItemSelectedListener() != null) { 185739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout ItemBridgeAdapter.ViewHolder ibh = (view == null) ? null : 186739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout (ItemBridgeAdapter.ViewHolder) vh.getGridView().getChildViewHolder(view); 187739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout 188739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout getOnItemSelectedListener().onItemSelected(ibh == null ? null : ibh.mItem, null); 189739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout } 190739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout }; 191739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout} 192