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