aboutsummaryrefslogtreecommitdiff
path: root/src/com/android/tv/guide/ProgramTableAdapter.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/tv/guide/ProgramTableAdapter.java')
-rw-r--r--src/com/android/tv/guide/ProgramTableAdapter.java172
1 files changed, 88 insertions, 84 deletions
diff --git a/src/com/android/tv/guide/ProgramTableAdapter.java b/src/com/android/tv/guide/ProgramTableAdapter.java
index e4a67972..99f853b1 100644
--- a/src/com/android/tv/guide/ProgramTableAdapter.java
+++ b/src/com/android/tv/guide/ProgramTableAdapter.java
@@ -45,19 +45,21 @@ import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.tv.R;
import com.android.tv.TvApplication;
+import com.android.tv.common.TvCommonUtils;
import com.android.tv.common.feature.CommonFeatures;
import com.android.tv.data.Channel;
import com.android.tv.data.Program;
import com.android.tv.data.Program.CriticScore;
import com.android.tv.dvr.DvrDataManager;
import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.guide.ProgramManager.TableEntriesUpdatedListener;
import com.android.tv.parental.ParentalControlSettings;
import com.android.tv.ui.HardwareLayerAnimatorListenerAdapter;
@@ -73,7 +75,7 @@ import java.util.List;
/**
* Adapts the {@link ProgramListAdapter} list to the body of the program guide table.
*/
-public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapter.ProgramRowHolder>
+class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapter.ProgramRowViewHolder>
implements ProgramManager.TableEntryChangedListener {
private static final String TAG = "ProgramTableAdapter";
private static final boolean DEBUG = false;
@@ -112,8 +114,7 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
private final int mDvrPaddingStartWithTrack;
private final int mDvrPaddingStartWithOutTrack;
- public ProgramTableAdapter(Context context, ProgramManager programManager,
- ProgramGuide programGuide) {
+ ProgramTableAdapter(Context context, ProgramGuide programGuide) {
mContext = context;
mAccessibilityManager =
(AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
@@ -125,8 +126,8 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
mDvrManager = null;
mDvrDataManager = null;
}
- mProgramManager = programManager;
mProgramGuide = programGuide;
+ mProgramManager = programGuide.getProgramManager();
Resources res = context.getResources();
mChannelLogoWidth = res.getDimensionPixelSize(
@@ -193,7 +194,7 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
mProgramListAdapters.clear();
for (int i = 0; i < mProgramManager.getChannelCount(); i++) {
ProgramListAdapter listAdapter = new ProgramListAdapter(mContext.getResources(),
- mProgramManager, i);
+ mProgramGuide, i);
mProgramManager.addTableEntriesUpdatedListener(listAdapter);
mProgramListAdapters.add(listAdapter);
}
@@ -211,12 +212,12 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
}
@Override
- public void onBindViewHolder(ProgramRowHolder holder, int position) {
+ public void onBindViewHolder(ProgramRowViewHolder holder, int position) {
holder.onBind(position);
}
@Override
- public void onBindViewHolder(ProgramRowHolder holder, int position, List<Object> payloads) {
+ public void onBindViewHolder(ProgramRowViewHolder holder, int position, List<Object> payloads) {
if (!payloads.isEmpty()) {
holder.updateDetailView();
} else {
@@ -225,11 +226,11 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
}
@Override
- public ProgramRowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ public ProgramRowViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
ProgramRow programRow = (ProgramRow) itemView.findViewById(R.id.row);
programRow.setRecycledViewPool(mRecycledViewPool);
- return new ProgramRowHolder(itemView);
+ return new ProgramRowViewHolder(itemView);
}
@Override
@@ -241,18 +242,7 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
notifyItemChanged(channelIndex, true);
}
- @Override
- public void onViewAttachedToWindow(ProgramRowHolder holder) {
- holder.onAttachedToWindow();
- }
-
- @Override
- public void onViewDetachedFromWindow(ProgramRowHolder holder) {
- holder.onDetachedFromWindow();
- }
-
- // TODO: make it static
- public class ProgramRowHolder extends RecyclerView.ViewHolder
+ class ProgramRowViewHolder extends RecyclerView.ViewHolder
implements ProgramRow.ChildFocusListener {
private final ViewGroup mContainer;
@@ -269,6 +259,12 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
}
}
};
+ private final Runnable mUpdateDetailViewRunnable = new Runnable() {
+ @Override
+ public void run() {
+ updateDetailView();
+ }
+ };
private final RecyclerView.OnScrollListener mOnScrollListener =
new RecyclerView.OnScrollListener() {
@@ -282,8 +278,9 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
new ViewTreeObserver.OnGlobalFocusChangeListener() {
@Override
public void onGlobalFocusChanged(View oldFocus, View newFocus) {
- onChildFocus(isChild(oldFocus) ? oldFocus : null,
- isChild(newFocus) ? newFocus : null);
+ onChildFocus(
+ GuideUtils.isDescendant(mContainer, oldFocus) ? oldFocus : null,
+ GuideUtils.isDescendant(mContainer, newFocus) ? newFocus : null);
}
};
@@ -312,11 +309,38 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
private final ImageView mInputLogoView;
private boolean mIsInputLogoVisible;
+ private AccessibilityStateChangeListener mAccessibilityStateChangeListener =
+ new AccessibilityManager.AccessibilityStateChangeListener() {
+ @Override
+ public void onAccessibilityStateChanged(boolean enable) {
+ enable &= !TvCommonUtils.isRunningInTest();
+ mDetailView.setFocusable(enable);
+ mChannelHeaderView.setFocusable(enable);
+ }
+ };
- public ProgramRowHolder(View itemView) {
+ ProgramRowViewHolder(View itemView) {
super(itemView);
mContainer = (ViewGroup) itemView;
+ mContainer.addOnAttachStateChangeListener(
+ new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ mContainer.getViewTreeObserver()
+ .addOnGlobalFocusChangeListener(mGlobalFocusChangeListener);
+ mAccessibilityManager.addAccessibilityStateChangeListener(
+ mAccessibilityStateChangeListener);
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ mContainer.getViewTreeObserver()
+ .removeOnGlobalFocusChangeListener(mGlobalFocusChangeListener);
+ mAccessibilityManager.removeAccessibilityStateChangeListener(
+ mAccessibilityStateChangeListener);
+ }
+ });
mProgramRow = (ProgramRow) mContainer.findViewById(R.id.row);
mDetailView = (ViewGroup) mContainer.findViewById(R.id.detail);
@@ -339,23 +363,18 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
mChannelLogoView = (ImageView) mContainer.findViewById(R.id.channel_logo);
mChannelBlockView = (ImageView) mContainer.findViewById(R.id.channel_block);
mInputLogoView = (ImageView) mContainer.findViewById(R.id.input_logo);
- mDetailView.setFocusable(mAccessibilityManager.isEnabled());
- mChannelHeaderView.setFocusable(mAccessibilityManager.isEnabled());
- mAccessibilityManager.addAccessibilityStateChangeListener(
- new AccessibilityManager.AccessibilityStateChangeListener() {
- @Override
- public void onAccessibilityStateChanged(boolean enable) {
- mDetailView.setFocusable(enable);
- mChannelHeaderView.setFocusable(enable);
- }
- });
+
+ boolean accessibilityEnabled = mAccessibilityManager.isEnabled()
+ && !TvCommonUtils.isRunningInTest();
+ mDetailView.setFocusable(accessibilityEnabled);
+ mChannelHeaderView.setFocusable(accessibilityEnabled);
}
public void onBind(int position) {
onBindChannel(mProgramManager.getChannel(position));
mProgramRow.swapAdapter(mProgramListAdapters.get(position), true);
- mProgramRow.setProgramManager(mProgramManager);
+ mProgramRow.setProgramGuide(mProgramGuide);
mProgramRow.setChannel(mProgramManager.getChannel(position));
mProgramRow.setChildFocusListener(this);
mProgramRow.resetScroll(mProgramGuide.getTimelineRowScrollOffset());
@@ -416,24 +435,11 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
}
}
- public boolean isChild(View view) {
- if (view == null) {
- return false;
- }
- for (ViewParent p = view.getParent(); p != null; p = p.getParent()) {
- if (p == mContainer) {
- return true;
- }
- }
- return false;
- }
-
@Override
public void onChildFocus(View oldFocus, View newFocus) {
if (newFocus == null) {
return;
- }
- // When the accessibility service is enabled, focus might be put on channel's header or
+ } // When the accessibility service is enabled, focus might be put on channel's header or
// detail view, besides program items.
if (newFocus == mChannelHeaderView) {
mSelectedEntry = ((ProgramItemView) mProgramRow.getChildAt(0)).getTableEntry();
@@ -443,7 +449,15 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
mSelectedEntry = ((ProgramItemView) newFocus).getTableEntry();
}
if (oldFocus == null) {
- updateDetailView();
+ // Focus moved from other row.
+ if (mProgramGuide.getProgramGrid().isInLayout()) {
+ // We need to post runnable to avoid updating detail view when
+ // the recycler view is in layout, which may cause detail view not
+ // laid out according to the updated contents.
+ mHandler.post(mUpdateDetailViewRunnable);
+ } else {
+ updateDetailView();
+ }
return;
}
@@ -508,16 +522,6 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
});
}
- private void onAttachedToWindow() {
- mContainer.getViewTreeObserver()
- .addOnGlobalFocusChangeListener(mGlobalFocusChangeListener);
- }
-
- private void onDetachedFromWindow() {
- mContainer.getViewTreeObserver()
- .removeOnGlobalFocusChangeListener(mGlobalFocusChangeListener);
- }
-
private void updateDetailView() {
if (mSelectedEntry == null) {
// The view holder is never on focus before.
@@ -556,10 +560,8 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
program.getStartTimeUtcMillis(),
program.getEndTimeUtcMillis(), false));
- boolean trackMetaDataVisible = false;
- trackMetaDataVisible |=
- updateTextView(mAspectRatioView, Utils.getAspectRatioString(
- program.getVideoWidth(), program.getVideoHeight()));
+ boolean trackMetaDataVisible = updateTextView(mAspectRatioView, Utils
+ .getAspectRatioString(program.getVideoWidth(), program.getVideoHeight()));
int videoDefinitionLevel = Utils.getVideoDefinitionLevelFromSize(
program.getVideoWidth(), program.getVideoHeight());
@@ -658,7 +660,9 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
if (TextUtils.isEmpty(name)) {
return mContext.getString(R.string.program_guide_content_locked);
} else {
- return mContext.getString(R.string.program_guide_content_locked_format, name);
+ return TvContentRating.UNRATED.equals(blockedRating)
+ ? mContext.getString(R.string.program_guide_content_locked_unrated)
+ : mContext.getString(R.string.program_guide_content_locked_format, name);
}
}
@@ -666,7 +670,7 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
* Update tv input logo. It should be called when the visible child item in ProgramGrid
* changed.
*/
- public void updateInputLogo(int lastPosition, boolean forceShow) {
+ void updateInputLogo(int lastPosition, boolean forceShow) {
if (mChannel == null) {
mInputLogoView.setVisibility(View.GONE);
mIsInputLogoVisible = false;
@@ -731,7 +735,7 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
mInputLogoView.setVisibility(View.VISIBLE);
}
- private void updateCriticScoreView(ProgramRowHolder holder, final long programId,
+ private void updateCriticScoreView(ProgramRowViewHolder holder, final long programId,
CriticScore criticScore, View view) {
TextView criticScoreSource = (TextView) view.findViewById(R.id.critic_score_source);
TextView criticScoreText = (TextView) view.findViewById(R.id.critic_score_score);
@@ -759,11 +763,11 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
}
}
- private static ImageLoaderCallback<ProgramRowHolder> createCriticScoreLogoCallback(
- ProgramRowHolder holder, final long programId, ImageView logoView) {
- return new ImageLoaderCallback<ProgramRowHolder>(holder) {
+ private static ImageLoaderCallback<ProgramRowViewHolder> createCriticScoreLogoCallback(
+ ProgramRowViewHolder holder, final long programId, ImageView logoView) {
+ return new ImageLoaderCallback<ProgramRowViewHolder>(holder) {
@Override
- public void onBitmapLoaded(ProgramRowHolder holder, @Nullable Bitmap logoImage) {
+ public void onBitmapLoaded(ProgramRowViewHolder holder, @Nullable Bitmap logoImage) {
if (logoImage == null || holder.mSelectedEntry == null
|| holder.mSelectedEntry.program == null
|| holder.mSelectedEntry.program.getId() != programId) {
@@ -776,11 +780,11 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
};
}
- private static ImageLoaderCallback<ProgramRowHolder> createProgramPosterArtCallback(
- ProgramRowHolder holder, final Program program) {
- return new ImageLoaderCallback<ProgramRowHolder>(holder) {
+ private static ImageLoaderCallback<ProgramRowViewHolder> createProgramPosterArtCallback(
+ ProgramRowViewHolder holder, final Program program) {
+ return new ImageLoaderCallback<ProgramRowViewHolder>(holder) {
@Override
- public void onBitmapLoaded(ProgramRowHolder holder, @Nullable Bitmap posterArt) {
+ public void onBitmapLoaded(ProgramRowViewHolder holder, @Nullable Bitmap posterArt) {
if (posterArt == null || holder.mSelectedEntry == null
|| holder.mSelectedEntry.program == null) {
return;
@@ -794,11 +798,11 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
};
}
- private static ImageLoaderCallback<ProgramRowHolder> createChannelLogoLoadedCallback(
- ProgramRowHolder holder, final long channelId) {
- return new ImageLoaderCallback<ProgramRowHolder>(holder) {
+ private static ImageLoaderCallback<ProgramRowViewHolder> createChannelLogoLoadedCallback(
+ ProgramRowViewHolder holder, final long channelId) {
+ return new ImageLoaderCallback<ProgramRowViewHolder>(holder) {
@Override
- public void onBitmapLoaded(ProgramRowHolder holder, @Nullable Bitmap logo) {
+ public void onBitmapLoaded(ProgramRowViewHolder holder, @Nullable Bitmap logo) {
if (logo == null || holder.mChannel == null
|| holder.mChannel.getId() != channelId) {
return;
@@ -808,11 +812,11 @@ public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapte
};
}
- private static ImageLoaderCallback<ProgramRowHolder> createTvInputLogoLoadedCallback(
- final TvInputInfo info, ProgramRowHolder holder) {
- return new ImageLoaderCallback<ProgramRowHolder>(holder) {
+ private static ImageLoaderCallback<ProgramRowViewHolder> createTvInputLogoLoadedCallback(
+ final TvInputInfo info, ProgramRowViewHolder holder) {
+ return new ImageLoaderCallback<ProgramRowViewHolder>(holder) {
@Override
- public void onBitmapLoaded(ProgramRowHolder holder, @Nullable Bitmap logo) {
+ public void onBitmapLoaded(ProgramRowViewHolder holder, @Nullable Bitmap logo) {
if (logo != null && holder.mChannel != null && info.getId()
.equals(holder.mChannel.getInputId())) {
holder.updateInputLogoInternal(logo);