blob: b72dba3da4cc11beaa1449830cf093ff52205a10 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package androidx.leanback.widget;
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
import android.graphics.Paint;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.RestrictTo;
import androidx.leanback.R;
/**
* RowHeaderPresenter provides a default presentation for {@link HeaderItem} using a
* {@link RowHeaderView} and optionally a TextView for description. If a subclass creates its own
* view, the subclass must also override {@link #onCreateViewHolder(ViewGroup)},
* {@link #onSelectLevelChanged(ViewHolder)}.
*/
public class RowHeaderPresenter extends Presenter {
private final int mLayoutResourceId;
private final Paint mFontMeasurePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private boolean mNullItemVisibilityGone;
private final boolean mAnimateSelect;
/**
* Creates default RowHeaderPresenter using a title view and a description view.
* @see ViewHolder#ViewHolder(View)
*/
public RowHeaderPresenter() {
this(R.layout.lb_row_header);
}
/**
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
public RowHeaderPresenter(int layoutResourceId) {
this(layoutResourceId, true);
}
/**
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
public RowHeaderPresenter(int layoutResourceId, boolean animateSelect) {
mLayoutResourceId = layoutResourceId;
mAnimateSelect = animateSelect;
}
/**
* Optionally sets the view visibility to {@link View#GONE} when bound to null.
*/
public void setNullItemVisibilityGone(boolean nullItemVisibilityGone) {
mNullItemVisibilityGone = nullItemVisibilityGone;
}
/**
* Returns true if the view visibility is set to {@link View#GONE} when bound to null.
*/
public boolean isNullItemVisibilityGone() {
return mNullItemVisibilityGone;
}
/**
* A ViewHolder for the RowHeaderPresenter.
*/
public static class ViewHolder extends Presenter.ViewHolder {
float mSelectLevel;
int mOriginalTextColor;
float mUnselectAlpha;
RowHeaderView mTitleView;
TextView mDescriptionView;
/**
* Creating a new ViewHolder that supports title and description.
* @param view Root of Views.
*/
public ViewHolder(View view) {
super(view);
mTitleView = (RowHeaderView)view.findViewById(R.id.row_header);
mDescriptionView = (TextView)view.findViewById(R.id.row_header_description);
initColors();
}
/**
* Uses a single {@link RowHeaderView} for creating a new ViewHolder.
* @param view The single RowHeaderView.
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
public ViewHolder(RowHeaderView view) {
super(view);
mTitleView = view;
initColors();
}
void initColors() {
if (mTitleView != null) {
mOriginalTextColor = mTitleView.getCurrentTextColor();
}
mUnselectAlpha = view.getResources().getFraction(
R.fraction.lb_browse_header_unselect_alpha, 1, 1);
}
public final float getSelectLevel() {
return mSelectLevel;
}
}
@Override
public Presenter.ViewHolder onCreateViewHolder(ViewGroup parent) {
View root = LayoutInflater.from(parent.getContext())
.inflate(mLayoutResourceId, parent, false);
ViewHolder viewHolder = new ViewHolder(root);
if (mAnimateSelect) {
setSelectLevel(viewHolder, 0);
}
return viewHolder;
}
@Override
public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
HeaderItem headerItem = item == null ? null : ((Row) item).getHeaderItem();
RowHeaderPresenter.ViewHolder vh = (RowHeaderPresenter.ViewHolder)viewHolder;
if (headerItem == null) {
if (vh.mTitleView != null) {
vh.mTitleView.setText(null);
}
if (vh.mDescriptionView != null) {
vh.mDescriptionView.setText(null);
}
viewHolder.view.setContentDescription(null);
if (mNullItemVisibilityGone) {
viewHolder.view.setVisibility(View.GONE);
}
} else {
if (vh.mTitleView != null) {
vh.mTitleView.setText(headerItem.getName());
}
if (vh.mDescriptionView != null) {
if (TextUtils.isEmpty(headerItem.getDescription())) {
vh.mDescriptionView.setVisibility(View.GONE);
} else {
vh.mDescriptionView.setVisibility(View.VISIBLE);
}
vh.mDescriptionView.setText(headerItem.getDescription());
}
viewHolder.view.setContentDescription(headerItem.getContentDescription());
viewHolder.view.setVisibility(View.VISIBLE);
}
}
@Override
public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
RowHeaderPresenter.ViewHolder vh = (ViewHolder)viewHolder;
if (vh.mTitleView != null) {
vh.mTitleView.setText(null);
}
if (vh.mDescriptionView != null) {
vh.mDescriptionView.setText(null);
}
if (mAnimateSelect) {
setSelectLevel((ViewHolder) viewHolder, 0);
}
}
/**
* Sets the select level.
*/
public final void setSelectLevel(ViewHolder holder, float selectLevel) {
holder.mSelectLevel = selectLevel;
onSelectLevelChanged(holder);
}
/**
* Called when the select level changes. The default implementation sets the alpha on the view.
*/
protected void onSelectLevelChanged(ViewHolder holder) {
if (mAnimateSelect) {
holder.view.setAlpha(holder.mUnselectAlpha + holder.mSelectLevel
* (1f - holder.mUnselectAlpha));
}
}
/**
* Returns the space (distance in pixels) below the baseline of the
* text view, if one exists; otherwise, returns 0.
*/
public int getSpaceUnderBaseline(ViewHolder holder) {
int space = holder.view.getPaddingBottom();
if (holder.view instanceof TextView) {
space += (int) getFontDescent((TextView) holder.view, mFontMeasurePaint);
}
return space;
}
@SuppressWarnings("ReferenceEquality")
protected static float getFontDescent(TextView textView, Paint fontMeasurePaint) {
if (fontMeasurePaint.getTextSize() != textView.getTextSize()) {
fontMeasurePaint.setTextSize(textView.getTextSize());
}
if (fontMeasurePaint.getTypeface() != textView.getTypeface()) {
fontMeasurePaint.setTypeface(textView.getTypeface());
}
return fontMeasurePaint.descent();
}
}