blob: 7c9d5db2ff6f0444fa49405794b7029abff16cf4 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package android.support.v17.leanback.widget;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.os.Handler;
import android.support.v17.leanback.R;
import android.support.v17.leanback.widget.ListRowPresenter.ViewHolder;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.FrameLayout;
import android.widget.ImageView;
import java.util.Collection;
/**
* Renders a {@link DetailsOverviewRow} to display an overview of an item. Typically this row will
* be the first row in a fragment such as the
* {@link android.support.v17.leanback.app.DetailsFragment}. The View created by the
* FullWidthDetailsOverviewRowPresenter is made in three parts: logo view on the left, action list view on
* the top and a customizable detailed description view on the right.
*
* <p>The detailed description is rendered using a {@link Presenter} passed in
* {@link #FullWidthDetailsOverviewRowPresenter(Presenter)}. Typically this will be an instance of
* {@link AbstractDetailsDescriptionPresenter}. The application can access the detailed description
* ViewHolder from {@link ViewHolder#getDetailsDescriptionViewHolder()}.
* </p>
*
* <p>The logo view is rendered using a customizable {@link DetailsOverviewLogoPresenter} passed in
* {@link #FullWidthDetailsOverviewRowPresenter(Presenter, DetailsOverviewLogoPresenter)}. The application
* can access the logo ViewHolder from {@link ViewHolder#getLogoViewHolder()}.
* </p>
*
* <p>
* To support activity shared element transition, call {@link #setListener(Listener)} with
* {@link FullWidthDetailsOverviewSharedElementHelper} during Activity's onCreate(). Application is free to
* create its own "shared element helper" class using the Listener for image binding.
* Call {@link #setParticipatingEntranceTransition(boolean)} with false
* </p>
*
* <p>
* The view has three states: {@link #STATE_HALF} {@link #STATE_FULL} and {@link #STATE_SMALL}. See
* {@link android.support.v17.leanback.app.DetailsFragment} where it switches states based on
* selected row position.
* </p>
*/
public class FullWidthDetailsOverviewRowPresenter extends RowPresenter {
private static final String TAG = "FullWidthDetailsOverviewRowPresenter";
private static final boolean DEBUG = false;
private static Rect sTmpRect = new Rect();
private static final Handler sHandler = new Handler();
/**
* This is the default state corresponding to layout file. The view takes full width
* of screen and covers bottom half of the screen.
*/
public static final int STATE_HALF = 0;
/**
* This is the state when the view covers full width and height of screen.
*/
public static final int STATE_FULL = 1;
/**
* This is the state where the view shrinks to a small banner.
*/
public static final int STATE_SMALL = 2;
/**
* This is the alignment mode that the logo and description align to the starting edge of the
* overview view.
*/
public static final int ALIGN_MODE_START = 0;
/**
* This is the alignment mode that the ending edge of logo and the starting edge of description
* align to the middle of the overview view. Note that this might not be the exact horizontal
* center of the overview view.
*/
public static final int ALIGN_MODE_MIDDLE = 1;
/**
* Listeners for events on ViewHolder.
*/
public static abstract class Listener {
/**
* {@link FullWidthDetailsOverviewRowPresenter#notifyOnBindLogo(ViewHolder)} is called.
* @param vh The ViewHolder that has bound logo view.
*/
public void onBindLogo(ViewHolder vh) {
}
}
class ActionsItemBridgeAdapter extends ItemBridgeAdapter {
FullWidthDetailsOverviewRowPresenter.ViewHolder mViewHolder;
ActionsItemBridgeAdapter(FullWidthDetailsOverviewRowPresenter.ViewHolder viewHolder) {
mViewHolder = viewHolder;
}
@Override
public void onBind(final ItemBridgeAdapter.ViewHolder ibvh) {
if (mViewHolder.getOnItemViewClickedListener() != null ||
mActionClickedListener != null) {
ibvh.getPresenter().setOnClickListener(
ibvh.getViewHolder(), new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mViewHolder.getOnItemViewClickedListener() != null) {
mViewHolder.getOnItemViewClickedListener().onItemClicked(
ibvh.getViewHolder(), ibvh.getItem(),
mViewHolder, mViewHolder.getRow());
}
if (mActionClickedListener != null) {
mActionClickedListener.onActionClicked((Action) ibvh.getItem());
}
}
});
}
}
@Override
public void onUnbind(final ItemBridgeAdapter.ViewHolder ibvh) {
if (mViewHolder.getOnItemViewClickedListener() != null ||
mActionClickedListener != null) {
ibvh.getPresenter().setOnClickListener(ibvh.getViewHolder(), null);
}
}
@Override
public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder viewHolder) {
// Remove first to ensure we don't add ourselves more than once.
viewHolder.itemView.removeOnLayoutChangeListener(mViewHolder.mLayoutChangeListener);
viewHolder.itemView.addOnLayoutChangeListener(mViewHolder.mLayoutChangeListener);
}
@Override
public void onDetachedFromWindow(ItemBridgeAdapter.ViewHolder viewHolder) {
viewHolder.itemView.removeOnLayoutChangeListener(mViewHolder.mLayoutChangeListener);
mViewHolder.checkFirstAndLastPosition(false);
}
}
/**
* A ViewHolder for the DetailsOverviewRow.
*/
public class ViewHolder extends RowPresenter.ViewHolder {
protected final DetailsOverviewRow.Listener mRowListener = createRowListener();
protected DetailsOverviewRow.Listener createRowListener() {
return new DetailsOverviewRowListener();
}
public class DetailsOverviewRowListener extends DetailsOverviewRow.Listener {
@Override
public void onImageDrawableChanged(DetailsOverviewRow row) {
sHandler.removeCallbacks(mUpdateDrawableCallback);
sHandler.post(mUpdateDrawableCallback);
}
@Override
public void onItemChanged(DetailsOverviewRow row) {
if (mDetailsDescriptionViewHolder != null) {
mDetailsPresenter.onUnbindViewHolder(mDetailsDescriptionViewHolder);
}
mDetailsPresenter.onBindViewHolder(mDetailsDescriptionViewHolder, row.getItem());
}
@Override
public void onActionsAdapterChanged(DetailsOverviewRow row) {
bindActions(row.getActionsAdapter());
}
};
final ViewGroup mOverviewRoot;
final FrameLayout mOverviewFrame;
final ViewGroup mDetailsDescriptionFrame;
final HorizontalGridView mActionsRow;
final Presenter.ViewHolder mDetailsDescriptionViewHolder;
final DetailsOverviewLogoPresenter.ViewHolder mDetailsLogoViewHolder;
int mNumItems;
ItemBridgeAdapter mActionBridgeAdapter;
int mState = STATE_HALF;
final Runnable mUpdateDrawableCallback = new Runnable() {
@Override
public void run() {
Row row = getRow();
if (row == null) {
return;
}
mDetailsOverviewLogoPresenter.onBindViewHolder(mDetailsLogoViewHolder, row);
}
};
void bindActions(ObjectAdapter adapter) {
mActionBridgeAdapter.setAdapter(adapter);
mActionsRow.setAdapter(mActionBridgeAdapter);
mNumItems = mActionBridgeAdapter.getItemCount();
}
void onBind() {
DetailsOverviewRow row = (DetailsOverviewRow) getRow();
bindActions(row.getActionsAdapter());
row.addListener(mRowListener);
}
void onUnbind() {
DetailsOverviewRow row = (DetailsOverviewRow) getRow();
row.removeListener(mRowListener);
sHandler.removeCallbacks(mUpdateDrawableCallback);
}
final View.OnLayoutChangeListener mLayoutChangeListener =
new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
if (DEBUG) Log.v(TAG, "onLayoutChange " + v);
checkFirstAndLastPosition(false);
}
};
final OnChildSelectedListener mChildSelectedListener = new OnChildSelectedListener() {
@Override
public void onChildSelected(ViewGroup parent, View view, int position, long id) {
dispatchItemSelection(view);
}
};
void dispatchItemSelection(View view) {
if (!isSelected()) {
return;
}
ItemBridgeAdapter.ViewHolder ibvh = (ItemBridgeAdapter.ViewHolder) (view != null ?
mActionsRow.getChildViewHolder(view) :
mActionsRow.findViewHolderForPosition(mActionsRow.getSelectedPosition()));
if (ibvh == null) {
if (getOnItemViewSelectedListener() != null) {
getOnItemViewSelectedListener().onItemSelected(null, null,
ViewHolder.this, getRow());
}
} else {
if (getOnItemViewSelectedListener() != null) {
getOnItemViewSelectedListener().onItemSelected(ibvh.getViewHolder(), ibvh.getItem(),
ViewHolder.this, getRow());
}
}
};
final RecyclerView.OnScrollListener mScrollListener =
new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
checkFirstAndLastPosition(true);
}
};
private int getViewCenter(View view) {
return (view.getRight() - view.getLeft()) / 2;
}
private void checkFirstAndLastPosition(boolean fromScroll) {
RecyclerView.ViewHolder viewHolder;
viewHolder = mActionsRow.findViewHolderForPosition(mNumItems - 1);
boolean showRight = (viewHolder == null ||
viewHolder.itemView.getRight() > mActionsRow.getWidth());
viewHolder = mActionsRow.findViewHolderForPosition(0);
boolean showLeft = (viewHolder == null || viewHolder.itemView.getLeft() < 0);
if (DEBUG) Log.v(TAG, "checkFirstAndLast fromScroll " + fromScroll +
" showRight " + showRight + " showLeft " + showLeft);
}
/**
* Constructor for the ViewHolder.
*
* @param rootView The root View that this view holder will be attached
* to.
*/
public ViewHolder(View rootView, Presenter detailsPresenter,
DetailsOverviewLogoPresenter logoPresenter) {
super(rootView);
mOverviewRoot = (ViewGroup) rootView.findViewById(R.id.details_root);
mOverviewFrame = (FrameLayout) rootView.findViewById(R.id.details_frame);
mDetailsDescriptionFrame =
(ViewGroup) rootView.findViewById(R.id.details_overview_description);
mActionsRow =
(HorizontalGridView) mOverviewFrame.findViewById(R.id.details_overview_actions);
mActionsRow.setHasOverlappingRendering(false);
mActionsRow.setOnScrollListener(mScrollListener);
mActionsRow.setAdapter(mActionBridgeAdapter);
mActionsRow.setOnChildSelectedListener(mChildSelectedListener);
final int fadeLength = rootView.getResources().getDimensionPixelSize(
R.dimen.lb_details_overview_actions_fade_size);
mActionsRow.setFadingRightEdgeLength(fadeLength);
mActionsRow.setFadingLeftEdgeLength(fadeLength);
mDetailsDescriptionViewHolder =
detailsPresenter.onCreateViewHolder(mDetailsDescriptionFrame);
mDetailsDescriptionFrame.addView(mDetailsDescriptionViewHolder.view);
mDetailsLogoViewHolder = (DetailsOverviewLogoPresenter.ViewHolder)
logoPresenter.onCreateViewHolder(mOverviewRoot);
mOverviewRoot.addView(mDetailsLogoViewHolder.view);
}
/**
* Returns the rectangle area with a color background.
*/
public final ViewGroup getOverviewView() {
return mOverviewFrame;
}
/**
* Returns the ViewHolder for logo.
*/
public final DetailsOverviewLogoPresenter.ViewHolder getLogoViewHolder() {
return mDetailsLogoViewHolder;
}
/**
* Returns the ViewHolder for DetailsDescription.
*/
public final Presenter.ViewHolder getDetailsDescriptionViewHolder() {
return mDetailsDescriptionViewHolder;
}
/**
* Returns the root view for inserting details description.
*/
public final ViewGroup getDetailsDescriptionFrame() {
return mDetailsDescriptionFrame;
}
/**
* Returns the view of actions row.
*/
public final ViewGroup getActionsRow() {
return mActionsRow;
}
/**
* Returns current state of the ViewHolder set by
* {@link FullWidthDetailsOverviewRowPresenter#setState(ViewHolder, int)}.
*/
public final int getState() {
return mState;
}
}
protected int mInitialState = STATE_HALF;
private final Presenter mDetailsPresenter;
private final DetailsOverviewLogoPresenter mDetailsOverviewLogoPresenter;
private OnActionClickedListener mActionClickedListener;
private int mBackgroundColor = Color.TRANSPARENT;
private int mActionsBackgroundColor = Color.TRANSPARENT;
private boolean mBackgroundColorSet;
private boolean mActionsBackgroundColorSet;
private Listener mListener;
private boolean mParticipatingEntranceTransition;
private int mAlignmentMode;
/**
* Constructor for a FullWidthDetailsOverviewRowPresenter.
*
* @param detailsPresenter The {@link Presenter} used to render the detailed
* description of the row.
*/
public FullWidthDetailsOverviewRowPresenter(Presenter detailsPresenter) {
this(detailsPresenter, new DetailsOverviewLogoPresenter());
}
/**
* Constructor for a FullWidthDetailsOverviewRowPresenter.
*
* @param detailsPresenter The {@link Presenter} used to render the detailed
* description of the row.
* @param logoPresenter The {@link Presenter} used to render the logo view.
*/
public FullWidthDetailsOverviewRowPresenter(Presenter detailsPresenter,
DetailsOverviewLogoPresenter logoPresenter) {
setHeaderPresenter(null);
setSelectEffectEnabled(false);
mDetailsPresenter = detailsPresenter;
mDetailsOverviewLogoPresenter = logoPresenter;
}
/**
* Sets the listener for Action click events.
*/
public void setOnActionClickedListener(OnActionClickedListener listener) {
mActionClickedListener = listener;
}
/**
* Returns the listener for Action click events.
*/
public OnActionClickedListener getOnActionClickedListener() {
return mActionClickedListener;
}
/**
* Sets the background color. If not set, a default from the theme will be used.
*/
public final void setBackgroundColor(int color) {
mBackgroundColor = color;
mBackgroundColorSet = true;
}
/**
* Returns the background color. If {@link #setBackgroundColor(int)}, transparent
* is returned.
*/
public final int getBackgroundColor() {
return mBackgroundColor;
}
/**
* Sets the background color for Action Bar. If not set, a default from the theme will be
* used.
*/
public final void setActionsBackgroundColor(int color) {
mActionsBackgroundColor = color;
mActionsBackgroundColorSet = true;
}
/**
* Returns the background color of actions. If {@link #setActionsBackgroundColor(int)}
* is not called, transparent is returned.
*/
public final int getActionsBackgroundColor() {
return mActionsBackgroundColor;
}
/**
* Returns true if the overview should be part of shared element transition.
*/
public final boolean isParticipatingEntranceTransition() {
return mParticipatingEntranceTransition;
}
/**
* Sets if the overview should be part of shared element transition.
*/
public final void setParticipatingEntranceTransition(boolean participating) {
mParticipatingEntranceTransition = participating;
}
/**
* Change the initial state used to create ViewHolder.
*/
public final void setInitialState(int state) {
mInitialState = state;
}
/**
* Returns the initial state used to create ViewHolder.
*/
public final int getInitialState() {
return mInitialState;
}
/**
* Set alignment mode of Description.
*
* @param alignmentMode One of {@link #ALIGN_MODE_MIDDLE} or {@link #ALIGN_MODE_START}
*/
public final void setAlignmentMode(int alignmentMode) {
mAlignmentMode = alignmentMode;
}
/**
* Returns alignment mode of Description.
*
* @return One of {@link #ALIGN_MODE_MIDDLE} or {@link #ALIGN_MODE_START}.
*/
public final int getAlignmentMode() {
return mAlignmentMode;
}
@Override
protected boolean isClippingChildren() {
return true;
}
/**
* Set listener for details overview presenter. Must be called before creating
* ViewHolder.
*/
public final void setListener(Listener listener) {
mListener = listener;
}
/**
* Get resource id to inflate the layout. The layout must match {@link #STATE_HALF}
*/
protected int getLayoutResourceId() {
return R.layout.lb_fullwidth_details_overview;
}
@Override
protected RowPresenter.ViewHolder createRowViewHolder(ViewGroup parent) {
View v = LayoutInflater.from(parent.getContext())
.inflate(getLayoutResourceId(), parent, false);
final ViewHolder vh = new ViewHolder(v, mDetailsPresenter, mDetailsOverviewLogoPresenter);
mDetailsOverviewLogoPresenter.setContext(vh.mDetailsLogoViewHolder, vh, this);
setState(vh, mInitialState);
vh.mActionBridgeAdapter = new ActionsItemBridgeAdapter(vh);
final View overview = vh.mOverviewFrame;
if (mBackgroundColorSet) {
overview.setBackgroundColor(mBackgroundColor);
}
if (mActionsBackgroundColorSet) {
overview.findViewById(R.id.details_overview_actions_background)
.setBackgroundColor(mActionsBackgroundColor);
}
RoundedRectHelper.getInstance().setClipToRoundedOutline(overview, true);
if (!getSelectEffectEnabled()) {
vh.mOverviewFrame.setForeground(null);
}
vh.mActionsRow.setOnUnhandledKeyListener(new BaseGridView.OnUnhandledKeyListener() {
@Override
public boolean onUnhandledKey(KeyEvent event) {
if (vh.getOnKeyListener() != null) {
if (vh.getOnKeyListener().onKey(vh.view, event.getKeyCode(), event)) {
return true;
}
}
return false;
}
});
return vh;
}
private static int getNonNegativeWidth(Drawable drawable) {
final int width = (drawable == null) ? 0 : drawable.getIntrinsicWidth();
return (width > 0 ? width : 0);
}
private static int getNonNegativeHeight(Drawable drawable) {
final int height = (drawable == null) ? 0 : drawable.getIntrinsicHeight();
return (height > 0 ? height : 0);
}
@Override
protected void onBindRowViewHolder(RowPresenter.ViewHolder holder, Object item) {
super.onBindRowViewHolder(holder, item);
DetailsOverviewRow row = (DetailsOverviewRow) item;
ViewHolder vh = (ViewHolder) holder;
mDetailsOverviewLogoPresenter.onBindViewHolder(vh.mDetailsLogoViewHolder, row);
mDetailsPresenter.onBindViewHolder(vh.mDetailsDescriptionViewHolder, row.getItem());
vh.onBind();
}
@Override
protected void onUnbindRowViewHolder(RowPresenter.ViewHolder holder) {
ViewHolder vh = (ViewHolder) holder;
vh.onUnbind();
mDetailsPresenter.onUnbindViewHolder(vh.mDetailsDescriptionViewHolder);
mDetailsOverviewLogoPresenter.onUnbindViewHolder(vh.mDetailsLogoViewHolder);
super.onUnbindRowViewHolder(holder);
}
@Override
public final boolean isUsingDefaultSelectEffect() {
return false;
}
@Override
protected void onSelectLevelChanged(RowPresenter.ViewHolder holder) {
super.onSelectLevelChanged(holder);
if (getSelectEffectEnabled()) {
ViewHolder vh = (ViewHolder) holder;
int dimmedColor = vh.mColorDimmer.getPaint().getColor();
((ColorDrawable) vh.mOverviewFrame.getForeground().mutate()).setColor(dimmedColor);
}
}
@Override
protected void onRowViewAttachedToWindow(RowPresenter.ViewHolder vh) {
super.onRowViewAttachedToWindow(vh);
ViewHolder viewHolder = (ViewHolder) vh;
mDetailsPresenter.onViewAttachedToWindow(viewHolder.mDetailsDescriptionViewHolder);
mDetailsOverviewLogoPresenter.onViewAttachedToWindow(viewHolder.mDetailsLogoViewHolder);
}
@Override
protected void onRowViewDetachedFromWindow(RowPresenter.ViewHolder vh) {
super.onRowViewDetachedFromWindow(vh);
ViewHolder viewHolder = (ViewHolder) vh;
mDetailsPresenter.onViewDetachedFromWindow(viewHolder.mDetailsDescriptionViewHolder);
mDetailsOverviewLogoPresenter.onViewDetachedFromWindow(viewHolder.mDetailsLogoViewHolder);
}
/**
* Called by {@link DetailsOverviewLogoPresenter} to notify logo was bound to view.
* Application should not directly call this method.
* @param viewHolder The row ViewHolder that has logo bound to view.
*/
public final void notifyOnBindLogo(ViewHolder viewHolder) {
onLayoutOverviewFrame(viewHolder, viewHolder.getState(), true);
onLayoutLogo(viewHolder, viewHolder.getState(), true);
if (mListener != null) {
mListener.onBindLogo(viewHolder);
}
}
/**
* Layout logo position based on current state. Subclass may override.
* The method is called when a logo is bound to view or state changes.
* @param viewHolder The row ViewHolder that contains the logo.
* @param oldState The old state, can be same as current viewHolder.getState()
* @param logoChanged Whether logo was changed.
*/
protected void onLayoutLogo(ViewHolder viewHolder, int oldState, boolean logoChanged) {
View v = viewHolder.getLogoViewHolder().view;
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams)
v.getLayoutParams();
switch (mAlignmentMode) {
case ALIGN_MODE_START:
default:
lp.setMarginStart(v.getResources().getDimensionPixelSize(
R.dimen.lb_details_v2_logo_margin_start));
break;
case ALIGN_MODE_MIDDLE:
lp.setMarginStart(v.getResources().getDimensionPixelSize(R.dimen.lb_details_v2_left)
- lp.width);
break;
}
switch (viewHolder.getState()) {
case STATE_FULL:
default:
lp.topMargin =
v.getResources().getDimensionPixelSize(R.dimen.lb_details_v2_blank_height)
- lp.height / 2;
break;
case STATE_HALF:
lp.topMargin = v.getResources().getDimensionPixelSize(
R.dimen.lb_details_v2_blank_height) + v.getResources()
.getDimensionPixelSize(R.dimen.lb_details_v2_actions_height) + v
.getResources().getDimensionPixelSize(
R.dimen.lb_details_v2_description_margin_top);
break;
case STATE_SMALL:
lp.topMargin = 0;
break;
}
v.setLayoutParams(lp);
}
/**
* Layout overview frame based on current state. Subclass may override.
* The method is called when a logo is bound to view or state changes.
* @param viewHolder The row ViewHolder that contains the logo.
* @param oldState The old state, can be same as current viewHolder.getState()
* @param logoChanged Whether logo was changed.
*/
protected void onLayoutOverviewFrame(ViewHolder viewHolder, int oldState, boolean logoChanged) {
boolean wasBanner = oldState == STATE_SMALL;
boolean isBanner = viewHolder.getState() == STATE_SMALL;
if (wasBanner != isBanner || logoChanged) {
Resources res = viewHolder.view.getResources();
int frameMarginStart;
int descriptionMarginStart = 0;
int logoWidth = 0;
if (mDetailsOverviewLogoPresenter.isBoundToImage(viewHolder.getLogoViewHolder(),
(DetailsOverviewRow) viewHolder.getRow())) {
logoWidth = viewHolder.getLogoViewHolder().view.getLayoutParams().width;
}
switch (mAlignmentMode) {
case ALIGN_MODE_START:
default:
if (isBanner) {
frameMarginStart = res.getDimensionPixelSize(
R.dimen.lb_details_v2_logo_margin_start);
descriptionMarginStart = logoWidth;
} else {
frameMarginStart = 0;
descriptionMarginStart = logoWidth + res.getDimensionPixelSize(
R.dimen.lb_details_v2_logo_margin_start);
}
break;
case ALIGN_MODE_MIDDLE:
if (isBanner) {
frameMarginStart = res.getDimensionPixelSize(R.dimen.lb_details_v2_left)
- logoWidth;
descriptionMarginStart = logoWidth;
} else {
frameMarginStart = 0;
descriptionMarginStart = res.getDimensionPixelSize(
R.dimen.lb_details_v2_left);
}
break;
}
MarginLayoutParams lpFrame =
(MarginLayoutParams) viewHolder.getOverviewView().getLayoutParams();
lpFrame.topMargin = isBanner ? 0
: res.getDimensionPixelSize(R.dimen.lb_details_v2_blank_height);
lpFrame.leftMargin = lpFrame.rightMargin = frameMarginStart;
viewHolder.getOverviewView().setLayoutParams(lpFrame);
View description = viewHolder.getDetailsDescriptionFrame();
MarginLayoutParams lpDesc = (MarginLayoutParams) description.getLayoutParams();
lpDesc.setMarginStart(descriptionMarginStart);
description.setLayoutParams(lpDesc);
View action = viewHolder.getActionsRow();
MarginLayoutParams lpActions = (MarginLayoutParams) action.getLayoutParams();
lpActions.setMarginStart(descriptionMarginStart);
lpActions.height =
isBanner ? 0 : res.getDimensionPixelSize(R.dimen.lb_details_v2_actions_height);
action.setLayoutParams(lpActions);
}
}
/**
* Switch state of a ViewHolder.
* @param viewHolder The ViewHolder to change state.
* @param state New state, can be {@link #STATE_FULL}, {@link #STATE_HALF}
* or {@link #STATE_SMALL}.
*/
public final void setState(ViewHolder viewHolder, int state) {
if (viewHolder.getState() != state) {
int oldState = viewHolder.getState();
viewHolder.mState = state;
onStateChanged(viewHolder, oldState);
}
}
/**
* Called when {@link ViewHolder#getState()} changes. Subclass may override.
* The default implementation calls {@link #onLayoutLogo(ViewHolder, int, boolean)} and
* {@link #onLayoutOverviewFrame(ViewHolder, int, boolean)}.
* @param viewHolder The ViewHolder which state changed.
* @param oldState The old state.
*/
protected void onStateChanged(ViewHolder viewHolder, int oldState) {
onLayoutOverviewFrame(viewHolder, oldState, false);
onLayoutLogo(viewHolder, oldState, false);
}
@Override
public void setEntranceTransitionState(RowPresenter.ViewHolder holder,
boolean afterEntrance) {
super.setEntranceTransitionState(holder, afterEntrance);
if (mParticipatingEntranceTransition) {
holder.view.setVisibility(afterEntrance? View.VISIBLE : View.INVISIBLE);
}
}
}