RowPresenter.java revision 60bb6af2e336072921f5d3c3861e86b3cc6241b3
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.support.v17.leanback.app.HeadersFragment; 17import android.support.v17.leanback.graphics.ColorOverlayDimmer; 18import android.view.View; 19import android.view.ViewGroup; 20 21/** 22 * An abstract {@link Presenter} that renders a {@link Row}. 23 * 24 * <h3>Customize UI widgets</h3> 25 * When a subclass of RowPresenter adds UI widgets, it should subclass 26 * {@link RowPresenter.ViewHolder} and override {@link #createRowViewHolder(ViewGroup)} 27 * and {@link #initializeRowViewHolder(ViewHolder)}. The subclass must use layout id 28 * "row_content" for the widget that will be aligned to the title of any {@link HeadersFragment} 29 * that may exist in the parent fragment. RowPresenter contains an optional and 30 * replaceable {@link RowHeaderPresenter} that renders the header. You can disable 31 * the default rendering or replace the Presenter with a new header presenter 32 * by calling {@link #setHeaderPresenter(RowHeaderPresenter)}. 33 * 34 * <h3>UI events from fragments</h3> 35 * RowPresenter receives calls from its parent (typically a Fragment) when: 36 * <ul> 37 * <li> 38 * A row is selected via {@link #setRowViewSelected(Presenter.ViewHolder, boolean)}. The event 39 * is triggered immediately when there is a row selection change before the selection 40 * animation is started. Selected status may control activated status of the row (see 41 * "Activated status" below). 42 * Subclasses of RowPresenter may override {@link #onRowViewSelected(ViewHolder, boolean)}. 43 * </li> 44 * <li> 45 * A row is expanded to full height via {@link #setRowViewExpanded(Presenter.ViewHolder, boolean)} 46 * when BrowseFragment hides fast lane on the left. 47 * The event is triggered immediately before the expand animation is started. 48 * Row title is shown when row is expanded. Expanded status may control activated status 49 * of the row (see "Activated status" below). 50 * Subclasses of RowPresenter may override {@link #onRowViewExpanded(ViewHolder, boolean)}. 51 * </li> 52 * </ul> 53 * 54 * <h3>Activated status</h3> 55 * The activated status of a row is applied to the row view and it's children via 56 * {@link View#setActivated(boolean)}. 57 * The activated status is typically used to control {@link BaseCardView} info region visibility. 58 * The row's activated status can be controlled by selected status and/or expanded status. 59 * Call {@link #setSyncActivatePolicy(int)} and choose one of the four policies: 60 * <ul> 61 * <li>{@link #SYNC_ACTIVATED_TO_EXPANDED} Activated status is synced with row expanded status</li> 62 * <li>{@link #SYNC_ACTIVATED_TO_SELECTED} Activated status is synced with row selected status</li> 63 * <li>{@link #SYNC_ACTIVATED_TO_EXPANDED_AND_SELECTED} Activated status is set to true 64 * when both expanded and selected status are true</li> 65 * <li>{@link #SYNC_ACTIVATED_CUSTOM} Activated status is not controlled by selected status 66 * or expanded status, application can control activated status by its own. 67 * Application should call {@link RowPresenter.ViewHolder#setActivated(boolean)} to change 68 * activated status of row view. 69 * </li> 70 * </ul> 71 * 72 * <h3>User events</h3> 73 * RowPresenter provides {@link OnItemSelectedListener} and {@link OnItemClickedListener}. 74 * If a subclass wants to add its own {@link View.OnFocusChangeListener} or 75 * {@link View.OnClickListener}, it must do that in {@link #createRowViewHolder(ViewGroup)} 76 * to be properly chained by the library. Adding View listeners after 77 * {@link #createRowViewHolder(ViewGroup)} is undefined and may result in 78 * incorrect behavior by the library's listeners. 79 * 80 * <h3>Selection animation</h3> 81 * <p> 82 * When a user scrolls through rows, a fragment will initiate animation and call 83 * {@link #setSelectLevel(Presenter.ViewHolder, float)} with float value between 84 * 0 and 1. By default, the RowPresenter draws a dim overlay on top of the row 85 * view for views that are not selected. Subclasses may override this default effect 86 * by having {@link #isUsingDefaultSelectEffect()} return false and overriding 87 * {@link #onSelectLevelChanged(ViewHolder)} to apply a different selection effect. 88 * </p> 89 * <p> 90 * Call {@link #setSelectEffectEnabled(boolean)} to enable/disable the select effect, 91 * This will not only enable/disable the default dim effect but also subclasses must 92 * respect this flag as well. 93 * </p> 94 */ 95public abstract class RowPresenter extends Presenter { 96 97 /** 98 * Don't synchronize row view activated status with selected status or expanded status, 99 * application will do its own through {@link RowPresenter.ViewHolder#setActivated(boolean)}. 100 */ 101 public static final int SYNC_ACTIVATED_CUSTOM = 0; 102 103 /** 104 * Synchronizes row view's activated status to expand status of the row view holder. 105 */ 106 public static final int SYNC_ACTIVATED_TO_EXPANDED = 1; 107 108 /** 109 * Synchronizes row view's activated status to selected status of the row view holder. 110 */ 111 public static final int SYNC_ACTIVATED_TO_SELECTED = 2; 112 113 /** 114 * Sets the row view's activated status to true when both expand and selected are true. 115 */ 116 public static final int SYNC_ACTIVATED_TO_EXPANDED_AND_SELECTED = 3; 117 118 static class ContainerViewHolder extends Presenter.ViewHolder { 119 /** 120 * wrapped row view holder 121 */ 122 final ViewHolder mRowViewHolder; 123 124 public ContainerViewHolder(RowContainerView containerView, ViewHolder rowViewHolder) { 125 super(containerView); 126 containerView.addRowView(rowViewHolder.view); 127 if (rowViewHolder.mHeaderViewHolder != null) { 128 containerView.addHeaderView(rowViewHolder.mHeaderViewHolder.view); 129 } 130 mRowViewHolder = rowViewHolder; 131 mRowViewHolder.mContainerViewHolder = this; 132 } 133 } 134 135 /** 136 * A view holder for a {@link Row}. 137 */ 138 public static class ViewHolder extends Presenter.ViewHolder { 139 private static final int ACTIVATED_NOT_ASSIGNED = 0; 140 private static final int ACTIVATED = 1; 141 private static final int NOT_ACTIVATED = 2; 142 143 ContainerViewHolder mContainerViewHolder; 144 RowHeaderPresenter.ViewHolder mHeaderViewHolder; 145 Row mRow; 146 int mActivated = ACTIVATED_NOT_ASSIGNED; 147 boolean mSelected; 148 boolean mExpanded; 149 boolean mInitialzed; 150 float mSelectLevel = 0f; // initially unselected 151 protected final ColorOverlayDimmer mColorDimmer; 152 private View.OnKeyListener mOnKeyListener; 153 154 /** 155 * Constructor for ViewHolder. 156 * 157 * @param view The View bound to the Row. 158 */ 159 public ViewHolder(View view) { 160 super(view); 161 mColorDimmer = ColorOverlayDimmer.createDefault(view.getContext()); 162 } 163 164 /** 165 * Returns the Row bound to the View in this ViewHolder. 166 */ 167 public final Row getRow() { 168 return mRow; 169 } 170 171 /** 172 * Returns whether the Row is in its expanded state. 173 * 174 * @return true if the Row is expanded, false otherwise. 175 */ 176 public final boolean isExpanded() { 177 return mExpanded; 178 } 179 180 /** 181 * Returns whether the Row is selected. 182 * 183 * @return true if the Row is selected, false otherwise. 184 */ 185 public final boolean isSelected() { 186 return mSelected; 187 } 188 189 /** 190 * Returns the current selection level of the Row. 191 */ 192 public final float getSelectLevel() { 193 return mSelectLevel; 194 } 195 196 /** 197 * Returns the view holder for the Row header for this Row. 198 */ 199 public final RowHeaderPresenter.ViewHolder getHeaderViewHolder() { 200 return mHeaderViewHolder; 201 } 202 203 /** 204 * Sets the row view's activated status. The status will be applied to children through 205 * {@link #syncActivatedStatus(View)}. Application should only call this function 206 * when {@link RowPresenter#getSyncActivatePolicy()} is 207 * {@link RowPresenter#SYNC_ACTIVATED_CUSTOM}; otherwise the value will 208 * be overwritten when expanded or selected status changes. 209 */ 210 public final void setActivated(boolean activated) { 211 mActivated = activated ? ACTIVATED : NOT_ACTIVATED; 212 } 213 214 /** 215 * Synchronizes the activated status of view to the last value passed through 216 * {@link RowPresenter.ViewHolder#setActivated(boolean)}. No operation if 217 * {@link RowPresenter.ViewHolder#setActivated(boolean)} is never called. Normally 218 * application does not need to call this method, {@link ListRowPresenter} automatically 219 * calls this method when a child is attached to list row. However if 220 * application writes its own custom RowPresenter, it should call this method 221 * when attaches a child to the row view. 222 */ 223 public final void syncActivatedStatus(View view) { 224 if (mActivated == ACTIVATED) { 225 view.setActivated(true); 226 } else if (mActivated == NOT_ACTIVATED) { 227 view.setActivated(false); 228 } 229 } 230 231 /** 232 * Sets a key listener. 233 */ 234 public void setOnKeyListener(View.OnKeyListener keyListener) { 235 mOnKeyListener = keyListener; 236 } 237 238 /** 239 * Returns the key listener. 240 */ 241 public View.OnKeyListener getOnKeyListener() { 242 return mOnKeyListener; 243 } 244 } 245 246 private RowHeaderPresenter mHeaderPresenter = new RowHeaderPresenter(); 247 private OnItemSelectedListener mOnItemSelectedListener; 248 private OnItemClickedListener mOnItemClickedListener; 249 private OnItemViewSelectedListener mOnItemViewSelectedListener; 250 private OnItemViewClickedListener mOnItemViewClickedListener; 251 252 boolean mSelectEffectEnabled = true; 253 int mSyncActivatePolicy = SYNC_ACTIVATED_TO_EXPANDED; 254 255 256 /** 257 * Constructs a RowPresenter. 258 */ 259 public RowPresenter() { 260 mHeaderPresenter.setNullItemVisibilityGone(true); 261 } 262 263 @Override 264 public final Presenter.ViewHolder onCreateViewHolder(ViewGroup parent) { 265 ViewHolder vh = createRowViewHolder(parent); 266 vh.mInitialzed = false; 267 Presenter.ViewHolder result; 268 if (needsRowContainerView()) { 269 RowContainerView containerView = new RowContainerView(parent.getContext()); 270 if (mHeaderPresenter != null) { 271 vh.mHeaderViewHolder = (RowHeaderPresenter.ViewHolder) 272 mHeaderPresenter.onCreateViewHolder((ViewGroup) vh.view); 273 } 274 result = new ContainerViewHolder(containerView, vh); 275 } else { 276 result = vh; 277 } 278 initializeRowViewHolder(vh); 279 if (!vh.mInitialzed) { 280 throw new RuntimeException("super.initializeRowViewHolder() must be called"); 281 } 282 return result; 283 } 284 285 /** 286 * Called to create a ViewHolder object for a Row. Subclasses will override 287 * this method to return a different concrete ViewHolder object. 288 * 289 * @param parent The parent View for the Row's view holder. 290 * @return A ViewHolder for the Row's View. 291 */ 292 protected abstract ViewHolder createRowViewHolder(ViewGroup parent); 293 294 /** 295 * Called after a {@link RowPresenter.ViewHolder} is created for a Row. 296 * Subclasses may override this method and start by calling 297 * super.initializeRowViewHolder(ViewHolder). 298 * 299 * @param vh The ViewHolder to initialize for the Row. 300 */ 301 protected void initializeRowViewHolder(ViewHolder vh) { 302 vh.mInitialzed = true; 303 // set clip children to false for slide transition 304 if (vh.view instanceof ViewGroup) { 305 ((ViewGroup) vh.view).setClipChildren(false); 306 } 307 if (vh.mContainerViewHolder != null) { 308 ((ViewGroup) vh.mContainerViewHolder.view).setClipChildren(false); 309 } 310 } 311 312 /** 313 * Set the Presenter used for rendering the header. Can be null to disable 314 * header rendering. The method must be called before creating any Row Views. 315 */ 316 public final void setHeaderPresenter(RowHeaderPresenter headerPresenter) { 317 mHeaderPresenter = headerPresenter; 318 } 319 320 /** 321 * Get the Presenter used for rendering the header, or null if none has been 322 * set. 323 */ 324 public final RowHeaderPresenter getHeaderPresenter() { 325 return mHeaderPresenter; 326 } 327 328 /** 329 * Get the {@link RowPresenter.ViewHolder} from the given Presenter 330 * ViewHolder. 331 */ 332 public final ViewHolder getRowViewHolder(Presenter.ViewHolder holder) { 333 if (holder instanceof ContainerViewHolder) { 334 return ((ContainerViewHolder) holder).mRowViewHolder; 335 } else { 336 return (ViewHolder) holder; 337 } 338 } 339 340 /** 341 * Set the expanded state of a Row view. 342 * 343 * @param holder The Row ViewHolder to set expanded state on. 344 * @param expanded True if the Row is expanded, false otherwise. 345 */ 346 public final void setRowViewExpanded(Presenter.ViewHolder holder, boolean expanded) { 347 ViewHolder rowViewHolder = getRowViewHolder(holder); 348 rowViewHolder.mExpanded = expanded; 349 onRowViewExpanded(rowViewHolder, expanded); 350 } 351 352 /** 353 * Set the selected state of a Row view. 354 * 355 * @param holder The Row ViewHolder to set expanded state on. 356 * @param selected True if the Row is expanded, false otherwise. 357 */ 358 public final void setRowViewSelected(Presenter.ViewHolder holder, boolean selected) { 359 ViewHolder rowViewHolder = getRowViewHolder(holder); 360 rowViewHolder.mSelected = selected; 361 onRowViewSelected(rowViewHolder, selected); 362 } 363 364 /** 365 * Subclass may override this to respond to expanded state changes of a Row. 366 * The default implementation will hide/show the header view. Subclasses may 367 * make visual changes to the Row View but must not create animation on the 368 * Row view. 369 */ 370 protected void onRowViewExpanded(ViewHolder vh, boolean expanded) { 371 updateHeaderViewVisibility(vh); 372 updateActivateStatus(vh, vh.view); 373 } 374 375 /** 376 * Update view's activate status according to {@link #getSyncActivatePolicy()} and the 377 * selected status and expanded status of the RowPresenter ViewHolder. 378 */ 379 private void updateActivateStatus(ViewHolder vh, View view) { 380 switch (mSyncActivatePolicy) { 381 case SYNC_ACTIVATED_TO_EXPANDED: 382 vh.setActivated(vh.isExpanded()); 383 break; 384 case SYNC_ACTIVATED_TO_SELECTED: 385 vh.setActivated(vh.isSelected()); 386 break; 387 case SYNC_ACTIVATED_TO_EXPANDED_AND_SELECTED: 388 vh.setActivated(vh.isExpanded() && vh.isSelected()); 389 break; 390 } 391 vh.syncActivatedStatus(view); 392 } 393 394 /** 395 * Sets policy of updating row view activated status. Can be one of: 396 * <li> Default value {@link #SYNC_ACTIVATED_TO_EXPANDED} 397 * <li> {@link #SYNC_ACTIVATED_TO_SELECTED} 398 * <li> {@link #SYNC_ACTIVATED_TO_EXPANDED_AND_SELECTED} 399 * <li> {@link #SYNC_ACTIVATED_CUSTOM} 400 */ 401 public final void setSyncActivatePolicy(int syncActivatePolicy) { 402 mSyncActivatePolicy = syncActivatePolicy; 403 } 404 405 /** 406 * Returns policy of updating row view activated status. Can be one of: 407 * <li> Default value {@link #SYNC_ACTIVATED_TO_EXPANDED} 408 * <li> {@link #SYNC_ACTIVATED_TO_SELECTED} 409 * <li> {@link #SYNC_ACTIVATED_TO_EXPANDED_AND_SELECTED} 410 * <li> {@link #SYNC_ACTIVATED_CUSTOM} 411 */ 412 public final int getSyncActivatePolicy() { 413 return mSyncActivatePolicy; 414 } 415 416 /** 417 * Subclass may override this to respond to selected state changes of a Row. 418 * Subclass may make visual changes to Row view but must not create 419 * animation on the Row view. 420 */ 421 protected void onRowViewSelected(ViewHolder vh, boolean selected) { 422 if (selected) { 423 if (mOnItemViewSelectedListener != null) { 424 mOnItemViewSelectedListener.onItemSelected(null, null, vh, vh.getRow()); 425 } 426 if (mOnItemSelectedListener != null) { 427 mOnItemSelectedListener.onItemSelected(null, vh.getRow()); 428 } 429 } 430 updateHeaderViewVisibility(vh); 431 updateActivateStatus(vh, vh.view); 432 } 433 434 private void updateHeaderViewVisibility(ViewHolder vh) { 435 if (mHeaderPresenter != null && vh.mHeaderViewHolder != null) { 436 RowContainerView containerView = ((RowContainerView) vh.mContainerViewHolder.view); 437 containerView.showHeader(vh.isExpanded()); 438 } 439 } 440 441 /** 442 * Set the current select level to a value between 0 (unselected) and 1 (selected). 443 * Subclasses may override {@link #onSelectLevelChanged(ViewHolder)} to 444 * respond to changes in the selected level. 445 */ 446 public final void setSelectLevel(Presenter.ViewHolder vh, float level) { 447 ViewHolder rowViewHolder = getRowViewHolder(vh); 448 rowViewHolder.mSelectLevel = level; 449 onSelectLevelChanged(rowViewHolder); 450 } 451 452 /** 453 * Get the current select level. The value will be between 0 (unselected) 454 * and 1 (selected). 455 */ 456 public final float getSelectLevel(Presenter.ViewHolder vh) { 457 return getRowViewHolder(vh).mSelectLevel; 458 } 459 460 /** 461 * Callback when select level is changed. The default implementation applies 462 * the select level to {@link RowHeaderPresenter#setSelectLevel(RowHeaderPresenter.ViewHolder, float)} 463 * when {@link #getSelectEffectEnabled()} is true. Subclasses may override 464 * this function and implement a different select effect. In this case, you 465 * should also override {@link #isUsingDefaultSelectEffect()} to disable 466 * the default dimming effect applied by the library. 467 */ 468 protected void onSelectLevelChanged(ViewHolder vh) { 469 if (getSelectEffectEnabled()) { 470 vh.mColorDimmer.setActiveLevel(vh.mSelectLevel); 471 if (vh.mHeaderViewHolder != null) { 472 mHeaderPresenter.setSelectLevel(vh.mHeaderViewHolder, vh.mSelectLevel); 473 } 474 if (isUsingDefaultSelectEffect()) { 475 ((RowContainerView) vh.mContainerViewHolder.view).setForegroundColor( 476 vh.mColorDimmer.getPaint().getColor()); 477 } 478 } 479 } 480 481 /** 482 * Enables or disables the row selection effect. 483 * This will not only affect the default dim effect, but subclasses must 484 * respect this flag as well. 485 */ 486 public final void setSelectEffectEnabled(boolean applyDimOnSelect) { 487 mSelectEffectEnabled = applyDimOnSelect; 488 } 489 490 /** 491 * Returns true if the row selection effect is enabled. 492 * This value not only determines whether the default dim implementation is 493 * used, but subclasses must also respect this flag. 494 */ 495 public final boolean getSelectEffectEnabled() { 496 return mSelectEffectEnabled; 497 } 498 499 /** 500 * Return whether this RowPresenter is using the default dimming effect 501 * provided by the library. Subclasses may(most likely) return false and 502 * override {@link #onSelectLevelChanged(ViewHolder)}. 503 */ 504 public boolean isUsingDefaultSelectEffect() { 505 return true; 506 } 507 508 final boolean needsDefaultSelectEffect() { 509 return isUsingDefaultSelectEffect() && getSelectEffectEnabled(); 510 } 511 512 final boolean needsRowContainerView() { 513 return mHeaderPresenter != null || needsDefaultSelectEffect(); 514 } 515 516 /** 517 * Return true if the Row view can draw outside its bounds. 518 */ 519 public boolean canDrawOutOfBounds() { 520 return false; 521 } 522 523 @Override 524 public final void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) { 525 onBindRowViewHolder(getRowViewHolder(viewHolder), item); 526 } 527 528 protected void onBindRowViewHolder(ViewHolder vh, Object item) { 529 vh.mRow = (Row) item; 530 if (vh.mHeaderViewHolder != null) { 531 mHeaderPresenter.onBindViewHolder(vh.mHeaderViewHolder, item); 532 } 533 } 534 535 @Override 536 public final void onUnbindViewHolder(Presenter.ViewHolder viewHolder) { 537 onUnbindRowViewHolder(getRowViewHolder(viewHolder)); 538 } 539 540 protected void onUnbindRowViewHolder(ViewHolder vh) { 541 if (vh.mHeaderViewHolder != null) { 542 mHeaderPresenter.onUnbindViewHolder(vh.mHeaderViewHolder); 543 } 544 vh.mRow = null; 545 } 546 547 @Override 548 public final void onViewAttachedToWindow(Presenter.ViewHolder holder) { 549 onRowViewAttachedToWindow(getRowViewHolder(holder)); 550 } 551 552 protected void onRowViewAttachedToWindow(ViewHolder vh) { 553 if (vh.mHeaderViewHolder != null) { 554 mHeaderPresenter.onViewAttachedToWindow(vh.mHeaderViewHolder); 555 } 556 } 557 558 @Override 559 public final void onViewDetachedFromWindow(Presenter.ViewHolder holder) { 560 onRowViewDetachedFromWindow(getRowViewHolder(holder)); 561 } 562 563 protected void onRowViewDetachedFromWindow(ViewHolder vh) { 564 if (vh.mHeaderViewHolder != null) { 565 mHeaderPresenter.onViewDetachedFromWindow(vh.mHeaderViewHolder); 566 } 567 cancelAnimationsRecursive(vh.view); 568 } 569 570 /** 571 * Set the listener for item or row selection. A RowPresenter fires a row 572 * selection event with a null item. Subclasses (e.g. {@link ListRowPresenter}) 573 * can fire a selection event with the selected item. 574 */ 575 public final void setOnItemSelectedListener(OnItemSelectedListener listener) { 576 mOnItemSelectedListener = listener; 577 } 578 579 /** 580 * Get the listener for item or row selection. 581 */ 582 public final OnItemSelectedListener getOnItemSelectedListener() { 583 return mOnItemSelectedListener; 584 } 585 586 /** 587 * Set the listener for item click events. A RowPresenter does not use this 588 * listener, but a subclass may fire an item click event if it has the concept 589 * of an item. The {@link OnItemClickedListener} will override any 590 * {@link View.OnClickListener} that an item's Presenter sets during 591 * {@link Presenter#onCreateViewHolder(ViewGroup)}. So in general, you 592 * should choose to use an OnItemClickedListener or a {@link 593 * View.OnClickListener}, but not both. 594 */ 595 public final void setOnItemClickedListener(OnItemClickedListener listener) { 596 mOnItemClickedListener = listener; 597 } 598 599 /** 600 * Get the listener for item click events. 601 */ 602 public final OnItemClickedListener getOnItemClickedListener() { 603 return mOnItemClickedListener; 604 } 605 606 /** 607 * Set listener for item or row selection. RowPresenter fires row selection 608 * event with null item, subclass of RowPresenter e.g. {@link ListRowPresenter} can 609 * fire a selection event with selected item. 610 */ 611 public final void setOnItemViewSelectedListener(OnItemViewSelectedListener listener) { 612 mOnItemViewSelectedListener = listener; 613 } 614 615 /** 616 * Get listener for item or row selection. 617 */ 618 public final OnItemViewSelectedListener getOnItemViewSelectedListener() { 619 return mOnItemViewSelectedListener; 620 } 621 622 /** 623 * Set listener for item click event. RowPresenter does nothing but subclass of 624 * RowPresenter may fire item click event if it does have a concept of item. 625 * OnItemViewClickedListener will override {@link View.OnClickListener} that 626 * item presenter sets during {@link Presenter#onCreateViewHolder(ViewGroup)}. 627 * So in general, developer should choose one of the listeners but not both. 628 */ 629 public final void setOnItemViewClickedListener(OnItemViewClickedListener listener) { 630 mOnItemViewClickedListener = listener; 631 } 632 633 /** 634 * Set listener for item click event. 635 */ 636 public final OnItemViewClickedListener getOnItemViewClickedListener() { 637 return mOnItemViewClickedListener; 638 } 639 640 /** 641 * Freeze/Unfreeze the row, typically used when transition starts/ends. 642 * This method is called by fragment, app should not call it directly. 643 */ 644 public void freeze(ViewHolder holder, boolean freeze) { 645 } 646 647 /** 648 * Change visibility of views, entrance transition will be run against the views that 649 * change visibilities. Subclass may override and begin with calling 650 * super.setEntranceTransitionState(). This method is called by fragment, 651 * app should not call it directly. 652 */ 653 public void setEntranceTransitionState(ViewHolder holder, boolean afterTransition) { 654 if (holder.mHeaderViewHolder != null && 655 holder.mHeaderViewHolder.view.getVisibility() != View.GONE) { 656 holder.mHeaderViewHolder.view.setVisibility(afterTransition ? 657 View.VISIBLE : View.INVISIBLE); 658 } 659 } 660} 661