blob: 3bd46617d5004ad27b3a69d679a9a017852cd9eb [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 android.support.v17.leanback.widget;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
import android.support.v17.leanback.R;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.TextView;
/**
* An abstract {@link Presenter} for rendering a detailed description of an
* item. Typically this Presenter will be used in a DetailsOveriewRowPresenter.
*
* <p>Subclasses will override {@link #onBindDescription} to implement the data
* binding for this Presenter.
*/
public abstract class AbstractDetailsDescriptionPresenter extends Presenter {
public static class ViewHolder extends Presenter.ViewHolder {
private final TextView mTitle;
private final TextView mSubtitle;
private final TextView mBody;
private final int mTitleMargin;
private final int mUnderTitleBaselineMargin;
private final int mUnderSubtitleBaselineMargin;
private final int mTitleLineSpacing;
private final int mBodyLineSpacing;
private final int mBodyMaxLines;
private final int mBodyMinLines;
private final FontMetricsInt mTitleFontMetricsInt;
private final FontMetricsInt mSubtitleFontMetricsInt;
private final FontMetricsInt mBodyFontMetricsInt;
private ViewTreeObserver.OnPreDrawListener mPreDrawListener;
public ViewHolder(final View view) {
super(view);
mTitle = (TextView) view.findViewById(R.id.lb_details_description_title);
mSubtitle = (TextView) view.findViewById(R.id.lb_details_description_subtitle);
mBody = (TextView) view.findViewById(R.id.lb_details_description_body);
FontMetricsInt titleFontMetricsInt = getFontMetricsInt(mTitle);
final int titleAscent = view.getResources().getDimensionPixelSize(
R.dimen.lb_details_description_title_baseline);
// Ascent is negative
mTitleMargin = titleAscent + titleFontMetricsInt.ascent;
mUnderTitleBaselineMargin = view.getResources().getDimensionPixelSize(
R.dimen.lb_details_description_under_title_baseline_margin);
mUnderSubtitleBaselineMargin = view.getResources().getDimensionPixelSize(
R.dimen.lb_details_description_under_subtitle_baseline_margin);
mTitleLineSpacing = view.getResources().getDimensionPixelSize(
R.dimen.lb_details_description_title_line_spacing);
mBodyLineSpacing = view.getResources().getDimensionPixelSize(
R.dimen.lb_details_description_body_line_spacing);
mBodyMaxLines = view.getResources().getInteger(
R.integer.lb_details_description_body_max_lines);
mBodyMinLines = view.getResources().getInteger(
R.integer.lb_details_description_body_min_lines);
mTitleFontMetricsInt = getFontMetricsInt(mTitle);
mSubtitleFontMetricsInt = getFontMetricsInt(mSubtitle);
mBodyFontMetricsInt = getFontMetricsInt(mBody);
mTitle.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
addPreDrawListener();
}
});
}
void addPreDrawListener() {
if (mPreDrawListener != null) {
return;
}
mPreDrawListener = new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
final int titleLines = mTitle.getLineCount();
final int maxLines = titleLines > 1 ? mBodyMinLines : mBodyMaxLines;
if (mBody.getMaxLines() != maxLines) {
mBody.setMaxLines(maxLines);
return false;
} else {
removePreDrawListener();
return true;
}
}
};
view.getViewTreeObserver().addOnPreDrawListener(mPreDrawListener);
}
void removePreDrawListener() {
if (mPreDrawListener != null) {
view.getViewTreeObserver().removeOnPreDrawListener(mPreDrawListener);
mPreDrawListener = null;
}
}
public TextView getTitle() {
return mTitle;
}
public TextView getSubtitle() {
return mSubtitle;
}
public TextView getBody() {
return mBody;
}
private FontMetricsInt getFontMetricsInt(TextView textView) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextSize(textView.getTextSize());
paint.setTypeface(textView.getTypeface());
return paint.getFontMetricsInt();
}
}
@Override
public final ViewHolder onCreateViewHolder(ViewGroup parent) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.lb_details_description, parent, false);
return new ViewHolder(v);
}
@Override
public final void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
ViewHolder vh = (ViewHolder) viewHolder;
onBindDescription(vh, item);
boolean hasTitle = true;
if (TextUtils.isEmpty(vh.mTitle.getText())) {
vh.mTitle.setVisibility(View.GONE);
hasTitle = false;
} else {
vh.mTitle.setVisibility(View.VISIBLE);
vh.mTitle.setLineSpacing(vh.mTitleLineSpacing - vh.mTitle.getLineHeight() +
vh.mTitle.getLineSpacingExtra(), vh.mTitle.getLineSpacingMultiplier());
}
setTopMargin(vh.mTitle, vh.mTitleMargin);
boolean hasSubtitle = true;
if (TextUtils.isEmpty(vh.mSubtitle.getText())) {
vh.mSubtitle.setVisibility(View.GONE);
hasSubtitle = false;
} else {
vh.mSubtitle.setVisibility(View.VISIBLE);
if (hasTitle) {
setTopMargin(vh.mSubtitle, vh.mUnderTitleBaselineMargin +
vh.mSubtitleFontMetricsInt.ascent - vh.mTitleFontMetricsInt.descent);
} else {
setTopMargin(vh.mSubtitle, 0);
}
}
if (TextUtils.isEmpty(vh.mBody.getText())) {
vh.mBody.setVisibility(View.GONE);
} else {
vh.mBody.setVisibility(View.VISIBLE);
vh.mBody.setLineSpacing(vh.mBodyLineSpacing - vh.mBody.getLineHeight() +
vh.mBody.getLineSpacingExtra(), vh.mBody.getLineSpacingMultiplier());
if (hasSubtitle) {
setTopMargin(vh.mBody, vh.mUnderSubtitleBaselineMargin +
vh.mBodyFontMetricsInt.ascent - vh.mSubtitleFontMetricsInt.descent);
} else if (hasTitle) {
setTopMargin(vh.mBody, vh.mUnderTitleBaselineMargin +
vh.mBodyFontMetricsInt.ascent - vh.mTitleFontMetricsInt.descent);
} else {
setTopMargin(vh.mBody, 0);
}
}
}
/**
* Binds the data from the item referenced in the DetailsOverviewRow to the
* ViewHolder.
*
* @param vh The ViewHolder for this details description view.
* @param item The item from the DetailsOverviewRow being presented.
*/
protected abstract void onBindDescription(ViewHolder vh, Object item);
@Override
public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {}
@Override
public void onViewAttachedToWindow(Presenter.ViewHolder holder) {
// In case predraw listener was removed in detach, make sure
// we have the proper layout.
ViewHolder vh = (ViewHolder) holder;
vh.addPreDrawListener();
super.onViewAttachedToWindow(holder);
}
@Override
public void onViewDetachedFromWindow(Presenter.ViewHolder holder) {
ViewHolder vh = (ViewHolder) holder;
vh.removePreDrawListener();
super.onViewDetachedFromWindow(holder);
}
private void setTopMargin(TextView textView, int topMargin) {
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) textView.getLayoutParams();
lp.topMargin = topMargin;
textView.setLayoutParams(lp);
}
}