aboutsummaryrefslogtreecommitdiff
path: root/src/com/android/tv/guide/ProgramItemView.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/tv/guide/ProgramItemView.java')
-rw-r--r--src/com/android/tv/guide/ProgramItemView.java522
1 files changed, 324 insertions, 198 deletions
diff --git a/src/com/android/tv/guide/ProgramItemView.java b/src/com/android/tv/guide/ProgramItemView.java
index b23d578c..9f379e43 100644
--- a/src/com/android/tv/guide/ProgramItemView.java
+++ b/src/com/android/tv/guide/ProgramItemView.java
@@ -24,7 +24,6 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.StateListDrawable;
import android.os.Handler;
-import android.os.SystemClock;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
@@ -35,21 +34,21 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
-
-import com.android.tv.ApplicationSingletons;
import com.android.tv.MainActivity;
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.analytics.Tracker;
import com.android.tv.common.feature.CommonFeatures;
-import com.android.tv.data.Channel;
+import com.android.tv.common.util.Clock;
+import com.android.tv.data.ChannelDataManager;
+import com.android.tv.data.Program;
+import com.android.tv.data.api.Channel;
import com.android.tv.dvr.DvrManager;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.ui.DvrUiHelper;
import com.android.tv.guide.ProgramManager.TableEntry;
import com.android.tv.util.ToastUtils;
import com.android.tv.util.Utils;
-
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.TimeUnit;
@@ -60,10 +59,10 @@ public class ProgramItemView extends TextView {
private static final int MAX_PROGRESS = 10000; // From android.widget.ProgressBar.MAX_VALUE
// State indicating the focused program is the current program
- private static final int[] STATE_CURRENT_PROGRAM = { R.attr.state_current_program };
+ private static final int[] STATE_CURRENT_PROGRAM = {R.attr.state_current_program};
// Workaround state in order to not use too much texture memory for RippleDrawable
- private static final int[] STATE_TOO_WIDE = { R.attr.state_program_too_wide };
+ private static final int[] STATE_TOO_WIDE = {R.attr.state_program_too_wide};
private static int sVisibleThreshold;
private static int sItemPadding;
@@ -73,8 +72,10 @@ public class ProgramItemView extends TextView {
private static TextAppearanceSpan sEpisodeTitleStyle;
private static TextAppearanceSpan sGrayedOutEpisodeTitleStyle;
+ private final DvrManager mDvrManager;
+ private final Clock mClock;
+ private final ChannelDataManager mChannelDataManager;
private ProgramGuide mProgramGuide;
- private DvrManager mDvrManager;
private TableEntry mTableEntry;
private int mMaxWidthForRipple;
private int mTextWidth;
@@ -84,96 +85,119 @@ public class ProgramItemView extends TextView {
// as a result of the re-layout (see b/21378855).
private boolean mPreventParentRelayout;
- private static final View.OnClickListener ON_CLICKED = new View.OnClickListener() {
- @Override
- public void onClick(final View view) {
- TableEntry entry = ((ProgramItemView) view).mTableEntry;
- if (entry == null) {
- //do nothing
- return;
- }
- ApplicationSingletons singletons = TvApplication.getSingletons(view.getContext());
- Tracker tracker = singletons.getTracker();
- tracker.sendEpgItemClicked();
- final MainActivity tvActivity = (MainActivity) view.getContext();
- final Channel channel = tvActivity.getChannelDataManager().getChannel(entry.channelId);
- if (entry.isCurrentProgram()) {
- view.postDelayed(new Runnable() {
- @Override
- public void run() {
- tvActivity.tuneToChannel(channel);
- tvActivity.hideOverlaysForTune();
+ private static final View.OnClickListener ON_CLICKED =
+ new View.OnClickListener() {
+ @Override
+ public void onClick(final View view) {
+ TableEntry entry = ((ProgramItemView) view).mTableEntry;
+ Clock clock = ((ProgramItemView) view).mClock;
+ if (entry == null) {
+ // do nothing
+ return;
}
- }, entry.getWidth() > ((ProgramItemView) view).mMaxWidthForRipple ? 0
- : view.getResources()
- .getInteger(R.integer.program_guide_ripple_anim_duration));
- } else if (entry.program != null && CommonFeatures.DVR.isEnabled(view.getContext())) {
- DvrManager dvrManager = singletons.getDvrManager();
- if (entry.entryStartUtcMillis > System.currentTimeMillis()
- && dvrManager.isProgramRecordable(entry.program)) {
- if (entry.scheduledRecording == null) {
- DvrUiHelper.checkStorageStatusAndShowErrorMessage(tvActivity,
- channel.getInputId(), new Runnable() {
+ TvSingletons singletons = TvSingletons.getSingletons(view.getContext());
+ Tracker tracker = singletons.getTracker();
+ tracker.sendEpgItemClicked();
+ final MainActivity tvActivity = (MainActivity) view.getContext();
+ final Channel channel =
+ tvActivity.getChannelDataManager().getChannel(entry.channelId);
+ if (entry.isCurrentProgram()) {
+ view.postDelayed(
+ new Runnable() {
@Override
public void run() {
- DvrUiHelper.requestRecordingFutureProgram(tvActivity,
- entry.program, false);
+ tvActivity.tuneToChannel(channel);
+ tvActivity.hideOverlaysForTune();
}
- });
- } else {
- dvrManager.removeScheduledRecording(entry.scheduledRecording);
- String msg = view.getResources().getString(
- R.string.dvr_schedules_deletion_info, entry.program.getTitle());
- ToastUtils.show(view.getContext(), msg, Toast.LENGTH_SHORT);
+ },
+ entry.getWidth() > ((ProgramItemView) view).mMaxWidthForRipple
+ ? 0
+ : view.getResources()
+ .getInteger(
+ R.integer
+ .program_guide_ripple_anim_duration));
+ } else if (entry.program != null
+ && CommonFeatures.DVR.isEnabled(view.getContext())) {
+ DvrManager dvrManager = singletons.getDvrManager();
+ if (entry.entryStartUtcMillis > clock.currentTimeMillis()
+ && dvrManager.isProgramRecordable(entry.program)) {
+ if (entry.scheduledRecording == null) {
+ DvrUiHelper.checkStorageStatusAndShowErrorMessage(
+ tvActivity,
+ channel.getInputId(),
+ new Runnable() {
+ @Override
+ public void run() {
+ DvrUiHelper.requestRecordingFutureProgram(
+ tvActivity, entry.program, false);
+ }
+ });
+ } else {
+ dvrManager.removeScheduledRecording(entry.scheduledRecording);
+ String msg =
+ view.getResources()
+ .getString(
+ R.string.dvr_schedules_deletion_info,
+ entry.program.getTitle());
+ ToastUtils.show(view.getContext(), msg, Toast.LENGTH_SHORT);
+ }
+ } else {
+ ToastUtils.show(
+ view.getContext(),
+ view.getResources()
+ .getString(R.string.dvr_msg_cannot_record_program),
+ Toast.LENGTH_SHORT);
+ }
}
- } else {
- ToastUtils.show(view.getContext(), view.getResources()
- .getString(R.string.dvr_msg_cannot_record_program), Toast.LENGTH_SHORT);
}
- }
- }
- };
+ };
private static final View.OnFocusChangeListener ON_FOCUS_CHANGED =
new View.OnFocusChangeListener() {
- @Override
- public void onFocusChange(View view, boolean hasFocus) {
- if (hasFocus) {
- ((ProgramItemView) view).mUpdateFocus.run();
- } else {
- Handler handler = view.getHandler();
- if (handler != null) {
- handler.removeCallbacks(((ProgramItemView) view).mUpdateFocus);
+ @Override
+ public void onFocusChange(View view, boolean hasFocus) {
+ if (hasFocus) {
+ ((ProgramItemView) view).mUpdateFocus.run();
+ } else {
+ Handler handler = view.getHandler();
+ if (handler != null) {
+ handler.removeCallbacks(((ProgramItemView) view).mUpdateFocus);
+ }
+ }
}
- }
- }
- };
-
- private final Runnable mUpdateFocus = new Runnable() {
- @Override
- public void run() {
- refreshDrawableState();
- TableEntry entry = mTableEntry;
- if (entry == null) {
- //do nothing
- return;
- }
- if (entry.isCurrentProgram()) {
- Drawable background = getBackground();
- if (!mProgramGuide.isActive() || mProgramGuide.isRunningAnimation()) {
- // If program guide is not active or is during showing/hiding,
- // the animation is unnecessary, skip it.
- background.jumpToCurrentState();
+ };
+
+ private final Runnable mUpdateFocus =
+ new Runnable() {
+ @Override
+ public void run() {
+ refreshDrawableState();
+ TableEntry entry = mTableEntry;
+ if (entry == null) {
+ // do nothing
+ return;
+ }
+ if (entry.isCurrentProgram()) {
+ Drawable background = getBackground();
+ if (!mProgramGuide.isActive() || mProgramGuide.isRunningAnimation()) {
+ // If program guide is not active or is during showing/hiding,
+ // the animation is unnecessary, skip it.
+ background.jumpToCurrentState();
+ }
+ int progress =
+ getProgress(
+ mClock, entry.entryStartUtcMillis, entry.entryEndUtcMillis);
+ setProgress(background, R.id.reverse_progress, MAX_PROGRESS - progress);
+ }
+ if (getHandler() != null) {
+ getHandler()
+ .postAtTime(
+ this,
+ Utils.ceilTime(
+ mClock.uptimeMillis(), FOCUS_UPDATE_FREQUENCY));
+ }
}
- int progress = getProgress(entry.entryStartUtcMillis, entry.entryEndUtcMillis);
- setProgress(background, R.id.reverse_progress, MAX_PROGRESS - progress);
- }
- if (getHandler() != null) {
- getHandler().postAtTime(this,
- Utils.ceilTime(SystemClock.uptimeMillis(), FOCUS_UPDATE_FREQUENCY));
- }
- }
- };
+ };
public ProgramItemView(Context context) {
this(context, null);
@@ -187,7 +211,10 @@ public class ProgramItemView extends TextView {
super(context, attrs, defStyle);
setOnClickListener(ON_CLICKED);
setOnFocusChangeListener(ON_FOCUS_CHANGED);
- mDvrManager = TvApplication.getSingletons(getContext()).getDvrManager();
+ TvSingletons singletons = TvSingletons.getSingletons(getContext());
+ mDvrManager = singletons.getDvrManager();
+ mChannelDataManager = singletons.getChannelDataManager();
+ mClock = singletons.getClock();
}
private void initIfNeeded() {
@@ -196,35 +223,46 @@ public class ProgramItemView extends TextView {
}
Resources res = getContext().getResources();
- sVisibleThreshold = res.getDimensionPixelOffset(
- R.dimen.program_guide_table_item_visible_threshold);
+ sVisibleThreshold =
+ res.getDimensionPixelOffset(R.dimen.program_guide_table_item_visible_threshold);
sItemPadding = res.getDimensionPixelOffset(R.dimen.program_guide_table_item_padding);
- sCompoundDrawablePadding = res.getDimensionPixelOffset(
- R.dimen.program_guide_table_item_compound_drawable_padding);
-
- ColorStateList programTitleColor = ColorStateList.valueOf(res.getColor(
- R.color.program_guide_table_item_program_title_text_color, null));
- ColorStateList grayedOutProgramTitleColor = res.getColorStateList(
- R.color.program_guide_table_item_grayed_out_program_text_color, null);
- ColorStateList episodeTitleColor = ColorStateList.valueOf(res.getColor(
- R.color.program_guide_table_item_program_episode_title_text_color, null));
- ColorStateList grayedOutEpisodeTitleColor = ColorStateList.valueOf(res.getColor(
- R.color.program_guide_table_item_grayed_out_program_episode_title_text_color,
- null));
- int programTitleSize = res.getDimensionPixelSize(
- R.dimen.program_guide_table_item_program_title_font_size);
- int episodeTitleSize = res.getDimensionPixelSize(
- R.dimen.program_guide_table_item_program_episode_title_font_size);
-
- sProgramTitleStyle = new TextAppearanceSpan(null, 0, programTitleSize, programTitleColor,
- null);
- sGrayedOutProgramTitleStyle = new TextAppearanceSpan(null, 0, programTitleSize,
- grayedOutProgramTitleColor, null);
- sEpisodeTitleStyle = new TextAppearanceSpan(null, 0, episodeTitleSize, episodeTitleColor,
- null);
- sGrayedOutEpisodeTitleStyle = new TextAppearanceSpan(null, 0, episodeTitleSize,
- grayedOutEpisodeTitleColor, null);
+ sCompoundDrawablePadding =
+ res.getDimensionPixelOffset(
+ R.dimen.program_guide_table_item_compound_drawable_padding);
+
+ ColorStateList programTitleColor =
+ ColorStateList.valueOf(
+ res.getColor(
+ R.color.program_guide_table_item_program_title_text_color, null));
+ ColorStateList grayedOutProgramTitleColor =
+ res.getColorStateList(
+ R.color.program_guide_table_item_grayed_out_program_text_color, null);
+ ColorStateList episodeTitleColor =
+ ColorStateList.valueOf(
+ res.getColor(
+ R.color.program_guide_table_item_program_episode_title_text_color,
+ null));
+ ColorStateList grayedOutEpisodeTitleColor =
+ ColorStateList.valueOf(
+ res.getColor(
+ R.color
+ .program_guide_table_item_grayed_out_program_episode_title_text_color,
+ null));
+ int programTitleSize =
+ res.getDimensionPixelSize(R.dimen.program_guide_table_item_program_title_font_size);
+ int episodeTitleSize =
+ res.getDimensionPixelSize(
+ R.dimen.program_guide_table_item_program_episode_title_font_size);
+
+ sProgramTitleStyle =
+ new TextAppearanceSpan(null, 0, programTitleSize, programTitleColor, null);
+ sGrayedOutProgramTitleStyle =
+ new TextAppearanceSpan(null, 0, programTitleSize, grayedOutProgramTitleColor, null);
+ sEpisodeTitleStyle =
+ new TextAppearanceSpan(null, 0, episodeTitleSize, episodeTitleColor, null);
+ sGrayedOutEpisodeTitleStyle =
+ new TextAppearanceSpan(null, 0, episodeTitleSize, grayedOutEpisodeTitleColor, null);
}
@Override
@@ -236,8 +274,9 @@ public class ProgramItemView extends TextView {
@Override
protected int[] onCreateDrawableState(int extraSpace) {
if (mTableEntry != null) {
- int states[] = super.onCreateDrawableState(extraSpace
- + STATE_CURRENT_PROGRAM.length + STATE_TOO_WIDE.length);
+ int[] states =
+ super.onCreateDrawableState(
+ extraSpace + STATE_CURRENT_PROGRAM.length + STATE_TOO_WIDE.length);
if (mTableEntry.isCurrentProgram()) {
mergeDrawableStates(states, STATE_CURRENT_PROGRAM);
}
@@ -254,86 +293,168 @@ public class ProgramItemView extends TextView {
}
@SuppressLint("SwitchIntDef")
- public void setValues(ProgramGuide programGuide, TableEntry entry, int selectedGenreId,
- long fromUtcMillis, long toUtcMillis, String gapTitle) {
+ public void setValues(
+ ProgramGuide programGuide,
+ TableEntry entry,
+ int selectedGenreId,
+ long fromUtcMillis,
+ long toUtcMillis,
+ String gapTitle) {
mProgramGuide = programGuide;
mTableEntry = entry;
ViewGroup.LayoutParams layoutParams = getLayoutParams();
- layoutParams.width = entry.getWidth();
- setLayoutParams(layoutParams);
+ if (layoutParams != null) {
+ // There is no layoutParams in the tests so we skip this
+ layoutParams.width = entry.getWidth();
+ setLayoutParams(layoutParams);
+ }
+ String title = mTableEntry.program != null ? mTableEntry.program.getTitle() : null;
+ if (mTableEntry.isGap()) {
+ title = gapTitle;
+ }
+ if (TextUtils.isEmpty(title)) {
+ title = getResources().getString(R.string.program_title_for_no_information);
+ }
+ updateText(selectedGenreId, title);
+ updateIcons();
+ updateContentDescription(title);
+ measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+ mTextWidth = getMeasuredWidth() - getPaddingStart() - getPaddingEnd();
+ // Maximum width for us to use a ripple
+ mMaxWidthForRipple = GuideUtils.convertMillisToPixel(fromUtcMillis, toUtcMillis);
+ }
- String title = entry.program != null ? entry.program.getTitle() : null;
- String episode = entry.program != null ?
- entry.program.getEpisodeDisplayTitle(getContext()) : null;
+ private boolean isEntryWideEnough() {
+ return mTableEntry != null && mTableEntry.getWidth() >= sVisibleThreshold;
+ }
+
+ private void updateText(int selectedGenreId, String title) {
+ if (!isEntryWideEnough()) {
+ setText(null);
+ return;
+ }
+
+ String episode =
+ mTableEntry.program != null
+ ? mTableEntry.program.getEpisodeDisplayTitle(getContext())
+ : null;
TextAppearanceSpan titleStyle = sGrayedOutProgramTitleStyle;
TextAppearanceSpan episodeStyle = sGrayedOutEpisodeTitleStyle;
+ if (mTableEntry.isGap()) {
- if (entry.getWidth() < sVisibleThreshold) {
- setText(null);
+ episode = null;
+ } else if (mTableEntry.hasGenre(selectedGenreId)) {
+ titleStyle = sProgramTitleStyle;
+ episodeStyle = sEpisodeTitleStyle;
+ }
+ SpannableStringBuilder description = new SpannableStringBuilder();
+ description.append(title);
+ if (!TextUtils.isEmpty(episode)) {
+ description.append('\n');
+
+ // Add a 'zero-width joiner'/ZWJ in order to ensure we have the same line height for
+ // all lines. This is a non-printing character so it will not change the horizontal
+ // spacing however it will affect the line height. As we ensure the ZWJ has the same
+ // text style as the title it will make sure the line height is consistent.
+ description.append('\u200D');
+
+ int middle = description.length();
+ description.append(episode);
+
+ description.setSpan(titleStyle, 0, middle, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ description.setSpan(
+ episodeStyle, middle, description.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else {
- if (entry.isGap()) {
- title = gapTitle;
- episode = null;
- } else if (entry.hasGenre(selectedGenreId)) {
- titleStyle = sProgramTitleStyle;
- episodeStyle = sEpisodeTitleStyle;
+ description.setSpan(
+ titleStyle, 0, description.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ setText(description);
+ }
+
+ private void updateIcons() {
+ // Sets recording icons if needed.
+ int iconResId = 0;
+ if (isEntryWideEnough() && mTableEntry.scheduledRecording != null) {
+ if (mDvrManager.isConflicting(mTableEntry.scheduledRecording)) {
+ iconResId = R.drawable.ic_warning_white_18dp;
+ } else {
+ switch (mTableEntry.scheduledRecording.getState()) {
+ case ScheduledRecording.STATE_RECORDING_NOT_STARTED:
+ iconResId = R.drawable.ic_scheduled_recording;
+ break;
+ case ScheduledRecording.STATE_RECORDING_IN_PROGRESS:
+ iconResId = R.drawable.ic_recording_program;
+ break;
+ default:
+ // leave the iconResId=0
+ }
}
- if (TextUtils.isEmpty(title)) {
- title = getResources().getString(R.string.program_title_for_no_information);
+ }
+ setCompoundDrawablePadding(iconResId != 0 ? sCompoundDrawablePadding : 0);
+ setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, iconResId, 0);
+ }
+
+ private void updateContentDescription(String title) {
+ // The content description includes extra information that is displayed on the detail view
+ Resources resources = getResources();
+ String description = title;
+ // TODO(b/73282818): only say channel name when the row changes
+ Channel channel = mChannelDataManager.getChannel(mTableEntry.channelId);
+ if (channel != null) {
+ description = channel.getDisplayNumber() + " " + description;
+ }
+ description +=
+ " "
+ + Utils.getDurationString(
+ getContext(),
+ mClock,
+ mTableEntry.entryStartUtcMillis,
+ mTableEntry.entryEndUtcMillis,
+ true);
+ Program program = mTableEntry.program;
+ if (program != null) {
+ String episodeDescription = program.getEpisodeContentDescription(getContext());
+ if (!TextUtils.isEmpty(episodeDescription)) {
+ description += " " + episodeDescription;
}
- SpannableStringBuilder description = new SpannableStringBuilder();
- description.append(title);
- if (!TextUtils.isEmpty(episode)) {
- description.append('\n');
-
- // Add a 'zero-width joiner'/ZWJ in order to ensure we have the same line height for
- // all lines. This is a non-printing character so it will not change the horizontal
- // spacing however it will affect the line height. As we ensure the ZWJ has the same
- // text style as the title it will make sure the line height is consistent.
- description.append('\u200D');
-
- int middle = description.length();
- description.append(episode);
-
- description.setSpan(titleStyle, 0, middle, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- description.setSpan(episodeStyle, middle, description.length(),
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ if (mTableEntry.scheduledRecording != null) {
+ if (mDvrManager.isConflicting(mTableEntry.scheduledRecording)) {
+ description +=
+ " " + resources.getString(R.string.dvr_epg_program_recording_conflict);
} else {
- description.setSpan(titleStyle, 0, description.length(),
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- setText(description);
-
- // Sets recording icons if needed.
- int iconResId = 0;
- if (mTableEntry.scheduledRecording != null) {
- if (mDvrManager.isConflicting(mTableEntry.scheduledRecording)) {
- iconResId = R.drawable.ic_warning_white_18dp;
- } else {
- switch (mTableEntry.scheduledRecording.getState()) {
- case ScheduledRecording.STATE_RECORDING_NOT_STARTED:
- iconResId = R.drawable.ic_scheduled_recording;
- break;
- case ScheduledRecording.STATE_RECORDING_IN_PROGRESS:
- iconResId = R.drawable.ic_recording_program;
- break;
- }
+ switch (mTableEntry.scheduledRecording.getState()) {
+ case ScheduledRecording.STATE_RECORDING_NOT_STARTED:
+ description +=
+ " "
+ + resources.getString(
+ R.string.dvr_epg_program_recording_scheduled);
+ break;
+ case ScheduledRecording.STATE_RECORDING_IN_PROGRESS:
+ description +=
+ " "
+ + resources.getString(
+ R.string.dvr_epg_program_recording_in_progress);
+ break;
+ default:
+ // do nothing
}
}
- setCompoundDrawablePadding(iconResId != 0 ? sCompoundDrawablePadding : 0);
- setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, iconResId, 0);
}
- measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
- mTextWidth = getMeasuredWidth() - getPaddingStart() - getPaddingEnd();
- // Maximum width for us to use a ripple
- mMaxWidthForRipple = GuideUtils.convertMillisToPixel(fromUtcMillis, toUtcMillis);
+ if (mTableEntry.isBlocked()) {
+ description += " " + resources.getString(R.string.program_guide_content_locked);
+ } else if (program != null) {
+ String programDescription = program.getDescription();
+ if (!TextUtils.isEmpty(programDescription)) {
+ description += " " + programDescription;
+ }
+ }
+ setContentDescription(description);
}
- /**
- * Update programItemView to handle alignments of text.
- */
+ /** Update programItemView to handle alignments of text. */
public void updateVisibleArea() {
View parentView = ((View) getParent());
if (parentView == null) {
@@ -341,7 +462,7 @@ public class ProgramItemView extends TextView {
}
if (getLayoutDirection() == LAYOUT_DIRECTION_LTR) {
layoutVisibleArea(parentView.getLeft() - getLeft(), getRight() - parentView.getRight());
- } else {
+ } else {
layoutVisibleArea(getRight() - parentView.getRight(), parentView.getLeft() - getLeft());
}
}
@@ -349,16 +470,14 @@ public class ProgramItemView extends TextView {
/**
* Layout title and episode according to visible area.
*
- * Here's the spec.
- * 1. Don't show text if it's shorter than 48dp.
- * 2. Try showing whole text in visible area by placing and wrapping text,
- * but do not wrap text less than 30min.
- * 3. Episode title is visible only if title isn't multi-line.
+ * <p>Here's the spec. 1. Don't show text if it's shorter than 48dp. 2. Try showing whole text
+ * in visible area by placing and wrapping text, but do not wrap text less than 30min. 3.
+ * Episode title is visible only if title isn't multi-line.
*
* @param startOffset Offset of the start position from the enclosing view's start position.
* @param endOffset Offset of the end position from the enclosing view's end position.
*/
- private void layoutVisibleArea(int startOffset, int endOffset) {
+ private void layoutVisibleArea(int startOffset, int endOffset) {
int width = mTableEntry.getWidth();
int startPadding = Math.max(0, startOffset);
int endPadding = Math.max(0, endOffset);
@@ -388,8 +507,8 @@ public class ProgramItemView extends TextView {
mTableEntry = null;
}
- private static int getProgress(long start, long end) {
- long currentTime = System.currentTimeMillis();
+ private static int getProgress(Clock clock, long start, long end) {
+ long currentTime = clock.currentTimeMillis();
if (currentTime <= start) {
return 0;
} else if (currentTime >= end) {
@@ -417,11 +536,15 @@ public class ProgramItemView extends TextView {
private static int getStateCount(StateListDrawable stateListDrawable) {
try {
- Object stateCount = StateListDrawable.class.getDeclaredMethod("getStateCount")
- .invoke(stateListDrawable);
+ Object stateCount =
+ StateListDrawable.class
+ .getDeclaredMethod("getStateCount")
+ .invoke(stateListDrawable);
return (int) stateCount;
- } catch (NoSuchMethodException|IllegalAccessException|IllegalArgumentException
- |InvocationTargetException e) {
+ } catch (NoSuchMethodException
+ | IllegalAccessException
+ | IllegalArgumentException
+ | InvocationTargetException e) {
Log.e(TAG, "Failed to call StateListDrawable.getStateCount()", e);
return 0;
}
@@ -429,12 +552,15 @@ public class ProgramItemView extends TextView {
private static Drawable getStateDrawable(StateListDrawable stateListDrawable, int index) {
try {
- Object drawable = StateListDrawable.class
- .getDeclaredMethod("getStateDrawable", Integer.TYPE)
- .invoke(stateListDrawable, index);
+ Object drawable =
+ StateListDrawable.class
+ .getDeclaredMethod("getStateDrawable", Integer.TYPE)
+ .invoke(stateListDrawable, index);
return (Drawable) drawable;
- } catch (NoSuchMethodException|IllegalAccessException|IllegalArgumentException
- |InvocationTargetException e) {
+ } catch (NoSuchMethodException
+ | IllegalAccessException
+ | IllegalArgumentException
+ | InvocationTargetException e) {
Log.e(TAG, "Failed to call StateListDrawable.getStateDrawable(" + index + ")", e);
return null;
}