Home | History | Annotate | Download | only in widget
      1 package androidx.leanback.widget;
      2 
      3 import android.view.LayoutInflater;
      4 import android.view.View;
      5 import android.view.ViewGroup;
      6 import android.widget.ImageView;
      7 
      8 import androidx.leanback.R;
      9 
     10 /**
     11  * Presenter that responsible to create a ImageView and bind to DetailsOverviewRow. The default
     12  * implementation uses {@link DetailsOverviewRow#getImageDrawable()} and binds to {@link ImageView}.
     13  * <p>
     14  * Default implementation assumes no scaleType on ImageView and uses intrinsic width and height of
     15  * {@link DetailsOverviewRow#getImageDrawable()} to initialize ImageView's layout params.  To
     16  * specify a fixed size and/or specify a scapeType, subclass should change ImageView's layout params
     17  * and scaleType in {@link #onCreateView(ViewGroup)}.
     18  * <p>
     19  * Subclass may override and has its own image view. Subclass may also download image from URL
     20  * instead of using {@link DetailsOverviewRow#getImageDrawable()}. It's subclass's responsibility to
     21  * call {@link FullWidthDetailsOverviewRowPresenter#notifyOnBindLogo(FullWidthDetailsOverviewRowPresenter.ViewHolder)}
     22  * whenever {@link #isBoundToImage(ViewHolder, DetailsOverviewRow)} turned to true so that activity
     23  * transition can be started.
     24  */
     25 public class DetailsOverviewLogoPresenter extends Presenter {
     26 
     27     /**
     28      * ViewHolder for Logo view of DetailsOverviewRow.
     29      */
     30     public static class ViewHolder extends Presenter.ViewHolder {
     31 
     32         protected FullWidthDetailsOverviewRowPresenter mParentPresenter;
     33         protected FullWidthDetailsOverviewRowPresenter.ViewHolder mParentViewHolder;
     34         private boolean mSizeFromDrawableIntrinsic;
     35 
     36         public ViewHolder(View view) {
     37             super(view);
     38         }
     39 
     40         public FullWidthDetailsOverviewRowPresenter getParentPresenter() {
     41             return mParentPresenter;
     42         }
     43 
     44         public FullWidthDetailsOverviewRowPresenter.ViewHolder getParentViewHolder() {
     45             return mParentViewHolder;
     46         }
     47 
     48         /**
     49          * @return True if layout size of ImageView should be changed to intrinsic size of Drawable,
     50          *         false otherwise. Used by
     51          *         {@link DetailsOverviewLogoPresenter#onBindViewHolder(Presenter.ViewHolder, Object)}
     52          *         .
     53          *
     54          * @see DetailsOverviewLogoPresenter#onCreateView(ViewGroup)
     55          * @see DetailsOverviewLogoPresenter#onBindViewHolder(Presenter.ViewHolder, Object)
     56          */
     57         public boolean isSizeFromDrawableIntrinsic() {
     58             return mSizeFromDrawableIntrinsic;
     59         }
     60 
     61         /**
     62          * Change if the ImageView layout size should be synchronized to Drawable intrinsic size.
     63          * Used by
     64          * {@link DetailsOverviewLogoPresenter#onBindViewHolder(Presenter.ViewHolder, Object)}.
     65          *
     66          * @param sizeFromDrawableIntrinsic True if layout size of ImageView should be changed to
     67          *        intrinsic size of Drawable, false otherwise.
     68          *
     69          * @see DetailsOverviewLogoPresenter#onCreateView(ViewGroup)
     70          * @see DetailsOverviewLogoPresenter#onBindViewHolder(Presenter.ViewHolder, Object)
     71          */
     72         public void setSizeFromDrawableIntrinsic(boolean sizeFromDrawableIntrinsic) {
     73             mSizeFromDrawableIntrinsic = sizeFromDrawableIntrinsic;
     74         }
     75     }
     76 
     77     /**
     78      * Create a View for the Logo, default implementation loads from
     79      * {@link R.layout#lb_fullwidth_details_overview_logo}. Subclass may override this method to use
     80      * a fixed layout size and change ImageView scaleType. If the layout params is WRAP_CONTENT for
     81      * both width and size, the ViewHolder would be using intrinsic size of Drawable in
     82      * {@link #onBindViewHolder(Presenter.ViewHolder, Object)}.
     83      *
     84      * @param parent Parent view.
     85      * @return View created for the logo.
     86      */
     87     public View onCreateView(ViewGroup parent) {
     88         return LayoutInflater.from(parent.getContext())
     89                 .inflate(R.layout.lb_fullwidth_details_overview_logo, parent, false);
     90     }
     91 
     92     @Override
     93     public Presenter.ViewHolder onCreateViewHolder(ViewGroup parent) {
     94         View view = onCreateView(parent);
     95         ViewHolder vh = new ViewHolder(view);
     96         ViewGroup.LayoutParams lp = view.getLayoutParams();
     97         vh.setSizeFromDrawableIntrinsic(lp.width == ViewGroup.LayoutParams.WRAP_CONTENT
     98                 && lp.height == ViewGroup.LayoutParams.WRAP_CONTENT);
     99         return vh;
    100     }
    101 
    102     /**
    103      * Called from {@link FullWidthDetailsOverviewRowPresenter} to setup FullWidthDetailsOverviewRowPresenter
    104      * and FullWidthDetailsOverviewRowPresenter.ViewHolder that hosts the logo.
    105      * @param viewHolder
    106      * @param parentViewHolder
    107      * @param parentPresenter
    108      */
    109     public void setContext(ViewHolder viewHolder,
    110             FullWidthDetailsOverviewRowPresenter.ViewHolder parentViewHolder,
    111             FullWidthDetailsOverviewRowPresenter parentPresenter) {
    112         viewHolder.mParentViewHolder = parentViewHolder;
    113         viewHolder.mParentPresenter = parentPresenter;
    114     }
    115 
    116     /**
    117      * Returns true if the logo view is bound to image. Subclass may override. The default
    118      * implementation returns true when {@link DetailsOverviewRow#getImageDrawable()} is not null.
    119      * If subclass of DetailsOverviewLogoPresenter manages its own image drawable, it should
    120      * override this function to report status correctly and invoke
    121      * {@link FullWidthDetailsOverviewRowPresenter#notifyOnBindLogo(FullWidthDetailsOverviewRowPresenter.ViewHolder)}
    122      * when image view is bound to the drawable.
    123      */
    124     public boolean isBoundToImage(ViewHolder viewHolder, DetailsOverviewRow row) {
    125         return row != null && row.getImageDrawable() != null;
    126     }
    127 
    128     /**
    129      * Bind logo View to drawable of DetailsOverviewRow and call notifyOnBindLogo().  The
    130      * default implementation assumes the Logo View is an ImageView and change layout size to
    131      * intrinsic size of ImageDrawable if {@link ViewHolder#isSizeFromDrawableIntrinsic()} is true.
    132      * @param viewHolder ViewHolder to bind.
    133      * @param item DetailsOverviewRow object to bind.
    134      */
    135     @Override
    136     public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
    137         DetailsOverviewRow row = (DetailsOverviewRow) item;
    138         ImageView imageView = ((ImageView) viewHolder.view);
    139         imageView.setImageDrawable(row.getImageDrawable());
    140         if (isBoundToImage((ViewHolder) viewHolder, row)) {
    141             ViewHolder vh = (ViewHolder) viewHolder;
    142             if (vh.isSizeFromDrawableIntrinsic()) {
    143                 ViewGroup.LayoutParams lp = imageView.getLayoutParams();
    144                 lp.width = row.getImageDrawable().getIntrinsicWidth();
    145                 lp.height = row.getImageDrawable().getIntrinsicHeight();
    146                 if (imageView.getMaxWidth() > 0 || imageView.getMaxHeight() > 0) {
    147                     float maxScaleWidth = 1f;
    148                     if (imageView.getMaxWidth() > 0) {
    149                         if (lp.width > imageView.getMaxWidth()) {
    150                             maxScaleWidth = imageView.getMaxWidth() / (float) lp.width;
    151                         }
    152                     }
    153                     float maxScaleHeight = 1f;
    154                     if (imageView.getMaxHeight() > 0) {
    155                         if (lp.height > imageView.getMaxHeight()) {
    156                             maxScaleHeight = imageView.getMaxHeight() / (float) lp.height;
    157                         }
    158                     }
    159                     float scale = Math.min(maxScaleWidth, maxScaleHeight);
    160                     lp.width = (int) (lp.width * scale);
    161                     lp.height = (int) (lp.height * scale);
    162                 }
    163                 imageView.setLayoutParams(lp);
    164             }
    165             vh.mParentPresenter.notifyOnBindLogo(vh.mParentViewHolder);
    166         }
    167     }
    168 
    169     @Override
    170     public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
    171     }
    172 
    173 }
    174