DetailsOverviewRowPresenter.java revision 056561d81012983d2d27b8665c4aeabb427174cb
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.graphics.Color; 18import android.support.v17.leanback.R; 19import android.support.v7.widget.RecyclerView; 20import android.util.Log; 21import android.util.TypedValue; 22import android.view.LayoutInflater; 23import android.view.View; 24import android.view.ViewGroup; 25import android.widget.FrameLayout; 26import android.widget.ImageView; 27 28import java.util.Collection; 29 30/** 31 * DetailsOverviewRowPresenter renders {@link DetailsOverviewRow} to display an 32 * overview of an item. Typically this row will be the first row in a fragment 33 * such as {@link android.support.v17.leanback.app.DetailsFragment 34 * DetailsFragment}. 35 * 36 * <p>The detailed description is rendered using a {@link Presenter}. 37 */ 38public class DetailsOverviewRowPresenter extends RowPresenter { 39 40 private static final String TAG = "DetailsOverviewRowPresenter"; 41 private static final boolean DEBUG = false; 42 43 private static final int MORE_ACTIONS_FADE_MS = 100; 44 45 public static class ViewHolder extends RowPresenter.ViewHolder { 46 final ImageView mImageView; 47 final FrameLayout mDetailsDescriptionFrame; 48 final HorizontalGridView mActionsRow; 49 final View mMoreActionsView; 50 Presenter.ViewHolder mDetailsDescriptionViewHolder; 51 int mNumItems; 52 boolean mShowMoreRight; 53 boolean mShowMoreLeft; 54 boolean mShowMoreActions; 55 56 void bind(ItemBridgeAdapter bridgeAdapter) { 57 mNumItems = bridgeAdapter.getItemCount(); 58 bridgeAdapter.setAdapterListener(mAdapterListener); 59 60 mMoreActionsView.setAlpha(0f); 61 mShowMoreRight = false; 62 mShowMoreActions = false; 63 64 mShowMoreLeft = true; 65 showMoreLeft(false); 66 } 67 68 final ItemBridgeAdapter.AdapterListener mAdapterListener = 69 new ItemBridgeAdapter.AdapterListener() { 70 71 @Override 72 public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder viewHolder) { 73 checkFirstAndLastPosition(false); 74 } 75 @Override 76 public void onDetachedFromWindow(ItemBridgeAdapter.ViewHolder viewHolder) { 77 checkFirstAndLastPosition(false); 78 } 79 }; 80 81 final RecyclerView.OnScrollListener mScrollListener = 82 new RecyclerView.OnScrollListener() { 83 84 @Override 85 public void onScrollStateChanged(int newState) { 86 } 87 @Override 88 public void onScrolled(int dx, int dy) { 89 checkFirstAndLastPosition(true); 90 } 91 }; 92 93 private int getViewCenter(View view) { 94 return (view.getRight() - view.getLeft()) / 2; 95 } 96 97 private void checkFirstAndLastPosition(boolean fromScroll) { 98 RecyclerView.ViewHolder viewHolder; 99 100 viewHolder = mActionsRow.findViewHolderForPosition(mNumItems - 1); 101 boolean showRight = (viewHolder == null || 102 viewHolder.itemView.getRight() > mActionsRow.getWidth()); 103 104 boolean showMore = (viewHolder == null || 105 getViewCenter(viewHolder.itemView) > mActionsRow.getWidth()); 106 107 viewHolder = mActionsRow.findViewHolderForPosition(0); 108 boolean showLeft = (viewHolder == null || viewHolder.itemView.getLeft() < 0); 109 110 if (DEBUG) Log.v(TAG, "checkFirstAndLast fromScroll " + fromScroll + 111 " showRight " + showRight + " showLeft " + showLeft); 112 113 showMoreActions(showMore); 114 showMoreRight(showRight); 115 showMoreLeft(showLeft); 116 } 117 118 private void showMoreLeft(boolean show) { 119 if (show != mShowMoreLeft) { 120 mActionsRow.setFadingLeftEdge(show); 121 mShowMoreLeft = show; 122 } 123 } 124 125 private void showMoreRight(boolean show) { 126 if (show != mShowMoreRight) { 127 mActionsRow.setFadingRightEdge(show); 128 mShowMoreRight = show; 129 } 130 } 131 132 private void showMoreActions(boolean show) { 133 if (show != mShowMoreActions) { 134 mMoreActionsView.animate().alpha(show ? 1f : 0).setDuration( 135 MORE_ACTIONS_FADE_MS).start(); 136 mShowMoreActions = show; 137 } 138 } 139 140 public ViewHolder(View rootView) { 141 super(rootView); 142 mImageView = (ImageView) rootView.findViewById(R.id.details_overview_image); 143 mDetailsDescriptionFrame = 144 (FrameLayout) rootView.findViewById(R.id.details_overview_description); 145 mActionsRow = 146 (HorizontalGridView) rootView.findViewById(R.id.details_overview_actions); 147 mActionsRow.setOnScrollListener(mScrollListener); 148 149 final int fadeLength = rootView.getResources().getDimensionPixelSize( 150 R.dimen.lb_details_overview_actions_fade_size); 151 mActionsRow.setFadingRightEdgeLength(fadeLength); 152 mActionsRow.setFadingRightEdgeOffset(-fadeLength); 153 mActionsRow.setFadingLeftEdgeLength(fadeLength); 154 mActionsRow.setFadingLeftEdgeOffset(-fadeLength); 155 156 mMoreActionsView = rootView.findViewById(R.id.details_overview_actions_more); 157 } 158 } 159 160 private final Presenter mDetailsPresenter; 161 private final ActionPresenterSelector mActionPresenterSelector; 162 private final ItemBridgeAdapter mActionBridgeAdapter; 163 private int mBackgroundColor = Color.TRANSPARENT; 164 private boolean mBackgroundColorSet; 165 private boolean mIsStyleLarge = true; 166 167 /** 168 * Constructor that uses the given {@link Presenter} to render the detailed 169 * description for the row. 170 */ 171 public DetailsOverviewRowPresenter(Presenter detailsPresenter) { 172 setHeaderPresenter(null); 173 setSelectEffectEnabled(false); 174 mDetailsPresenter = detailsPresenter; 175 mActionPresenterSelector = new ActionPresenterSelector(); 176 mActionBridgeAdapter = new ItemBridgeAdapter(); 177 } 178 179 /** 180 * Sets the listener for action click events. 181 */ 182 public void setOnActionClickedListener(OnActionClickedListener listener) { 183 mActionPresenterSelector.setOnActionClickedListener(listener); 184 } 185 186 /** 187 * Gets the listener for action click events. 188 */ 189 public OnActionClickedListener getOnActionClickedListener() { 190 return mActionPresenterSelector.getOnActionClickedListener(); 191 } 192 193 /** 194 * Sets the background color. If not set a default from the theme will be used. 195 */ 196 public void setBackgroundColor(int color) { 197 mBackgroundColor = color; 198 mBackgroundColorSet = true; 199 } 200 201 /** 202 * Returns the background color. If no background color was set, returns transparent. 203 */ 204 public int getBackgroundColor() { 205 return mBackgroundColor; 206 } 207 208 /** 209 * Sets the layout style to be large or small. 210 * The default is large. 211 */ 212 public void setStyleLarge(boolean large) { 213 mIsStyleLarge = large; 214 } 215 216 /** 217 * Returns true if the layout style is large. 218 */ 219 public boolean isStyleLarge() { 220 return mIsStyleLarge; 221 } 222 223 private int getDefaultBackgroundColor(Context context) { 224 TypedValue outValue = new TypedValue(); 225 context.getTheme().resolveAttribute(R.attr.defaultBrandColor, outValue, true); 226 return context.getResources().getColor(outValue.resourceId); 227 } 228 229 @Override 230 protected RowPresenter.ViewHolder createRowViewHolder(ViewGroup parent) { 231 View v = LayoutInflater.from(parent.getContext()) 232 .inflate(R.layout.lb_details_overview, parent, false); 233 ViewHolder vh = new ViewHolder(v); 234 235 vh.mDetailsDescriptionViewHolder = 236 mDetailsPresenter.onCreateViewHolder(vh.mDetailsDescriptionFrame); 237 vh.mDetailsDescriptionFrame.addView(vh.mDetailsDescriptionViewHolder.view); 238 239 initDetailsOverview(v.findViewById(R.id.details_overview)); 240 241 return vh; 242 } 243 244 private void initDetailsOverview(View view) { 245 int resId = mIsStyleLarge ? R.dimen.lb_details_overview_height_large : 246 R.dimen.lb_details_overview_height_small; 247 248 ViewGroup.LayoutParams lp = view.getLayoutParams(); 249 lp.height = view.getResources().getDimensionPixelSize(resId); 250 view.setLayoutParams(lp); 251 252 view.setBackgroundColor(mBackgroundColorSet ? 253 mBackgroundColor : getDefaultBackgroundColor(view.getContext())); 254 255 } 256 257 @Override 258 protected void onBindRowViewHolder(RowPresenter.ViewHolder holder, Object item) { 259 super.onBindRowViewHolder(holder, item); 260 261 DetailsOverviewRow row = (DetailsOverviewRow) item; 262 ViewHolder vh = (ViewHolder) holder; 263 if (row.getImageDrawable() != null) { 264 vh.mImageView.setImageDrawable(row.getImageDrawable()); 265 } 266 if (vh.mDetailsDescriptionViewHolder == null) { 267 } 268 mDetailsPresenter.onBindViewHolder(vh.mDetailsDescriptionViewHolder, row); 269 270 mActionBridgeAdapter.clear(); 271 ArrayObjectAdapter aoa = new ArrayObjectAdapter(mActionPresenterSelector); 272 aoa.addAll(0, (Collection)row.getActions()); 273 274 mActionBridgeAdapter.setAdapter(aoa); 275 vh.mActionsRow.setAdapter(mActionBridgeAdapter); 276 277 vh.bind(mActionBridgeAdapter); 278 } 279 280 @Override 281 protected void onUnbindRowViewHolder(RowPresenter.ViewHolder holder) { 282 super.onUnbindRowViewHolder(holder); 283 284 ViewHolder vh = (ViewHolder) holder; 285 if (vh.mDetailsDescriptionViewHolder != null) { 286 mDetailsPresenter.onUnbindViewHolder(vh.mDetailsDescriptionViewHolder); 287 } 288 289 vh.mActionsRow.setAdapter(null); 290 } 291} 292