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  */
14 package android.support.v17.leanback.widget;
15 
16 import android.graphics.Paint;
17 import android.support.v17.leanback.R;
18 import android.view.LayoutInflater;
19 import android.view.View;
20 import android.view.ViewGroup;
21 import android.widget.TextView;
22 
23 /**
24  * RowHeaderPresenter provides a default presentation for {@link HeaderItem} using a
25  * {@link RowHeaderView}. If a subclass creates its own view, the subclass must also override
26  * {@link #onSelectLevelChanged(ViewHolder)}.
27  */
28 public class RowHeaderPresenter extends Presenter {
29 
30     private final int mLayoutResourceId;
31     private final Paint mFontMeasurePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
32     private boolean mNullItemVisibilityGone;
33     private final boolean mAnimateSelect;
34 
RowHeaderPresenter()35     public RowHeaderPresenter() {
36         this(R.layout.lb_row_header);
37     }
38 
39     /**
40      * @hide
41      */
RowHeaderPresenter(int layoutResourceId)42     public RowHeaderPresenter(int layoutResourceId) {
43         this(layoutResourceId, true);
44     }
45 
46     /**
47      * @hide
48      */
RowHeaderPresenter(int layoutResourceId, boolean animateSelect)49     public RowHeaderPresenter(int layoutResourceId, boolean animateSelect) {
50         mLayoutResourceId = layoutResourceId;
51         mAnimateSelect = animateSelect;
52     }
53 
54     /**
55      * Optionally sets the view visibility to {@link View#GONE} when bound to null.
56      */
setNullItemVisibilityGone(boolean nullItemVisibilityGone)57     public void setNullItemVisibilityGone(boolean nullItemVisibilityGone) {
58         mNullItemVisibilityGone = nullItemVisibilityGone;
59     }
60 
61     /**
62      * Returns true if the view visibility is set to {@link View#GONE} when bound to null.
63      */
isNullItemVisibilityGone()64     public boolean isNullItemVisibilityGone() {
65         return mNullItemVisibilityGone;
66     }
67 
68     /**
69      * A ViewHolder for the RowHeaderPresenter.
70      */
71     public static class ViewHolder extends Presenter.ViewHolder {
72         float mSelectLevel;
73         int mOriginalTextColor;
74         float mUnselectAlpha;
75 
ViewHolder(View view)76         public ViewHolder(View view) {
77             super(view);
78         }
getSelectLevel()79         public final float getSelectLevel() {
80             return mSelectLevel;
81         }
82     }
83 
84     @Override
onCreateViewHolder(ViewGroup parent)85     public Presenter.ViewHolder onCreateViewHolder(ViewGroup parent) {
86         RowHeaderView headerView = (RowHeaderView) LayoutInflater.from(parent.getContext())
87                 .inflate(mLayoutResourceId, parent, false);
88 
89         ViewHolder viewHolder = new ViewHolder(headerView);
90         viewHolder.mOriginalTextColor = headerView.getCurrentTextColor();
91         viewHolder.mUnselectAlpha = parent.getResources().getFraction(
92                 R.fraction.lb_browse_header_unselect_alpha, 1, 1);
93         if (mAnimateSelect) {
94             setSelectLevel(viewHolder, 0);
95         }
96         return viewHolder;
97     }
98 
99     @Override
onBindViewHolder(Presenter.ViewHolder viewHolder, Object item)100     public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
101         HeaderItem headerItem = item == null ? null : ((Row) item).getHeaderItem();
102         if (headerItem == null) {
103             ((RowHeaderView) viewHolder.view).setText(null);
104             viewHolder.view.setContentDescription(null);
105             if (mNullItemVisibilityGone) {
106                 viewHolder.view.setVisibility(View.GONE);
107             }
108         } else {
109             viewHolder.view.setVisibility(View.VISIBLE);
110             ((RowHeaderView) viewHolder.view).setText(headerItem.getName());
111             viewHolder.view.setContentDescription(headerItem.getContentDescription());
112         }
113     }
114 
115     @Override
onUnbindViewHolder(Presenter.ViewHolder viewHolder)116     public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
117         ((RowHeaderView) viewHolder.view).setText(null);
118         if (mAnimateSelect) {
119             setSelectLevel((ViewHolder) viewHolder, 0);
120         }
121     }
122 
123     /**
124      * Sets the select level.
125      */
setSelectLevel(ViewHolder holder, float selectLevel)126     public final void setSelectLevel(ViewHolder holder, float selectLevel) {
127         holder.mSelectLevel = selectLevel;
128         onSelectLevelChanged(holder);
129     }
130 
131     /**
132      * Called when the select level changes.  The default implementation sets the alpha on the view.
133      */
onSelectLevelChanged(ViewHolder holder)134     protected void onSelectLevelChanged(ViewHolder holder) {
135         if (mAnimateSelect) {
136             holder.view.setAlpha(holder.mUnselectAlpha + holder.mSelectLevel *
137                     (1f - holder.mUnselectAlpha));
138         }
139     }
140 
141     /**
142      * Returns the space (distance in pixels) below the baseline of the
143      * text view, if one exists; otherwise, returns 0.
144      */
getSpaceUnderBaseline(ViewHolder holder)145     public int getSpaceUnderBaseline(ViewHolder holder) {
146         int space = holder.view.getPaddingBottom();
147         if (holder.view instanceof TextView) {
148             space += (int) getFontDescent((TextView) holder.view, mFontMeasurePaint);
149         }
150         return space;
151     }
152 
getFontDescent(TextView textView, Paint fontMeasurePaint)153     protected static float getFontDescent(TextView textView, Paint fontMeasurePaint) {
154         if (fontMeasurePaint.getTextSize() != textView.getTextSize()) {
155             fontMeasurePaint.setTextSize(textView.getTextSize());
156         }
157         if (fontMeasurePaint.getTypeface() != textView.getTypeface()) {
158             fontMeasurePaint.setTypeface(textView.getTypeface());
159         }
160         return fontMeasurePaint.descent();
161     }
162 }
163