AbstractDetailsDescriptionPresenter.java revision 2a2b18cd1bc49aa5f51d2a2ab7272328ee0235f3
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.graphics.Paint;
17import android.graphics.Paint.FontMetricsInt;
18import android.support.v17.leanback.R;
19import android.text.TextUtils;
20import android.view.LayoutInflater;
21import android.view.View;
22import android.view.ViewGroup;
23import android.widget.TextView;
24
25/**
26 * An abstract {@link Presenter} for rendering a detailed description of an
27 * item. Typically this Presenter will be used in a DetailsOveriewRowPresenter.
28 *
29 * <p>Subclasses will override {@link #onBindDescription} to implement the data
30 * binding for this Presenter.
31 */
32public abstract class AbstractDetailsDescriptionPresenter extends Presenter {
33
34    public static class ViewHolder extends Presenter.ViewHolder {
35        private final TextView mTitle;
36        private final TextView mSubtitle;
37        private final TextView mBody;
38        private final int mTitleMargin;
39        private final int mUnderTitleBaselineMargin;
40        private final int mUnderSubtitleBaselineMargin;
41        private final int mTitleLineSpacing;
42        private final int mBodyLineSpacing;
43        private final int mBodyMaxLines;
44        private final int mBodyMinLines;
45        private final FontMetricsInt mTitleFontMetricsInt;
46        private final FontMetricsInt mSubtitleFontMetricsInt;
47        private final FontMetricsInt mBodyFontMetricsInt;
48
49        public ViewHolder(View view) {
50            super(view);
51            mTitle = (TextView) view.findViewById(R.id.lb_details_description_title);
52            mSubtitle = (TextView) view.findViewById(R.id.lb_details_description_subtitle);
53            mBody = (TextView) view.findViewById(R.id.lb_details_description_body);
54
55            FontMetricsInt titleFontMetricsInt = getFontMetricsInt(mTitle);
56            final int titleAscent = view.getResources().getDimensionPixelSize(
57                    R.dimen.lb_details_description_title_baseline);
58            // Ascent is negative
59            mTitleMargin = titleAscent + titleFontMetricsInt.ascent;
60
61            mUnderTitleBaselineMargin = view.getResources().getDimensionPixelSize(
62                    R.dimen.lb_details_description_under_title_baseline_margin);
63            mUnderSubtitleBaselineMargin = view.getResources().getDimensionPixelSize(
64                    R.dimen.lb_details_description_under_subtitle_baseline_margin);
65
66            mTitleLineSpacing = view.getResources().getDimensionPixelSize(
67                    R.dimen.lb_details_description_title_line_spacing);
68            mBodyLineSpacing = view.getResources().getDimensionPixelSize(
69                    R.dimen.lb_details_description_body_line_spacing);
70
71            mBodyMaxLines = view.getResources().getInteger(
72                    R.integer.lb_details_description_body_max_lines);
73            mBodyMinLines = view.getResources().getInteger(
74                    R.integer.lb_details_description_body_min_lines);
75
76            mTitleFontMetricsInt = getFontMetricsInt(mTitle);
77            mSubtitleFontMetricsInt = getFontMetricsInt(mSubtitle);
78            mBodyFontMetricsInt = getFontMetricsInt(mBody);
79
80            mTitle.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
81                @Override
82                public void onLayoutChange(View v, int left, int top, int right,
83                        int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
84                    mBody.setMaxLines(mTitle.getLineCount() > 1 ? mBodyMinLines : mBodyMaxLines);
85                }
86            });
87        }
88
89        public TextView getTitle() {
90            return mTitle;
91        }
92
93        public TextView getSubtitle() {
94            return mSubtitle;
95        }
96
97        public TextView getBody() {
98            return mBody;
99        }
100
101        private FontMetricsInt getFontMetricsInt(TextView textView) {
102            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
103            paint.setTextSize(textView.getTextSize());
104            paint.setTypeface(textView.getTypeface());
105            return paint.getFontMetricsInt();
106        }
107    }
108
109    @Override
110    public final ViewHolder onCreateViewHolder(ViewGroup parent) {
111        View v = LayoutInflater.from(parent.getContext())
112            .inflate(R.layout.lb_details_description, parent, false);
113        return new ViewHolder(v);
114    }
115
116    @Override
117    public final void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
118        ViewHolder vh = (ViewHolder) viewHolder;
119        DetailsOverviewRow row = (DetailsOverviewRow) item;
120        onBindDescription(vh, row.getItem());
121
122        boolean hasTitle = true;
123        if (TextUtils.isEmpty(vh.mTitle.getText())) {
124            vh.mTitle.setVisibility(View.GONE);
125            hasTitle = false;
126        } else {
127            vh.mTitle.setVisibility(View.VISIBLE);
128            vh.mTitle.setLineSpacing(vh.mTitleLineSpacing - vh.mTitle.getLineHeight() -
129                    vh.mTitle.getLineSpacingExtra(), vh.mTitle.getLineSpacingMultiplier());
130        }
131        setTopMargin(vh.mTitle, vh.mTitleMargin);
132
133        boolean hasSubtitle = true;
134        if (TextUtils.isEmpty(vh.mSubtitle.getText())) {
135            vh.mSubtitle.setVisibility(View.GONE);
136            hasSubtitle = false;
137        } else {
138            vh.mSubtitle.setVisibility(View.VISIBLE);
139            if (hasTitle) {
140                setTopMargin(vh.mSubtitle, vh.mUnderTitleBaselineMargin +
141                        vh.mSubtitleFontMetricsInt.ascent - vh.mTitleFontMetricsInt.descent);
142            } else {
143                setTopMargin(vh.mSubtitle, 0);
144            }
145        }
146
147        if (TextUtils.isEmpty(vh.mBody.getText())) {
148            vh.mBody.setVisibility(View.GONE);
149        } else {
150            vh.mBody.setVisibility(View.VISIBLE);
151            vh.mBody.setLineSpacing(vh.mBodyLineSpacing - vh.mBody.getLineHeight() -
152                    vh.mBody.getLineSpacingExtra(), vh.mBody.getLineSpacingMultiplier());
153
154            if (hasSubtitle) {
155                setTopMargin(vh.mBody, vh.mUnderSubtitleBaselineMargin +
156                        vh.mBodyFontMetricsInt.ascent - vh.mSubtitleFontMetricsInt.descent);
157            } else if (hasTitle) {
158                setTopMargin(vh.mBody, vh.mUnderTitleBaselineMargin +
159                        vh.mBodyFontMetricsInt.ascent - vh.mTitleFontMetricsInt.descent);
160            } else {
161                setTopMargin(vh.mBody, 0);
162            }
163        }
164    }
165
166    /**
167     * Binds the data from the item referenced in the DetailsOverviewRow to the
168     * ViewHolder.
169     *
170     * @param vh The ViewHolder for this details description view.
171     * @param item The item from the DetailsOverviewRow being presented.
172     */
173    protected abstract void onBindDescription(ViewHolder vh, Object item);
174
175    @Override
176    public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {}
177
178    private void setTopMargin(TextView textView, int topMargin) {
179        ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) textView.getLayoutParams();
180        lp.topMargin = topMargin;
181        textView.setLayoutParams(lp);
182    }
183}
184