1package androidx.leanback.widget;
2
3import android.view.LayoutInflater;
4import android.view.View;
5import android.view.ViewGroup;
6import android.widget.ImageView;
7
8import 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 */
25public 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