ListRowPresenter.java revision 5870e4aca782a55d0e8f7650f06aec86080b2f88
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.content.Context; 17import android.content.res.TypedArray; 18import android.support.v17.leanback.R; 19import android.util.Log; 20import android.view.KeyEvent; 21import android.view.View; 22import android.view.ViewGroup; 23import android.view.ViewGroup.LayoutParams; 24 25import java.util.HashMap; 26 27/** 28 * ListRowPresenter renders {@link ListRow} using a 29 * {@link HorizontalGridView} hosted in a {@link ListRowView}. 30 * 31 * <h3>Hover card</h3> 32 * Optionally, {@link #setHoverCardPresenterSelector(PresenterSelector)} can be used to 33 * display a view for the currently focused list item below the rendered 34 * list. This view is known as a hover card. 35 * 36 * <h3>Selection animation</h3> 37 * ListRowPresenter disables {@link RowPresenter}'s default dimming effect and draw 38 * a dim overlay on top of each individual child items. Subclass may override and disable 39 * {@link #isUsingDefaultListSelectEffect()} and write its own dim effect in 40 * {@link #onSelectLevelChanged(RowPresenter.ViewHolder)}. 41 * 42 * <h3>Shadow</h3> 43 * ListRowPresenter applies a default shadow to child of each view. Call 44 * {@link #setShadowEnabled(boolean)} to disable shadow. Subclass may override and return 45 * false in {@link #isUsingDefaultShadow()} and replace with its own shadow implementation. 46 */ 47public class ListRowPresenter extends RowPresenter { 48 49 private static final String TAG = "ListRowPresenter"; 50 private static final boolean DEBUG = false; 51 52 private static final int DEFAULT_RECYCLED_POOL_SIZE = 24; 53 54 public static class ViewHolder extends RowPresenter.ViewHolder { 55 final ListRowPresenter mListRowPresenter; 56 final HorizontalGridView mGridView; 57 ItemBridgeAdapter mItemBridgeAdapter; 58 final HorizontalHoverCardSwitcher mHoverCardViewSwitcher = new HorizontalHoverCardSwitcher(); 59 final int mPaddingTop; 60 final int mPaddingBottom; 61 final int mPaddingLeft; 62 final int mPaddingRight; 63 64 public ViewHolder(View rootView, HorizontalGridView gridView, ListRowPresenter p) { 65 super(rootView); 66 mGridView = gridView; 67 mListRowPresenter = p; 68 mPaddingTop = mGridView.getPaddingTop(); 69 mPaddingBottom = mGridView.getPaddingBottom(); 70 mPaddingLeft = mGridView.getPaddingLeft(); 71 mPaddingRight = mGridView.getPaddingRight(); 72 } 73 74 public final ListRowPresenter getListRowPresenter() { 75 return mListRowPresenter; 76 } 77 78 public final HorizontalGridView getGridView() { 79 return mGridView; 80 } 81 82 public final ItemBridgeAdapter getBridgeAdapter() { 83 return mItemBridgeAdapter; 84 } 85 } 86 87 class ListRowPresenterItemBridgeAdapter extends ItemBridgeAdapter { 88 ListRowPresenter.ViewHolder mRowViewHolder; 89 90 ListRowPresenterItemBridgeAdapter(ListRowPresenter.ViewHolder rowViewHolder) { 91 mRowViewHolder = rowViewHolder; 92 } 93 94 @Override 95 public void onBind(final ItemBridgeAdapter.ViewHolder viewHolder) { 96 // Only when having an OnItemClickListner, we will attach the OnClickListener. 97 if (getOnItemViewClickedListener() != null) { 98 viewHolder.mHolder.view.setOnClickListener(new View.OnClickListener() { 99 @Override 100 public void onClick(View v) { 101 ItemBridgeAdapter.ViewHolder ibh = (ItemBridgeAdapter.ViewHolder) 102 mRowViewHolder.mGridView.getChildViewHolder(viewHolder.itemView); 103 if (getOnItemViewClickedListener() != null) { 104 getOnItemViewClickedListener().onItemClicked(viewHolder.mHolder, 105 ibh.mItem, mRowViewHolder, (ListRow) mRowViewHolder.mRow); 106 } 107 } 108 }); 109 } 110 } 111 112 @Override 113 public void onUnbind(ItemBridgeAdapter.ViewHolder viewHolder) { 114 if (getOnItemViewClickedListener() != null) { 115 viewHolder.mHolder.view.setOnClickListener(null); 116 } 117 } 118 119 @Override 120 public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder viewHolder) { 121 if (needsDefaultListSelectEffect()) { 122 int dimmedColor = mRowViewHolder.mColorDimmer.getPaint().getColor(); 123 ((ShadowOverlayContainer) viewHolder.itemView).setOverlayColor(dimmedColor); 124 } 125 mRowViewHolder.syncActivatedStatus(viewHolder.itemView); 126 } 127 128 @Override 129 public void onAddPresenter(Presenter presenter, int type) { 130 mRowViewHolder.getGridView().getRecycledViewPool().setMaxRecycledViews( 131 type, getRecycledPoolSize(presenter)); 132 } 133 } 134 135 private int mRowHeight; 136 private int mExpandedRowHeight; 137 private PresenterSelector mHoverCardPresenterSelector; 138 private int mFocusZoomFactor; 139 private boolean mUseFocusDimmer; 140 private boolean mShadowEnabled = true; 141 private int mBrowseRowsFadingEdgeLength = -1; 142 private boolean mRoundedCornersEnabled = true; 143 private HashMap<Presenter, Integer> mRecycledPoolSize = new HashMap<Presenter, Integer>(); 144 145 private static int sSelectedRowTopPadding; 146 private static int sExpandedSelectedRowTopPadding; 147 private static int sExpandedRowNoHovercardBottomPadding; 148 149 /** 150 * Constructs a ListRowPresenter with defaults. 151 * Uses {@link FocusHighlight#ZOOM_FACTOR_MEDIUM} for focus zooming and 152 * disabled dimming on focus. 153 */ 154 public ListRowPresenter() { 155 this(FocusHighlight.ZOOM_FACTOR_MEDIUM); 156 } 157 158 /** 159 * Constructs a ListRowPresenter with the given parameters. 160 * 161 * @param focusZoomFactor Controls the zoom factor used when an item view is focused. One of 162 * {@link FocusHighlight#ZOOM_FACTOR_NONE}, 163 * {@link FocusHighlight#ZOOM_FACTOR_SMALL}, 164 * {@link FocusHighlight#ZOOM_FACTOR_XSMALL}, 165 * {@link FocusHighlight#ZOOM_FACTOR_MEDIUM}, 166 * {@link FocusHighlight#ZOOM_FACTOR_LARGE} 167 * Dimming on focus defaults to disabled. 168 */ 169 public ListRowPresenter(int focusZoomFactor) { 170 this(focusZoomFactor, false); 171 } 172 173 /** 174 * Constructs a ListRowPresenter with the given parameters. 175 * 176 * @param focusZoomFactor Controls the zoom factor used when an item view is focused. One of 177 * {@link FocusHighlight#ZOOM_FACTOR_NONE}, 178 * {@link FocusHighlight#ZOOM_FACTOR_SMALL}, 179 * {@link FocusHighlight#ZOOM_FACTOR_XSMALL}, 180 * {@link FocusHighlight#ZOOM_FACTOR_MEDIUM}, 181 * {@link FocusHighlight#ZOOM_FACTOR_LARGE} 182 * @param useFocusDimmer determines if the FocusHighlighter will use the dimmer 183 */ 184 public ListRowPresenter(int focusZoomFactor, boolean useFocusDimmer) { 185 if (!FocusHighlightHelper.isValidZoomIndex(focusZoomFactor)) { 186 throw new IllegalArgumentException("Unhandled zoom factor"); 187 } 188 mFocusZoomFactor = focusZoomFactor; 189 mUseFocusDimmer = useFocusDimmer; 190 } 191 192 /** 193 * Sets the row height for rows created by this Presenter. Rows 194 * created before calling this method will not be updated. 195 * 196 * @param rowHeight Row height in pixels, or WRAP_CONTENT, or 0 197 * to use the default height. 198 */ 199 public void setRowHeight(int rowHeight) { 200 mRowHeight = rowHeight; 201 } 202 203 /** 204 * Returns the row height for list rows created by this Presenter. 205 */ 206 public int getRowHeight() { 207 return mRowHeight; 208 } 209 210 /** 211 * Sets the expanded row height for rows created by this Presenter. 212 * If not set, expanded rows have the same height as unexpanded 213 * rows. 214 * 215 * @param rowHeight The row height in to use when the row is expanded, 216 * in pixels, or WRAP_CONTENT, or 0 to use the default. 217 */ 218 public void setExpandedRowHeight(int rowHeight) { 219 mExpandedRowHeight = rowHeight; 220 } 221 222 /** 223 * Returns the expanded row height for rows created by this Presenter. 224 */ 225 public int getExpandedRowHeight() { 226 return mExpandedRowHeight != 0 ? mExpandedRowHeight : mRowHeight; 227 } 228 229 /** 230 * Returns the zoom factor used for focus highlighting. 231 */ 232 public final int getFocusZoomFactor() { 233 return mFocusZoomFactor; 234 } 235 /** 236 * Returns the zoom factor used for focus highlighting. 237 * @deprecated use {@link #getFocusZoomFactor} instead. 238 */ 239 @Deprecated public final int getZoomFactor() { 240 return mFocusZoomFactor; 241 } 242 243 /** 244 * Returns true if the focus dimmer is used for focus highlighting; false otherwise. 245 */ 246 public final boolean isFocusDimmerUsed() { 247 return mUseFocusDimmer; 248 } 249 250 private ItemBridgeAdapter.Wrapper mCardWrapper = new ItemBridgeAdapter.Wrapper() { 251 @Override 252 public View createWrapper(View root) { 253 ShadowOverlayContainer wrapper = new ShadowOverlayContainer(root.getContext()); 254 wrapper.setLayoutParams( 255 new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 256 wrapper.initialize(needsDefaultShadow(), 257 needsDefaultListSelectEffect(), 258 areChildRoundedCornersEnabled()); 259 return wrapper; 260 } 261 @Override 262 public void wrap(View wrapper, View wrapped) { 263 ((ShadowOverlayContainer) wrapper).wrap(wrapped); 264 } 265 }; 266 267 @Override 268 protected void initializeRowViewHolder(RowPresenter.ViewHolder holder) { 269 super.initializeRowViewHolder(holder); 270 final ViewHolder rowViewHolder = (ViewHolder) holder; 271 rowViewHolder.mItemBridgeAdapter = new ListRowPresenterItemBridgeAdapter(rowViewHolder); 272 if (needsDefaultListSelectEffect() || needsDefaultShadow() 273 || areChildRoundedCornersEnabled()) { 274 rowViewHolder.mItemBridgeAdapter.setWrapper(mCardWrapper); 275 } 276 if (needsDefaultShadow()) { 277 ShadowOverlayContainer.prepareParentForShadow(rowViewHolder.mGridView); 278 } 279 FocusHighlightHelper.setupBrowseItemFocusHighlight(rowViewHolder.mItemBridgeAdapter, 280 mFocusZoomFactor, mUseFocusDimmer); 281 rowViewHolder.mGridView.setFocusDrawingOrderEnabled(!isUsingZOrder()); 282 rowViewHolder.mGridView.setOnChildSelectedListener( 283 new OnChildSelectedListener() { 284 @Override 285 public void onChildSelected(ViewGroup parent, View view, int position, long id) { 286 selectChildView(rowViewHolder, view); 287 } 288 }); 289 rowViewHolder.mGridView.setOnUnhandledKeyListener( 290 new BaseGridView.OnUnhandledKeyListener() { 291 @Override 292 public boolean onUnhandledKey(KeyEvent event) { 293 if (rowViewHolder.getOnKeyListener() != null && 294 rowViewHolder.getOnKeyListener().onKey( 295 rowViewHolder.view, event.getKeyCode(), event)) { 296 return true; 297 } 298 return false; 299 } 300 }); 301 } 302 303 final boolean needsDefaultListSelectEffect() { 304 return isUsingDefaultListSelectEffect() && getSelectEffectEnabled(); 305 } 306 307 /** 308 * Sets the recycled pool size for the given presenter. 309 */ 310 public void setRecycledPoolSize(Presenter presenter, int size) { 311 mRecycledPoolSize.put(presenter, size); 312 } 313 314 /** 315 * Returns the recycled pool size for the given presenter. 316 */ 317 public int getRecycledPoolSize(Presenter presenter) { 318 return mRecycledPoolSize.containsKey(presenter) ? mRecycledPoolSize.get(presenter) : 319 DEFAULT_RECYCLED_POOL_SIZE; 320 } 321 322 /** 323 * Set {@link PresenterSelector} used for showing a select object in a hover card. 324 */ 325 public final void setHoverCardPresenterSelector(PresenterSelector selector) { 326 mHoverCardPresenterSelector = selector; 327 } 328 329 /** 330 * Get {@link PresenterSelector} used for showing a select object in a hover card. 331 */ 332 public final PresenterSelector getHoverCardPresenterSelector() { 333 return mHoverCardPresenterSelector; 334 } 335 336 /* 337 * Perform operations when a child of horizontal grid view is selected. 338 */ 339 private void selectChildView(ViewHolder rowViewHolder, View view) { 340 if (view != null) { 341 if (rowViewHolder.mExpanded && rowViewHolder.mSelected) { 342 ItemBridgeAdapter.ViewHolder ibh = (ItemBridgeAdapter.ViewHolder) 343 rowViewHolder.mGridView.getChildViewHolder(view); 344 345 if (mHoverCardPresenterSelector != null) { 346 rowViewHolder.mHoverCardViewSwitcher.select(rowViewHolder.mGridView, view, 347 ibh.mItem); 348 } 349 if (getOnItemViewSelectedListener() != null) { 350 getOnItemViewSelectedListener().onItemSelected(ibh.mHolder, ibh.mItem, 351 rowViewHolder, rowViewHolder.mRow); 352 } 353 } 354 } else { 355 if (mHoverCardPresenterSelector != null) { 356 rowViewHolder.mHoverCardViewSwitcher.unselect(); 357 } 358 if (getOnItemViewSelectedListener() != null) { 359 getOnItemViewSelectedListener().onItemSelected(null, null, 360 rowViewHolder, rowViewHolder.mRow); 361 } 362 } 363 } 364 365 private static void initStatics(Context context) { 366 if (sSelectedRowTopPadding == 0) { 367 sSelectedRowTopPadding = context.getResources().getDimensionPixelSize( 368 R.dimen.lb_browse_selected_row_top_padding); 369 sExpandedSelectedRowTopPadding = context.getResources().getDimensionPixelSize( 370 R.dimen.lb_browse_expanded_selected_row_top_padding); 371 sExpandedRowNoHovercardBottomPadding = context.getResources().getDimensionPixelSize( 372 R.dimen.lb_browse_expanded_row_no_hovercard_bottom_padding); 373 } 374 } 375 376 private int getSpaceUnderBaseline(ListRowPresenter.ViewHolder vh) { 377 RowHeaderPresenter.ViewHolder headerViewHolder = vh.getHeaderViewHolder(); 378 if (headerViewHolder != null) { 379 if (getHeaderPresenter() != null) { 380 return getHeaderPresenter().getSpaceUnderBaseline(headerViewHolder); 381 } 382 return headerViewHolder.view.getPaddingBottom(); 383 } 384 return 0; 385 } 386 387 private void setVerticalPadding(ListRowPresenter.ViewHolder vh) { 388 int paddingTop, paddingBottom; 389 // Note: sufficient bottom padding needed for card shadows. 390 if (vh.isExpanded()) { 391 int headerSpaceUnderBaseline = getSpaceUnderBaseline(vh); 392 if (DEBUG) Log.v(TAG, "headerSpaceUnderBaseline " + headerSpaceUnderBaseline); 393 paddingTop = (vh.isSelected() ? sExpandedSelectedRowTopPadding : vh.mPaddingTop) - 394 headerSpaceUnderBaseline; 395 paddingBottom = mHoverCardPresenterSelector == null ? 396 sExpandedRowNoHovercardBottomPadding : vh.mPaddingBottom; 397 } else if (vh.isSelected()) { 398 paddingTop = sSelectedRowTopPadding - vh.mPaddingBottom; 399 paddingBottom = sSelectedRowTopPadding; 400 } else { 401 paddingTop = 0; 402 paddingBottom = vh.mPaddingBottom; 403 } 404 vh.getGridView().setPadding(vh.mPaddingLeft, paddingTop, vh.mPaddingRight, 405 paddingBottom); 406 } 407 408 @Override 409 protected RowPresenter.ViewHolder createRowViewHolder(ViewGroup parent) { 410 initStatics(parent.getContext()); 411 ListRowView rowView = new ListRowView(parent.getContext()); 412 setupFadingEffect(rowView); 413 if (mRowHeight != 0) { 414 rowView.getGridView().setRowHeight(mRowHeight); 415 } 416 return new ViewHolder(rowView, rowView.getGridView(), this); 417 } 418 419 /** 420 * Dispatch item selected event using current selected item in the {@link HorizontalGridView}. 421 * The method should only be called from onRowViewSelected(). 422 */ 423 @Override 424 protected void dispatchItemSelectedListener(RowPresenter.ViewHolder holder, boolean selected) { 425 ViewHolder vh = (ViewHolder)holder; 426 ItemBridgeAdapter.ViewHolder itemViewHolder = (ItemBridgeAdapter.ViewHolder) 427 vh.mGridView.findViewHolderForPosition(vh.mGridView.getSelectedPosition()); 428 if (itemViewHolder == null) { 429 super.dispatchItemSelectedListener(holder, selected); 430 return; 431 } 432 433 if (selected) { 434 if (getOnItemViewSelectedListener() != null) { 435 getOnItemViewSelectedListener().onItemSelected( 436 itemViewHolder.getViewHolder(), itemViewHolder.mItem, vh, vh.getRow()); 437 } 438 } 439 } 440 441 @Override 442 protected void onRowViewSelected(RowPresenter.ViewHolder holder, boolean selected) { 443 super.onRowViewSelected(holder, selected); 444 ViewHolder vh = (ViewHolder) holder; 445 setVerticalPadding(vh); 446 updateFooterViewSwitcher(vh); 447 } 448 449 /* 450 * Show or hide hover card when row selection or expanded state is changed. 451 */ 452 private void updateFooterViewSwitcher(ViewHolder vh) { 453 if (vh.mExpanded && vh.mSelected) { 454 if (mHoverCardPresenterSelector != null) { 455 vh.mHoverCardViewSwitcher.init((ViewGroup) vh.view, 456 mHoverCardPresenterSelector); 457 } 458 ItemBridgeAdapter.ViewHolder ibh = (ItemBridgeAdapter.ViewHolder) 459 vh.mGridView.findViewHolderForPosition( 460 vh.mGridView.getSelectedPosition()); 461 selectChildView(vh, ibh == null ? null : ibh.itemView); 462 } else { 463 if (mHoverCardPresenterSelector != null) { 464 vh.mHoverCardViewSwitcher.unselect(); 465 } 466 } 467 } 468 469 private void setupFadingEffect(ListRowView rowView) { 470 // content is completely faded at 1/2 padding of left, fading length is 1/2 of padding. 471 HorizontalGridView gridView = rowView.getGridView(); 472 if (mBrowseRowsFadingEdgeLength < 0) { 473 TypedArray ta = gridView.getContext() 474 .obtainStyledAttributes(R.styleable.LeanbackTheme); 475 mBrowseRowsFadingEdgeLength = (int) ta.getDimension( 476 R.styleable.LeanbackTheme_browseRowsFadingEdgeLength, 0); 477 ta.recycle(); 478 } 479 gridView.setFadingLeftEdgeLength(mBrowseRowsFadingEdgeLength); 480 } 481 482 @Override 483 protected void onRowViewExpanded(RowPresenter.ViewHolder holder, boolean expanded) { 484 super.onRowViewExpanded(holder, expanded); 485 ViewHolder vh = (ViewHolder) holder; 486 if (getRowHeight() != getExpandedRowHeight()) { 487 int newHeight = expanded ? getExpandedRowHeight() : getRowHeight(); 488 vh.getGridView().setRowHeight(newHeight); 489 } 490 setVerticalPadding(vh); 491 updateFooterViewSwitcher(vh); 492 } 493 494 @Override 495 protected void onBindRowViewHolder(RowPresenter.ViewHolder holder, Object item) { 496 super.onBindRowViewHolder(holder, item); 497 ViewHolder vh = (ViewHolder) holder; 498 ListRow rowItem = (ListRow) item; 499 vh.mItemBridgeAdapter.setAdapter(rowItem.getAdapter()); 500 vh.mGridView.setAdapter(vh.mItemBridgeAdapter); 501 } 502 503 @Override 504 protected void onUnbindRowViewHolder(RowPresenter.ViewHolder holder) { 505 ViewHolder vh = (ViewHolder) holder; 506 vh.mGridView.setAdapter(null); 507 vh.mItemBridgeAdapter.clear(); 508 super.onUnbindRowViewHolder(holder); 509 } 510 511 /** 512 * ListRowPresenter overrides the default select effect of {@link RowPresenter} 513 * and return false. 514 */ 515 @Override 516 public final boolean isUsingDefaultSelectEffect() { 517 return false; 518 } 519 520 /** 521 * Returns true so that default select effect is applied to each individual 522 * child of {@link HorizontalGridView}. Subclass may return false to disable 523 * the default implementation. 524 * @see #onSelectLevelChanged(RowPresenter.ViewHolder) 525 */ 526 public boolean isUsingDefaultListSelectEffect() { 527 return true; 528 } 529 530 /** 531 * Returns true if SDK >= 18, where default shadow 532 * is applied to each individual child of {@link HorizontalGridView}. 533 * Subclass may return false to disable. 534 */ 535 public boolean isUsingDefaultShadow() { 536 return ShadowOverlayContainer.supportsShadow(); 537 } 538 539 /** 540 * Returns true if SDK >= L, where Z shadow is enabled so that Z order is enabled 541 * on each child of horizontal list. If subclass returns false in isUsingDefaultShadow() 542 * and does not use Z-shadow on SDK >= L, it should override isUsingZOrder() return false. 543 */ 544 public boolean isUsingZOrder() { 545 return ShadowHelper.getInstance().usesZShadow(); 546 } 547 548 /** 549 * Enable or disable child shadow. 550 * This is not only for enable/disable default shadow implementation but also subclass must 551 * respect this flag. 552 */ 553 public final void setShadowEnabled(boolean enabled) { 554 mShadowEnabled = enabled; 555 } 556 557 /** 558 * Returns true if child shadow is enabled. 559 * This is not only for enable/disable default shadow implementation but also subclass must 560 * respect this flag. 561 */ 562 public final boolean getShadowEnabled() { 563 return mShadowEnabled; 564 } 565 566 /** 567 * Enables or disabled rounded corners on children of this row. 568 * Supported on Android SDK >= L. 569 */ 570 public final void enableChildRoundedCorners(boolean enable) { 571 mRoundedCornersEnabled = enable; 572 } 573 574 /** 575 * Returns true if rounded corners are enabled for children of this row. 576 */ 577 public final boolean areChildRoundedCornersEnabled() { 578 return mRoundedCornersEnabled; 579 } 580 581 final boolean needsDefaultShadow() { 582 return isUsingDefaultShadow() && getShadowEnabled(); 583 } 584 585 @Override 586 public boolean canDrawOutOfBounds() { 587 return needsDefaultShadow(); 588 } 589 590 /** 591 * Applies select level to header and draw a default color dim over each child 592 * of {@link HorizontalGridView}. 593 * <p> 594 * Subclass may override this method. A subclass 595 * needs to call super.onSelectLevelChanged() for applying header select level 596 * and optionally applying a default select level to each child view of 597 * {@link HorizontalGridView} if {@link #isUsingDefaultListSelectEffect()} 598 * is true. Subclass may override {@link #isUsingDefaultListSelectEffect()} to return 599 * false and deal with the individual item select level by itself. 600 * </p> 601 */ 602 @Override 603 protected void onSelectLevelChanged(RowPresenter.ViewHolder holder) { 604 super.onSelectLevelChanged(holder); 605 if (needsDefaultListSelectEffect()) { 606 ViewHolder vh = (ViewHolder) holder; 607 int dimmedColor = vh.mColorDimmer.getPaint().getColor(); 608 for (int i = 0, count = vh.mGridView.getChildCount(); i < count; i++) { 609 ShadowOverlayContainer wrapper = (ShadowOverlayContainer) vh.mGridView.getChildAt(i); 610 wrapper.setOverlayColor(dimmedColor); 611 } 612 if (vh.mGridView.getFadingLeftEdge()) { 613 vh.mGridView.invalidate(); 614 } 615 } 616 } 617 618 @Override 619 public void freeze(RowPresenter.ViewHolder holder, boolean freeze) { 620 ViewHolder vh = (ViewHolder) holder; 621 vh.mGridView.setScrollEnabled(!freeze); 622 } 623 624 @Override 625 public void setEntranceTransitionState(RowPresenter.ViewHolder holder, 626 boolean afterEntrance) { 627 super.setEntranceTransitionState(holder, afterEntrance); 628 ((ViewHolder) holder).mGridView.setChildrenVisibility( 629 afterEntrance? View.VISIBLE : View.INVISIBLE); 630 } 631} 632