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