RowPresenter.java revision 8b068ddbbf22a246eab49ec25a2f7c3abfbdca51
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.widget; 15 16import android.view.View; 17import android.view.ViewGroup; 18 19/** 20 * In addition to {@link Presenter} which defines how to render and bind data to row view, 21 * RowPresenter receives calls from upper level(typically a fragment) when: 22 * <ul> 23 * <li> 24 * Row is selected via {@link #setRowViewSelected(ViewHolder, boolean)}. The event 25 * is triggered immediately when there is a row selection change before the selection 26 * animation is started. 27 * Subclass of RowPresenter may override and add more works in 28 * {@link #onRowViewSelected(ViewHolder, boolean)}. 29 * </li> 30 * <li> 31 * Row is expanded to full width via {@link #setRowViewExpanded(ViewHolder, boolean)}. 32 * The event is triggered immediately before the expand animation is started. 33 * Subclass of RowPresenter may override and add more works in 34 * {@link #onRowViewExpanded(ViewHolder, boolean)}. 35 * </li> 36 * </ul> 37 * </p> 38 * Subclass of RowPresenter may add more fields in ViewHolder by overriding 39 * {@link #createRowViewHolder(ViewGroup)} and {@link #initializeRowViewHolder(ViewHolder)}. 40 * </p> 41 * <p> 42 * RowPresenter contains an optional and replaceable {@link RowHeaderPresenter} that 43 * renders header. User can disable default rendering or replace with a new header presenter 44 * by calling {@link #setHeaderPresenter(RowHeaderPresenter)}. 45 * </p> 46 * <p> 47 * Provides {@link OnItemSelectedListener} and {@link OnItemClickedListener}. 48 * </p> 49 */ 50public abstract class RowPresenter extends Presenter { 51 52 public static class ViewHolder extends Presenter.ViewHolder { 53 RowHeaderPresenter.ViewHolder mHeaderViewHolder; 54 Row mRow; 55 boolean mSelected; 56 boolean mExpanded; 57 boolean mInitialzed; 58 public ViewHolder(View view) { 59 super(view); 60 } 61 public final Row getRow() { 62 return mRow; 63 } 64 public final boolean isExpanded() { 65 return mExpanded; 66 } 67 public final boolean isSelected() { 68 return mSelected; 69 } 70 public final RowHeaderPresenter.ViewHolder getHeaderViewHolder() { 71 return mHeaderViewHolder; 72 } 73 } 74 75 private RowHeaderPresenter mHeaderPresenter = new RowHeaderPresenter(); 76 private OnItemSelectedListener mOnItemSelectedListener; 77 private OnItemClickedListener mOnItemClickedListener; 78 79 @Override 80 public final Presenter.ViewHolder onCreateViewHolder(ViewGroup parent) { 81 ViewHolder vh = createRowViewHolder(parent); 82 vh.mInitialzed = false; 83 initializeRowViewHolder(vh); 84 if (!vh.mInitialzed) { 85 throw new RuntimeException("super.initializeRowViewHolder() must be called"); 86 } 87 return vh; 88 } 89 90 /** 91 * Called to create a ViewHolder object for row, subclass of {@link RowPresenter} 92 * should override and return a different concrete ViewHolder object. 93 */ 94 protected abstract ViewHolder createRowViewHolder(ViewGroup parent); 95 96 /** 97 * Called after a {@link RowPresenter.ViewHolder} is created, 98 * subclass of {@link RowPresenter} may override this method and start with calling 99 * super.initializeRowViewHolder(ViewHolder). 100 */ 101 protected void initializeRowViewHolder(ViewHolder vh) { 102 if (mHeaderPresenter != null) { 103 vh.mHeaderViewHolder = (RowHeaderPresenter.ViewHolder) 104 mHeaderPresenter.onCreateViewHolder((ViewGroup) vh.view); 105 ((ViewGroup) vh.view).addView(vh.mHeaderViewHolder.view, 0); 106 } 107 vh.mInitialzed = true; 108 } 109 110 /** 111 * Change the presenter used for rendering header. Can be null to disable header rendering. 112 * The method must be called before creating any row view. 113 */ 114 public final void setHeaderPresenter(RowHeaderPresenter headerPresenter) { 115 mHeaderPresenter = headerPresenter; 116 } 117 118 /** 119 * Get optional presenter used for rendering header. May return null. 120 */ 121 public final RowHeaderPresenter getHeaderPresenter() { 122 return mHeaderPresenter; 123 } 124 125 /** 126 * Change expanded state of row view. 127 */ 128 public final void setRowViewExpanded(ViewHolder holder, boolean expanded) { 129 holder.mExpanded = expanded; 130 onRowViewExpanded(holder, expanded); 131 } 132 133 /** 134 * Change select state of row view. 135 */ 136 public final void setRowViewSelected(ViewHolder holder, boolean selected) { 137 holder.mSelected = selected; 138 onRowViewSelected(holder, selected); 139 } 140 141 /** 142 * Subclass may override and respond to expanded state change of row in fragment. 143 * Default implementation hide/show header view depending on expanded state. 144 * Subclass may make visual changes to row view but not allowed to create 145 * animation on the row view. 146 */ 147 protected void onRowViewExpanded(ViewHolder vh, boolean expanded) { 148 if (mHeaderPresenter != null && vh.mHeaderViewHolder != null) { 149 mHeaderPresenter.setHidden(vh.mHeaderViewHolder, !expanded); 150 } 151 } 152 153 /** 154 * Subclass may override and respond to event Row is selected. 155 * Subclass may make visual changes to row view but not allowed to create 156 * animation on the row view. 157 */ 158 protected void onRowViewSelected(ViewHolder vh, boolean selected) { 159 if (selected && mOnItemSelectedListener != null) { 160 mOnItemSelectedListener.onItemSelected(null, vh.getRow()); 161 } 162 } 163 164 @Override 165 public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) { 166 ViewHolder vh = (ViewHolder) viewHolder; 167 vh.mRow = (Row) item; 168 if (vh.mHeaderViewHolder != null) { 169 mHeaderPresenter.onBindViewHolder(vh.mHeaderViewHolder, item); 170 } 171 vh.mSelected = false; 172 vh.mExpanded = false; 173 onRowViewExpanded(vh, false); 174 onRowViewSelected(vh, false); 175 } 176 177 @Override 178 public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) { 179 ViewHolder vh = (ViewHolder) viewHolder; 180 if (vh.mHeaderViewHolder != null) { 181 mHeaderPresenter.onUnbindViewHolder(vh.mHeaderViewHolder); 182 } 183 vh.mRow = null; 184 } 185 186 @Override 187 public void onViewAttachedToWindow(Presenter.ViewHolder holder) { 188 ViewHolder vh = (ViewHolder) holder; 189 if (vh.mHeaderViewHolder != null) { 190 mHeaderPresenter.onViewAttachedToWindow(vh.mHeaderViewHolder); 191 } 192 } 193 194 @Override 195 public void onViewDetachedFromWindow(Presenter.ViewHolder holder) { 196 ViewHolder vh = (ViewHolder) holder; 197 if (vh.mHeaderViewHolder != null) { 198 mHeaderPresenter.onViewDetachedFromWindow(vh.mHeaderViewHolder); 199 } 200 } 201 202 /** 203 * Set listener for item or row selection. RowPresenter fires row selection 204 * event with null item, subclass of RowPresenter e.g. {@link ListRowPresenter} can 205 * fire a selection event with selected item. 206 */ 207 public final void setOnItemSelectedListener(OnItemSelectedListener listener) { 208 mOnItemSelectedListener = listener; 209 } 210 211 /** 212 * Get listener for item or row selection. 213 */ 214 public final OnItemSelectedListener getOnItemSelectedListener() { 215 return mOnItemSelectedListener; 216 } 217 218 /** 219 * Set listener for item click event. RowPresenter does nothing but subclass of 220 * RowPresenter may fire item click event if it does have a concept of item. 221 * OnItemClickedListener will override the listener that item presenter sets during 222 * {@link Presenter#onCreateViewHolder(ViewGroup)}. So in general, developer should 223 * choose one of the listeners but not both. 224 */ 225 public final void setOnItemClickedListener(OnItemClickedListener listener) { 226 mOnItemClickedListener = listener; 227 } 228 229 /** 230 * Set listener for item click event. 231 */ 232 public final OnItemClickedListener getOnItemClickedListener() { 233 return mOnItemClickedListener; 234 } 235} 236