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