package android.support.v17.leanback.widget; import android.support.v17.leanback.R; import android.graphics.drawable.Drawable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.MarginLayoutParams; import android.widget.ImageView; /** * Presenter that responsible to create a ImageView and bind to DetailsOverviewRow. The default * implementation uses {@link DetailsOverviewRow#getImageDrawable()} and binds to {@link ImageView}. *
* Default implementation assumes no scaleType on ImageView and uses intrinsic width and height of * {@link DetailsOverviewRow#getImageDrawable()} to initialize ImageView's layout params. To * specify a fixed size and/or specify a scapeType, subclass should change ImageView's layout params * and scaleType in {@link #onCreateView(ViewGroup)}. *
* Subclass may override and has its own image view. Subclass may also download image from URL * instead of using {@link DetailsOverviewRow#getImageDrawable()}. It's subclass's responsibility to * call {@link FullWidthDetailsOverviewRowPresenter#notifyOnBindLogo(FullWidthDetailsOverviewRowPresenter.ViewHolder)} * whenever {@link #isBoundToImage(ViewHolder, DetailsOverviewRow)} turned to true so that activity * transition can be started. */ public class DetailsOverviewLogoPresenter extends Presenter { /** * ViewHolder for Logo view of DetailsOverviewRow. */ public static class ViewHolder extends Presenter.ViewHolder { protected FullWidthDetailsOverviewRowPresenter mParentPresenter; protected FullWidthDetailsOverviewRowPresenter.ViewHolder mParentViewHolder; private boolean mSizeFromDrawableIntrinsic; public ViewHolder(View view) { super(view); } public FullWidthDetailsOverviewRowPresenter getParentPresenter() { return mParentPresenter; } public FullWidthDetailsOverviewRowPresenter.ViewHolder getParentViewHolder() { return mParentViewHolder; } /** * @return True if layout size of ImageView should be changed to intrinsic size of Drawable, * false otherwise. Used by * {@link DetailsOverviewLogoPresenter#onBindViewHolder(Presenter.ViewHolder, Object)} * . * * @see DetailsOverviewLogoPresenter#onCreateView(ViewGroup) * @see DetailsOverviewLogoPresenter#onBindViewHolder(Presenter.ViewHolder, Object) */ public boolean isSizeFromDrawableIntrinsic() { return mSizeFromDrawableIntrinsic; } /** * Change if the ImageView layout size should be synchronized to Drawable intrinsic size. * Used by * {@link DetailsOverviewLogoPresenter#onBindViewHolder(Presenter.ViewHolder, Object)}. * * @param sizeFromDrawableIntrinsic True if layout size of ImageView should be changed to * intrinsic size of Drawable, false otherwise. * * @see DetailsOverviewLogoPresenter#onCreateView(ViewGroup) * @see DetailsOverviewLogoPresenter#onBindViewHolder(Presenter.ViewHolder, Object) */ public void setSizeFromDrawableIntrinsic(boolean sizeFromDrawableIntrinsic) { mSizeFromDrawableIntrinsic = sizeFromDrawableIntrinsic; } } /** * Create a View for the Logo, default implementation loads from * {@link R.layout#lb_fullwidth_details_overview_logo}. Subclass may override this method to use * a fixed layout size and change ImageView scaleType. If the layout params is WRAP_CONTENT for * both width and size, the ViewHolder would be using intrinsic size of Drawable in * {@link #onBindViewHolder(Presenter.ViewHolder, Object)}. * * @param parent Parent view. * @return View created for the logo. */ public View onCreateView(ViewGroup parent) { return LayoutInflater.from(parent.getContext()) .inflate(R.layout.lb_fullwidth_details_overview_logo, parent, false); } @Override public Presenter.ViewHolder onCreateViewHolder(ViewGroup parent) { View view = onCreateView(parent); ViewHolder vh = new ViewHolder(view); ViewGroup.LayoutParams lp = view.getLayoutParams(); vh.setSizeFromDrawableIntrinsic(lp.width == ViewGroup.LayoutParams.WRAP_CONTENT && lp.width == ViewGroup.LayoutParams.WRAP_CONTENT); return vh; } /** * Called from {@link FullWidthDetailsOverviewRowPresenter} to setup FullWidthDetailsOverviewRowPresenter * and FullWidthDetailsOverviewRowPresenter.ViewHolder that hosts the logo. * @param viewHolder * @param parentViewHolder * @param parentPresenter */ public void setContext(ViewHolder viewHolder, FullWidthDetailsOverviewRowPresenter.ViewHolder parentViewHolder, FullWidthDetailsOverviewRowPresenter parentPresenter) { viewHolder.mParentViewHolder = parentViewHolder; viewHolder.mParentPresenter = parentPresenter; } /** * Returns true if the logo view is bound to image. Subclass may override. The default * implementation returns true when {@link DetailsOverviewRow#getImageDrawable()} is not null. * If subclass of DetailsOverviewLogoPresenter manages its own image drawable, it should * override this function to report status correctly and invoke * {@link FullWidthDetailsOverviewRowPresenter#notifyOnBindLogo(FullWidthDetailsOverviewRowPresenter.ViewHolder)} * when image view is bound to the drawable. */ public boolean isBoundToImage(ViewHolder viewHolder, DetailsOverviewRow row) { return row != null && row.getImageDrawable() != null; } /** * Bind logo View to drawble of DetailsOverviewRow and call notifyOnBindLogo(). The * default implementation assumes the Logo View is an ImageView and change layout size to * intrinsic size of ImageDrawable if {@link ViewHolder#isSizeFromDrawableIntrinsic()} is true. * @param viewHolder ViewHolder to bind. * @param item DetailsOverviewRow object to bind. */ @Override public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) { DetailsOverviewRow row = (DetailsOverviewRow) item; ImageView imageView = ((ImageView) viewHolder.view); imageView.setImageDrawable(row.getImageDrawable()); if (isBoundToImage((ViewHolder) viewHolder, row)) { ViewHolder vh = (ViewHolder) viewHolder; if (vh.isSizeFromDrawableIntrinsic()) { ViewGroup.LayoutParams lp = imageView.getLayoutParams(); lp.width = row.getImageDrawable().getIntrinsicWidth(); lp.height = row.getImageDrawable().getIntrinsicHeight(); if (imageView.getMaxWidth() > 0 || imageView.getMaxHeight() > 0) { float maxScaleWidth = 1f; if (imageView.getMaxWidth() > 0) { if (lp.width > imageView.getMaxWidth()) { maxScaleWidth = imageView.getMaxWidth() / (float) lp.width; } } float maxScaleHeight = 1f; if (imageView.getMaxHeight() > 0) { if (lp.height > imageView.getMaxHeight()) { maxScaleHeight = imageView.getMaxHeight() / (float) lp.height; } } float scale = Math.min(maxScaleWidth, maxScaleHeight); lp.width = (int) (lp.width * scale); lp.height = (int) (lp.height * scale); } imageView.setLayoutParams(lp); } vh.mParentPresenter.notifyOnBindLogo(vh.mParentViewHolder); } } @Override public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) { } }