AbstractDetailsDescriptionPresenter.java revision 7c004076d5289caa0af7b5fb04cf7a3374be56b1
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 mUnderTitleBaseline;
40        private final int mUnderSubtitleBaseline;
41        private final int mBodyLineSpacing;
42        private final int mSubtitleAscent;
43        private final int mBodyAscent;
44
45        public ViewHolder(View view) {
46            super(view);
47            mTitle = (TextView) view.findViewById(R.id.lb_details_description_title);
48            mSubtitle = (TextView) view.findViewById(R.id.lb_details_description_subtitle);
49            mBody = (TextView) view.findViewById(R.id.lb_details_description_body);
50
51            FontMetricsInt titleFontMetricsInt = getFontMetricsInt(mTitle);
52            final int titleAscent = view.getResources().getDimensionPixelSize(
53                    R.dimen.lb_details_description_title_baseline);
54            // Ascent is negative
55            mTitleMargin = titleAscent + titleFontMetricsInt.ascent;
56
57            mUnderTitleBaseline = view.getResources().getDimensionPixelSize(
58                    R.dimen.lb_details_description_under_title_baseline);
59            mUnderSubtitleBaseline = view.getResources().getDimensionPixelSize(
60                    R.dimen.lb_details_description_under_subtitle_baseline);
61
62            FontMetricsInt subtitleFontMetricsInt = getFontMetricsInt(mSubtitle);
63            mSubtitleAscent = subtitleFontMetricsInt.ascent;
64
65            FontMetricsInt bodyFontMetricsInt = getFontMetricsInt(mBody);
66            mBodyAscent = bodyFontMetricsInt.ascent;
67
68            mBodyLineSpacing = view.getResources().getDimensionPixelSize(
69                    R.dimen.lb_details_description_body_line_spacing);
70        }
71
72        public TextView getTitle() {
73            return mTitle;
74        }
75
76        public TextView getSubtitle() {
77            return mSubtitle;
78        }
79
80        public TextView getBody() {
81            return mBody;
82        }
83
84        private FontMetricsInt getFontMetricsInt(TextView textView) {
85            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
86            paint.setTextSize(textView.getTextSize());
87            paint.setTypeface(textView.getTypeface());
88            return paint.getFontMetricsInt();
89        }
90    }
91
92    @Override
93    public final ViewHolder onCreateViewHolder(ViewGroup parent) {
94        View v = LayoutInflater.from(parent.getContext())
95            .inflate(R.layout.lb_details_description, parent, false);
96        return new ViewHolder(v);
97    }
98
99    @Override
100    public final void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
101        ViewHolder vh = (ViewHolder) viewHolder;
102        DetailsOverviewRow row = (DetailsOverviewRow) item;
103        onBindDescription(vh, row.getItem());
104
105        boolean hasTitle = true;
106        if (TextUtils.isEmpty(vh.mTitle.getText())) {
107            vh.mTitle.setVisibility(View.GONE);
108            hasTitle = false;
109        } else {
110            vh.mTitle.setVisibility(View.VISIBLE);
111        }
112        setTopMargin(vh.mTitle, vh.mTitleMargin);
113
114        boolean hasSubtitle = true;
115        if (TextUtils.isEmpty(vh.mSubtitle.getText())) {
116            vh.mSubtitle.setVisibility(View.GONE);
117            hasSubtitle = false;
118        } else {
119            vh.mSubtitle.setVisibility(View.VISIBLE);
120            if (hasTitle) {
121                setTopMargin(vh.mSubtitle, vh.mUnderTitleBaseline + vh.mSubtitleAscent);
122            } else {
123                setTopMargin(vh.mSubtitle, 0);
124            }
125        }
126
127        if (TextUtils.isEmpty(vh.mBody.getText())) {
128            vh.mBody.setVisibility(View.GONE);
129        } else {
130            vh.mBody.setVisibility(View.VISIBLE);
131            vh.mBody.setLineSpacing(vh.mBodyLineSpacing - vh.mBody.getLineHeight() -
132                    vh.mBody.getLineSpacingExtra(), vh.mBody.getLineSpacingMultiplier());
133
134            if (hasSubtitle) {
135                setTopMargin(vh.mBody, vh.mUnderSubtitleBaseline + vh.mBodyAscent);
136            } else if (hasTitle) {
137                setTopMargin(vh.mBody, vh.mUnderTitleBaseline + vh.mBodyAscent);
138            } else {
139                setTopMargin(vh.mBody, 0);
140            }
141        }
142    }
143
144    /**
145     * Binds the data from the item referenced in the DetailsOverviewRow to the
146     * ViewHolder.
147     *
148     * @param vh The ViewHolder for this details description view.
149     * @param item The item from the DetailsOverviewRow being presented.
150     */
151    protected abstract void onBindDescription(ViewHolder vh, Object item);
152
153    @Override
154    public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {}
155
156    private void setTopMargin(TextView textView, int topMargin) {
157        ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) textView.getLayoutParams();
158        lp.topMargin = topMargin;
159        textView.setLayoutParams(lp);
160    }
161}
162