最近需要改进PEG View的响应速度,因为我们目前的框架是采用动态创建TextView的方法,导致上下左右切换时响应没有那么快,老板很不高兴,作为员工那必须得改进啊。经过一段时间的查找,终于有了如下的EPG View,速度极快。
1、自定义EPG View,代码如下:
package com.amlogic.dvb_custom_view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;
import com.amlogic.DVBPlayer.AndroidNineMainMenu;
import com.amlogic.DVBPlayer.R;
import com.amlogic.aidl.ServiceInfoEntity;
import com.amlogic.dvb_interface.EPGData;
import com.amlogic.dvb_util.EPGUtil;
import com.nes.gracenote.bean.EnhancedScheduleGridBean;
import org.joda.time.DateTime;
import org.joda.time.LocalDateTime;
import java.util.Calendar;
import java.util.List;
public class EpgView extends ViewGroup {
public static int DAYS_BACK_MILLIS;
public static final int DAYS_FORWARD_MILLIS = 5 * 24 * 60 * 60 * 1000;
private static int HOURS_IN_VIEWPORT_MILLIS = 2 * 60 * 60 * 1000;
private static final int TIME_LABEL_SPACING_MILLIS = 30 * 60 * 1000;
public static final int UP_DIRECTION = 0;
public static final int DOWN_DIRECTION = 1;
private Context contextObj;
private boolean mEventNeedSelectedStatus = false;
private final Rect mClipRect;
private final Rect mDrawingRect;
private final Rect mMeasuringRect;
private final Paint mPaint;
private final Scroller mScroller;
private int mChannelLayoutPadding;
private int mChannelLayoutHeight;
private int mChannelLayoutWidth;
private final int mChannelLayoutMargin;
private final int mChannelLayoutBackground;
private final int mRedColor;
private final int mColorPrimaryDark;
private final int mTimerBarBackground;
private final int mEventLayoutSelected;
private final int mEventLayoutBackground;
private final int mEventLayoutBackgroundCurrent;
private final int mEventLayoutTextColor;
public int mEventLayoutTextSize;
private final int mTimeBarLineWidth;
private final int mTimeBarLineColor;
private int mTimeBarHeight;
private int mTimeBarTextSize;
private final int mEPGBackground;
//private final Map<String, Bitmap> mChannelImageCache;
//private final Map<String, Target> mChannelImageTargetCache;
private int mMaxHorizontalScroll;
private int mMaxVerticalScroll;
//event显示区域(2个小时)里,每一个像素占的毫秒数
private long mMillisPerPixel;
//时刻表上最左边的那个时间,单位毫秒
private long mTimeOffset;
private long mTimeLowerBoundary;
private long mTimeUpperBoundary;
public EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean currentProgram = null;
private boolean drawCurrentTimeLine = false;
public int currentChannelPosition = -1;
private int cuDays = 0;
private boolean isMoveRight;
private boolean isMoveLeft;
private EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean referenceEvent;
private int referenceEventPosition;
private EPGData epgData = null;
private List<ServiceInfoEntity> serviceList;
public EpgView(Context context) {
this(context, null);
}
public EpgView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public EpgView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
DAYS_BACK_MILLIS = 0;
contextObj = context;
if (cuDays > 0) {
DAYS_BACK_MILLIS = cuDays * 24 * 60 * 60 * 1000;
} else {
DAYS_BACK_MILLIS = 0;
}
setWillNotDraw(false);
//resetBoundaries();
mDrawingRect = new Rect();
mClipRect = new Rect();
mMeasuringRect = new Rect();
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
//mChannelImageCache = Maps.newHashMap();
//mChannelImageTargetCache = Maps.newHashMap();
// Adding some friction that makes the epg less flappy.
mScroller = new Scroller(context);
mScroller.setFriction(ViewConfiguration.getScrollFriction());
mEPGBackground = getResources().getColor(R.color.epg_background);
mChannelLayoutMargin = getResources().getDimensionPixelSize(R.dimen.epg_channel_layout_margin_8);
mChannelLayoutPadding = getResources().getDimensionPixelSize(R.dimen.epg_channel_layout_padding_8);
mChannelLayoutHeight = getResources().getDimensionPixelSize(R.dimen.epg_channel_layout_height_8);
mChannelLayoutWidth = getResources().getDimensionPixelSize(R.dimen.epg_channel_layout_width);
mChannelLayoutBackground = getResources().getColor(R.color.epg_channel_layout_background);
mEventLayoutBackground = getResources().getColor(R.color.translucent_black);
mEventLayoutBackgroundCurrent = getResources().getColor(R.color.epg_background_black);
mEventLayoutTextColor = getResources().getColor(R.color.epg_event_layout_text);
mEventLayoutSelected = getResources().getColor(R.color.epg_date_title_color);
mEventLayoutTextSize = getResources().getDimensionPixelSize(R.dimen.epg_event_layout_text_8);
mTimeBarHeight = getResources().getDimensionPixelSize(R.dimen.epg_time_bar_height_8);
mTimeBarTextSize = getResources().getDimensionPixelSize(R.dimen.epg_time_bar_text_8);
mTimeBarLineWidth = getResources().getDimensionPixelSize(R.dimen.epg_time_bar_line_width_8);
mTimeBarLineColor = getResources().getColor(R.color.mainmenu_epg_time_bar);
mRedColor = getResources().getColor(R.color.colorAccent);
mColorPrimaryDark = getResources().getColor(R.color.colorPrimaryDark);
mTimerBarBackground = getResources().getColor(R.color.color_epg_focus);
}
/*<dimen name="epg_channel_layout_margin_8">1dp</dimen> <!--EPG 每一行的间隔距离-->
<dimen name="epg_channel_layout_padding_8">5dp</dimen> <!-- epg event里的文字和边框的间隔-->
<dimen name="epg_channel_layout_height_8">50dp</dimen>
<dimen name="epg_channel_layout_width_8">165dp</dimen>
<dimen name="epg_channel_layout_width">0dp</dimen>
<dimen name="epg_event_layout_text_8">15dp</dimen> <!-- epg event里的文字大小-->
<dimen name="epg_time_bar_height_8">30dp</dimen>
<dimen name="epg_time_bar_height">40dp</dimen>
<dimen name="epg_time_bar_text_8">15dp</dimen>
<dimen name="epg_time_bar_line_width_8">1dp</dimen> <!-- epg 时间竖线粗-->*/
/*<!--整个epg 区域的背景色-->
<color name="epg_background">#ff4A4A4A</color>
<color name="epg_background_white">#ffffffff</color>
<!--epg event背景颜色-->
<color name="epg_background_black">#ff000000</color>
<color name="epg_event_layout_selected">#4772a4</color>
<color name="epg_channel_layout_background">#ff323232</color>
<color name="epg_event_layout_text">#ffd6d6d6</color>
<color name="epg_logo_background">#ff9a9a9a</color>
<color name="mainmenu_epg_time_bar">#ffc57120</color>
<color name="translucent_black">#E6000000</color>
<color name="epg_line_data_background">#D91c1c1c</color> */
public void setEPGData(Context context, EPGData epgData) {
this.epgData = epgData;
serviceList = epgData.getChannels();
contextObj = context;
Log.d("wujiang", "EpgView: setEPGData->serviceList size = " + serviceList.size());
if (serviceList.size() == 0) {
return;
}
currentChannelPosition = getFirstVisibleChannelPosition();
//Log.d("wujiang", "EpgView: currentChannelPosition = " + currentChannelPosition);
int programPosition = getProgramPosition(currentChannelPosition, Calendar.getInstance().getTimeInMillis());
currentProgram = epgData.getEvent(currentChannelPosition, programPosition);
//Log.d("wujiang", "setEPGData: Calendar.getInstance().getTimeInMillis() = " + Calendar.getInstance().getTimeInMillis());
Log.d("wujiang", "setEPGData: programPosition = " + programPosition);
Log.d("wujiang", "setEPGData: channel name = " + serviceList.get(currentChannelPosition).getName());
if (currentProgram == null) {
Log.d("wujiang", "setEPGData: currentProgram == null");
}
//暂时不设置被选中的event
//if (currentProgram != null) {
// currentProgram.setSelected(true);
//}
referenceEventPosition = programPosition;
//Log.e(TAG, " * * * EPG setEPGData() (referenceEventPosition) " + referenceEventPosition);
referenceEvent = currentProgram;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
@Override
protected void onDraw(Canvas canvas) {
//super.onDraw(canvas);
if (epgData != null && epgData.hasData()) {
mTimeLowerBoundary = getTimeFrom(getScrollX());
mTimeUpperBoundary = getTimeFrom(getScrollX() + getWidth());
//Log.e("M_TIME_UPPER", new Date(mTimeUpperBoundary).toString());
Rect drawingRect = mDrawingRect;
drawingRect.left = getScrollX();
drawingRect.top = getScrollY();
drawingRect.right = drawingRect.left + getWidth();
drawingRect.bottom = drawingRect.top + getHeight();
//drawChannelListItems(canvas, drawingRect);
drawEvents(canvas, drawingRect);
drawTimebar(canvas, drawingRect);
drawTimeLine(canvas, drawingRect);
//drawResetButton(canvas, drawingRect);
// If scroller is scrolling/animating do scroll. This applies when doing a fling.
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
}
} else {
mTimeLowerBoundary = getTimeFrom(getScrollX());
mTimeUpperBoundary = getTimeFrom(getScrollX() + getWidth());
Rect drawingRect = mDrawingRect;
drawingRect.left = getScrollX();
drawingRect.top = getScrollY();
drawingRect.right = drawingRect.left + getWidth();
drawingRect.bottom = drawingRect.top + getHeight();
drawBlankEvents(canvas, drawingRect);
drawTimebar(canvas, drawingRect);
}
}
/**
* This will recalculate boundaries, maximal scroll and scroll to start position which is current time.
* To be used on device rotation etc since the device height and width will change.
*
* @param withAnimation true if scroll to current position should be animated.
*/
public void recalculateAndRedraw(boolean withAnimation, boolean needDrawSelectedProgram) {
if (epgData != null && epgData.hasData()) {
Log.d("wujiang", "recalculateAndRedraw: needDrawSelectedProgram = " + needDrawSelectedProgram);
mEventNeedSelectedStatus = needDrawSelectedProgram;
resetBoundaries();
calculateMaxVerticalScroll();
calculateMaxHorizontalScroll();
mScroller.startScroll(getScrollX(), getScrollY(), getXPositionStart() - getScrollX(), 0, withAnimation ? 0 : 0);
if (currentProgram == null) {
Log.d("wujiang", "recalculateAndRedraw: 11111111111");
if (needDrawSelectedProgram == false) {
referenceEvent = gotoProgramNotSelect(currentChannelPosition, Calendar.getInstance().getTimeInMillis());
} else {
referenceEvent = gotoProgram(currentChannelPosition, Calendar.getInstance().getTimeInMillis());
}
} else {
Log.d("wujiang", "recalculateAndRedraw: 2222222222");
if ((currentProgram.getIntStartTime() > EPGUtil.getCurrentTimeInMillis()) || (currentProgram.getIntStartTime() < EPGUtil.getCurrentTimeInMillis())) {
int progPos = getProgramPosition(currentChannelPosition, EPGUtil.getCurrentTimeInMillis());
Log.d("wujiang", "recalculateAndRedraw: progPos = " + progPos);
EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean event = epgData.getEvent(currentChannelPosition, progPos);
if (needDrawSelectedProgram == false) {
referenceEvent = gotoProgramNotSelect(currentChannelPosition, event.getIntStartTime());
} else {
referenceEvent = gotoProgram(currentChannelPosition, event.getIntStartTime());
}
}
}
redraw();
} else {
Log.d("wujiang", "recalculateAndRedraw: epgData == null || !epgData.hasData()");
resetBoundaries();
redraw();
}
}
public void redraw() {
Log.d("wujiang", "redraw: call this fun");
invalidate();
requestLayout();
}
private EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean gotoProgram(int channelPosition, long time) {
Log.d("wujiang", "gotoProgram: call this fun, channelPosition = " + channelPosition);
if (channelPosition > -1 && channelPosition < epgData.getChannelCount()) {
int programPosition = getProgramPosition(channelPosition, time);
//Log.d("wujiang", "gotoProgram: programPosition = " + programPosition);
if (programPosition != -1) {
//Log.d("wujiang", "gotoProgram: 111111111111");
epgData.cleanSelection();
EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean event = epgData.getEvent(channelPosition, programPosition);
event.setSelected(true);
currentProgram = event;
/*if (epgActivity != null) {
//epgActivity.loadEventPosterFromServer(currentProgram);
update(currentProgram);
} else {
Log.e(TAG, "NULLLLLLLLLLLLLLLLLLL");
}*/
currentChannelPosition = channelPosition;
if (isMoveLeft || isMoveRight) {
referenceEvent = event;
} else {
referenceEventPosition = programPosition;
}
((AndroidNineMainMenu)contextObj).showEpgDetailInfo(currentProgram);
return event;
} else {
//Log.d("wujiang", "gotoProgram: 222222222222");
//没有EPG信息
EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean event = new EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean();
epgData.cleanSelection();
event.setTitle("No Information");
event.setIntStartTime(mTimeLowerBoundary);
event.setIntStopTime(mTimeUpperBoundary);
//Log.d("wujiang", "gotoProgram: mTimeLowerBoundary = " + mTimeLowerBoundary);
//Log.d("wujiang", "gotoProgram: mTimeUpperBoundary = " + mTimeUpperBoundary);
event.setSelected(true);
currentProgram = event;
currentChannelPosition = channelPosition;
if (isMoveLeft || isMoveRight) {
referenceEvent = event;
} else {
referenceEventPosition = programPosition;
}
((AndroidNineMainMenu)contextObj).showEpgDetailInfo(currentProgram);
return event;
}
}
return null;
}
private EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean gotoProgramNotSelect(int channelPosition, long time) {
Log.d("wujiang", "gotoProgramNotSelect: call this fun, channelPosition = " + channelPosition);
if (channelPosition > -1 && channelPosition < epgData.getChannelCount()) {
int programPosition = getProgramPosition(channelPosition, time);
Log.d("wujiang", "gotoProgramNotSelect: programPosition = " + programPosition);
if (programPosition != -1) {
epgData.cleanSelection();
EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean event = epgData.getEvent(channelPosition, programPosition);
//event.setSelected(true);
currentProgram = event;
/*if (epgActivity != null) {
//epgActivity.loadEventPosterFromServer(currentProgram);
update(currentProgram);
} else {
Log.e(TAG, "NULLLLLLLLLLLLLLLLLLL");
}*/
currentChannelPosition = channelPosition;
if (isMoveLeft || isMoveRight) {
referenceEvent = event;
} else {
referenceEventPosition = programPosition;
}
return event;
}
}
return null;
}
private int getProgramPosition(int channelPosition, long time) {
List<EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean> events = epgData.getEvents(channelPosition);
Log.d("wujiang", "getProgramPosition: events size = " + events.size());
//Log.d("wujiang", "getProgramPosition: time = " + time);
if (events != null) {
for (int eventPos = 0; eventPos < events.size(); eventPos++) {
EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean event = events.get(eventPos);
//Log.d("wujiang", "getProgramPosition: event getIntStartTime = " + event.getIntStartTime());
//Log.d("wujiang", "getProgramPosition: event getIntStopTime = " + event.getIntStopTime());
if ((event.getIntStartTime()) <= time && ((event.getIntStopTime()) > time)) {
return eventPos;
}
}
}
return -1;
}
private void calculateMaxVerticalScroll() {
final int maxVerticalScroll = getTopFrom(epgData.getChannelCount() - 2) + mChannelLayoutHeight;
mMaxVerticalScroll = maxVerticalScroll < getHeight() ? 0 : maxVerticalScroll - getHeight();
}
private void calculateMaxHorizontalScroll() {
long currentFWDMillis = ((LocalDateTime.now().toDateTime().getMillis() + HOURS_IN_VIEWPORT_MILLIS));
mMaxHorizontalScroll = (int) (mChannelLayoutMargin + mChannelLayoutWidth + (DAYS_BACK_MILLIS + EPGUtil.roundOfTimeToLowerBound(LocalDateTime.now().toDateTime().getMillis()) + HOURS_IN_VIEWPORT_MILLIS + ((LocalDateTime.now().toDateTime().withTime(23, 59, 59, 999).getMillis())) + DAYS_FORWARD_MILLIS) / mMillisPerPixel);
}
private void drawTimeLine(Canvas canvas, Rect drawingRect) {
//long now = System.currentTimeMillis();
long now = EPGUtil.getCurrentTimeInMillis();
if (shouldDrawTimeLine(now)) {
drawingRect.left = getXFrom(now);
drawingRect.top = getScrollY();
drawingRect.right = drawingRect.left + mTimeBarLineWidth;
drawingRect.bottom = drawingRect.top + mTimeBarHeight;
mPaint.setColor(mTimeBarLineColor);
canvas.drawRect(drawingRect, mPaint);
}
}
private boolean shouldDrawTimeLine(long now) {
return now >= mTimeLowerBoundary && now < mTimeUpperBoundary;
}
private void drawTimebar(Canvas canvas, Rect drawingRect) {
//drawingRect.left = getScrollX() + mChannelLayoutWidth + mChannelLayoutMargin;
drawingRect.left = getScrollX() + mChannelLayoutWidth;
drawingRect.top = getScrollY();
drawingRect.right = drawingRect.left + getWidth();
drawingRect.bottom = drawingRect.top + mTimeBarHeight;
//Log.d("wujiang", "drawTimebar: getScrollX = " + getScrollX());
//Log.d("wujiang", "drawTimebar: drawingRect.left = " + drawingRect.left);
//mClipRect.left = getScrollX() + mChannelLayoutWidth + mChannelLayoutMargin;
mClipRect.left = getScrollX() + mChannelLayoutWidth;
mClipRect.top = getScrollY();
mClipRect.right = drawingRect.left + getWidth();//getScrollX() + getWidth();
mClipRect.bottom = mClipRect.top + mTimeBarHeight;
//Log.d("wujiang", "drawTimebar: mClipRect.left = " + mClipRect.left);
canvas.save();
canvas.clipRect(mClipRect);
// Background
mPaint.setColor(mTimerBarBackground);
canvas.drawRect(drawingRect, mPaint);
// Time stamps
mPaint.setColor(mEventLayoutTextColor);
mPaint.setTextSize(mTimeBarTextSize);
for (int i = 0; i < HOURS_IN_VIEWPORT_MILLIS / TIME_LABEL_SPACING_MILLIS; i++) {
// Get time and round to nearest half hour
final long time = TIME_LABEL_SPACING_MILLIS *
(((mTimeLowerBoundary + (TIME_LABEL_SPACING_MILLIS * i)) +
(TIME_LABEL_SPACING_MILLIS / 2)) / TIME_LABEL_SPACING_MILLIS);
mPaint.setColor(mEventLayoutTextColor);
canvas.drawText(EPGUtil.getShortTime(time), getXFrom(time),
drawingRect.top + (((drawingRect.bottom - drawingRect.top) / 2) + (mTimeBarTextSize / 2)), mPaint);
// mPaint.setColor(mEPGBackground);
// canvas.drawLine(getXFrom(time), drawingRect.top, getXFrom(time), drawingRect.bottom, mPaint);
}
canvas.restore();
//drawTimebarDayIndicator(canvas, drawingRect);
drawTime();
drawTimebarBottomStroke(canvas, drawingRect);
}
private void drawTime() {
((AndroidNineMainMenu) contextObj).setEpgDateTextViewString(EPGUtil.getWeekdayName(mTimeLowerBoundary));
}
private void drawTimebarDayIndicator(Canvas canvas, Rect drawingRect) {
drawingRect.left = getScrollX();
drawingRect.top = getScrollY();
drawingRect.right = drawingRect.left + mChannelLayoutWidth;
drawingRect.bottom = drawingRect.top + mTimeBarHeight;
// Background
mPaint.setColor(mChannelLayoutBackground);
canvas.drawRect(drawingRect, mPaint);
// Text
mPaint.setColor(mEventLayoutTextColor);
mPaint.setTextSize(mTimeBarTextSize);
mPaint.setTextAlign(Paint.Align.CENTER);
if (EPGUtil.getWeekdayName(mTimeLowerBoundary).equals("Today")) {
canvas.drawText(EPGUtil.getWeekdayName(mTimeLowerBoundary),
drawingRect.left + ((drawingRect.right - drawingRect.left) / 2),
drawingRect.top + (((drawingRect.bottom - drawingRect.top) / 2) + (mTimeBarTextSize / 2)), mPaint);
} else {
// java.lang.ArrayIndexOutOfBoundsException: length=1; index=1 canvas.drawText(tmpStr[1],
String tmpStr[] = EPGUtil.getWeekdayName(mTimeLowerBoundary).split("\n");
canvas.drawText(tmpStr[0],
drawingRect.left + ((drawingRect.right - drawingRect.left) / 2),
drawingRect.top + (((drawingRect.bottom - drawingRect.top) / 4)) + (mTimeBarTextSize / 2), mPaint);
canvas.drawText(tmpStr[1],
drawingRect.left + ((drawingRect.right - drawingRect.left) / 2),
drawingRect.top + (((drawingRect.bottom - drawingRect.top) / 2) + (mTimeBarTextSize)), mPaint);
tmpStr = null;
}
mPaint.setTextAlign(Paint.Align.LEFT);
}
private void drawTimebarBottomStroke(Canvas canvas, Rect drawingRect) {
drawingRect.left = getScrollX();
drawingRect.top = getScrollY() + mTimeBarHeight;
drawingRect.right = drawingRect.left + getWidth();
drawingRect.bottom = drawingRect.top + mChannelLayoutMargin;
// Bottom stroke
mPaint.setColor(mEPGBackground);
canvas.drawRect(drawingRect, mPaint);
}
private void drawChannelListItems(Canvas canvas, Rect drawingRect) {
//Log.d("wujiang", "drawChannelListItems: call this fun");
mMeasuringRect.left = getScrollX();
mMeasuringRect.top = getScrollY();
mMeasuringRect.right = drawingRect.left + mChannelLayoutWidth;
mMeasuringRect.bottom = mMeasuringRect.top + getHeight();
final int firstPos = getFirstVisibleChannelPosition();
final int lastPos = getLastVisibleChannelPosition();
for (int pos = firstPos; pos <= lastPos; pos++) {
drawChannelItem(canvas, pos, drawingRect);
}
}
private void drawEvents(Canvas canvas, Rect drawingRect) {
//Log.d("wujiang", "drawEvents: call this fun");
final int firstPos = getFirstVisibleChannelPosition();
final int lastPos = getLastVisibleChannelPosition();
for (int pos = firstPos; pos <= lastPos; pos++) {
// Set clip rectangle
mClipRect.left = getScrollX() + mChannelLayoutWidth + mChannelLayoutMargin;
mClipRect.top = getTopFrom(pos);
mClipRect.right = getScrollX() + getWidth();
mClipRect.bottom = mClipRect.top + mChannelLayoutHeight;
canvas.save();
canvas.clipRect(mClipRect);
// Draw each event
boolean foundFirst = false;
List<EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean> epgEvents = epgData.getEvents(pos);
//Log.d("wujiang", "drawEvents: epgEvents size = " + epgEvents.size());
if (epgEvents.size() <= 0) {
//该频道没有EPG信息
//Log.d("wujiang", "drawEvents: 11111111");
drawNoInforEvent(canvas, pos, drawingRect);
} else {
//Log.d("wujiang", "drawEvents: 222222222");
for (EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean event : epgEvents) {
if (isEventVisible(event.getIntStartTime(), event.getIntStopTime())) {
//Log.d("wujiang", "drawEvents: 3333333");
drawEvent(canvas, pos, event, drawingRect);
foundFirst = true;
} else if (foundFirst) {
break;
}
}
if (foundFirst == false) {
//Log.d("wujiang", "drawEvents: 44444444");
drawNoInforEvent(canvas, pos, drawingRect);
}
}
canvas.restore();
}
}
private void drawBlankEvents(Canvas canvas, Rect drawingRect) {
final int firstPos = getFirstVisibleChannelPosition();
final int lastPos = getLastBlankLineChannelPosition();
for (int pos = firstPos; pos <= lastPos; pos++) {
mClipRect.left = getScrollX() + mChannelLayoutWidth + mChannelLayoutMargin;
mClipRect.top = getTopFrom(pos);
mClipRect.right = getScrollX() + getWidth();
mClipRect.bottom = mClipRect.top + mChannelLayoutHeight;
canvas.save();
canvas.clipRect(mClipRect);
mPaint.setColor(mEventLayoutBackground);
canvas.drawRect(mClipRect, mPaint);
canvas.restore();
}
}
private void drawNoInforEvent(final Canvas canvas, final int channelPosition, final Rect drawingRect) {
//Log.d("wujiang", "drawNoInforEvent: call this function");
String title = "No Information";
setEventDrawingRectangle(channelPosition, mTimeLowerBoundary, mTimeUpperBoundary, drawingRect, title);
// Background
mPaint.setColor(drawCurrentTimeLine ? mEventLayoutBackgroundCurrent : mEventLayoutBackground);
if (currentChannelPosition == channelPosition && mEventNeedSelectedStatus == true) {
mPaint.setColor(mEventLayoutSelected);
}
canvas.drawRect(drawingRect, mPaint);
// Add left and right inner padding
drawingRect.left += mChannelLayoutPadding;
drawingRect.right -= mChannelLayoutPadding;
// Text
mPaint.setColor(mEventLayoutTextColor);
mPaint.setTextSize(mEventLayoutTextSize);
// Move drawing.top so text will be centered (text is drawn bottom>up)
mPaint.getTextBounds(title, 0, title.length(), mMeasuringRect);
drawingRect.top += (((drawingRect.bottom - drawingRect.top) / 2) + (mMeasuringRect.height() / 2));
// Text
if (currentChannelPosition == channelPosition && mEventNeedSelectedStatus == true) {
mPaint.setColor(Color.YELLOW);
mPaint.setTextSize(mEventLayoutTextSize);
} else {
mPaint.setColor(mEventLayoutTextColor);
mPaint.setTextSize(mEventLayoutTextSize);
}
//NEW CHANGES USING SHOW_TYPE of EVENT
title = title.substring(0, mPaint.breakText(title, true, drawingRect.right - drawingRect.left, null));
TextPaint textPaint = new TextPaint(Paint.LINEAR_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(mPaint.getColor());
textPaint.setTextSize(mPaint.getTextSize());
textPaint.setStyle(mPaint.getStyle());
CharSequence txt = null;
txt = TextUtils.ellipsize(title, textPaint, (drawingRect.right - drawingRect.left) - 10, TextUtils.TruncateAt.END);
canvas.drawText(txt, 0, txt.length(), drawingRect.left, drawingRect.top, textPaint);
}
private void drawEvent(final Canvas canvas, final int channelPosition, final EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean event, final Rect drawingRect) {
setEventDrawingRectangle(channelPosition, event.getIntStartTime(), event.getIntStopTime(), drawingRect, event.getTitle());
// Background
mPaint.setColor(event.isCurrent() && drawCurrentTimeLine ? mEventLayoutBackgroundCurrent : mEventLayoutBackground);
if (event.isSelected()) {
mPaint.setColor(mEventLayoutSelected);
}
canvas.drawRect(drawingRect, mPaint);
// Add left and right inner padding
drawingRect.left += mChannelLayoutPadding;
drawingRect.right -= mChannelLayoutPadding;
// Text
mPaint.setColor(mEventLayoutTextColor);
mPaint.setTextSize(mEventLayoutTextSize);
//Log.e("TAG", " @ @ @ @ " + event.getGenres());
// Set Genre
Rect genreBackgroundRect = null;
ServiceInfoEntity serviceInfoEntity = serviceList.get(getServiceIndexInList((int) event.getChannelNumber()));
if (genreBackgroundRect == null) {
genreBackgroundRect = new Rect();
genreBackgroundRect.set(drawingRect.left, drawingRect.top + mTimeBarHeight + 10, (int) (drawingRect.left), drawingRect.bottom - 5);
}
// Move drawing.top so text will be centered (text is drawn bottom>up)
mPaint.getTextBounds(event.getTitle(), 0, event.getTitle().length(), mMeasuringRect);
drawingRect.top += (((drawingRect.bottom - drawingRect.top) / 2) + (mMeasuringRect.height() / 2));
// Text
if (event.isSelected()) {
mPaint.setColor(Color.YELLOW);
mPaint.setTextSize(mEventLayoutTextSize);
} else {
mPaint.setColor(mEventLayoutTextColor);
mPaint.setTextSize(mEventLayoutTextSize);
}
//NEW CHANGES USING SHOW_TYPE of EVENT
String title = null;
title = event.getTitle();
title = title.substring(0, mPaint.breakText(title, true, drawingRect.right - drawingRect.left, null));
TextPaint textPaint = new TextPaint(Paint.LINEAR_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(mPaint.getColor());
textPaint.setTextSize(mPaint.getTextSize());
textPaint.setStyle(mPaint.getStyle());
CharSequence txt = null;
if (event.getIntStartTime() < mTimeLowerBoundary) {
//canvas.drawText(title, getXFrom(mTimeLowerBoundary) + 10, drawingRect.top - 5, mPaint);
txt = TextUtils.ellipsize(title, textPaint, (drawingRect.right - getXFrom(mTimeLowerBoundary)) - 10, TextUtils.TruncateAt.END);
canvas.drawText(txt, 0, txt.length(), getXFrom(mTimeLowerBoundary) + 10, drawingRect.top, textPaint);
} else {
//canvas.drawText(title, drawingRect.left, drawingRect.top - 5, mPaint);
txt = TextUtils.ellipsize(title, textPaint, (drawingRect.right - drawingRect.left) - 10, TextUtils.TruncateAt.END);
canvas.drawText(txt, 0, txt.length(), drawingRect.left, drawingRect.top, textPaint);
}
}
private void setEventDrawingRectangle(final int channelPosition, final long start, final long end, final Rect drawingRect, String eventName) {
if (start < mTimeOffset) {
drawingRect.left = getXFrom(mTimeOffset);
} else {
drawingRect.left = getXFrom(start);
}
drawingRect.top = getTopFrom(channelPosition);
drawingRect.right = getXFrom(end) - mChannelLayoutMargin;
drawingRect.bottom = drawingRect.top + mChannelLayoutHeight;
}
private int getFirstVisibleChannelPosition() {
final int y = getScrollY();
int position = (y - mChannelLayoutMargin - mTimeBarHeight) / (mChannelLayoutHeight + mChannelLayoutMargin);
if (position < 0) {
position = 0;
}
return position;
}
private int getLastVisibleChannelPosition() {
final int y = getScrollY();
final int totalChannelCount = epgData.getChannelCount();
final int screenHeight = getHeight();
int position = (y + screenHeight + mTimeBarHeight - mChannelLayoutMargin) / (mChannelLayoutHeight + mChannelLayoutMargin);
if (position > totalChannelCount - 1) {
position = totalChannelCount - 1;
}
// Add one extra row if we don't fill screen with current..
return (y + screenHeight) > (position * mChannelLayoutHeight) && position < totalChannelCount - 1 ? position + 1 : position;
}
private int getLastBlankLineChannelPosition() {
final int y = getScrollY();
final int totalChannelCount = 6;
final int screenHeight = getHeight();
int position = (y + screenHeight + mTimeBarHeight - mChannelLayoutMargin) / (mChannelLayoutHeight + mChannelLayoutMargin);
if (position > totalChannelCount - 1) {
position = totalChannelCount - 1;
}
// Add one extra row if we don't fill screen with current..
return (y + screenHeight) > (position * mChannelLayoutHeight) && position < totalChannelCount - 1 ? position + 1 : position;
}
private boolean isEventVisible(final long start, final long end) {
return (start >= mTimeLowerBoundary && start <= mTimeUpperBoundary)
|| (end >= mTimeLowerBoundary && end <= mTimeUpperBoundary)
|| (start <= mTimeLowerBoundary && end >= mTimeUpperBoundary);
}
private void drawChannelItem(final Canvas canvas, int position, Rect drawingRect) {
Rect drawingRect1 = new Rect();
drawingRect.left = getScrollX();
drawingRect.top = getTopFrom(position);
drawingRect.right = drawingRect.left + mChannelLayoutWidth / 2;
drawingRect.bottom = drawingRect.top + mChannelLayoutHeight;
//mPaint.setColor(mChannelLayoutBackground);
mPaint.setColor(mRedColor);
canvas.drawRect(drawingRect, mPaint);
mPaint.setTextAlign(Paint.Align.CENTER);
//Channel-no
//mPaint.setColor(mEventLayoutTextColor);
mPaint.setColor(mColorPrimaryDark);
mPaint.setTextSize(mEventLayoutTextSize - 2);
canvas.drawText(Long.toString(epgData.getChannel(position).getChannelNumber()), drawingRect.centerX(), drawingRect.centerY() + 10, mPaint);
drawingRect1.left = getScrollX() + mChannelLayoutWidth / 2;
drawingRect1.top = getTopFrom(position);
drawingRect1.right = drawingRect1.left + mChannelLayoutWidth / 2;
drawingRect1.bottom = drawingRect1.top + mChannelLayoutHeight;
mPaint.setColor(mTimeBarLineColor);
canvas.drawRect(drawingRect1, mPaint);
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setColor(mColorPrimaryDark);
mPaint.setTextSize(mEventLayoutTextSize - 2);
canvas.drawText(epgData.getChannel(position).getName(), drawingRect1.centerX(), drawingRect1.centerY() + 10, mPaint);
}
void resetBoundaries() {
mMillisPerPixel = calculateMillisPerPixel();
mTimeOffset = calculatedBaseLine();
mTimeLowerBoundary = getTimeFrom(0);
mTimeUpperBoundary = getTimeFrom(getWidth());
}
private long calculateMillisPerPixel() {
return HOURS_IN_VIEWPORT_MILLIS / (getResources().getDisplayMetrics().widthPixels - mChannelLayoutWidth - mChannelLayoutMargin);
}
private long calculatedBaseLine() {
DateTime dateTime = new DateTime(LocalDateTime.now().toDateTime().getMillis()).minusMillis(DAYS_BACK_MILLIS);
if (DAYS_BACK_MILLIS > 0) {
//Log.e(TAG, " @ calculatedBaseLine with CU/SO @ " + dateTime.withTimeAtStartOfDay().toString());
return dateTime.withTimeAtStartOfDay().getMillis();
} else {
//Log.e(TAG, " @ calculatedBaseLine @ " + new Date(EPGUtils.roundOfTimeToLowerBound(dateTime.getMillis())));
return EPGUtil.roundOfTimeToLowerBound(dateTime.getMillis());
}
}
/**
* @param x 像素值(某个地方距epg起始地方的偏移值)
* @return 得到x地方的时刻,单位毫秒
*/
private long getTimeFrom(int x) {
return (x * mMillisPerPixel) + mTimeOffset;
}
/**
* @param position 可以理解成第几个节目
* @return 第position节目显示区域顶部位置像素值
*/
private int getTopFrom(int position) {
int y = position * (mChannelLayoutHeight + mChannelLayoutMargin) + mChannelLayoutMargin + mTimeBarHeight;
return y;
}
private int getXFrom(long time) {
return (int) ((time - mTimeOffset) / mMillisPerPixel) + mChannelLayoutMargin + mChannelLayoutWidth + mChannelLayoutMargin;
}
public int getServiceIndexInList(int channelNo) {
for (int i = 0; i < serviceList.size(); ++i) {
if (serviceList.get(i).getChannelNumber() == channelNo)
return i;
}
return 0;
}
private int getXPositionStart() {
//Log.e(TAG, " @ @ getXPositionStart @ @ " + new Date(EPGUtils.roundOfTimeToLowerBound(System.currentTimeMillis())));
if (DAYS_BACK_MILLIS > 0) {
int temp = getXFrom(EPGUtil.roundOfTimeToLowerBound(System.currentTimeMillis())) - mChannelLayoutMargin - mChannelLayoutWidth;
//Log.e(TAG, " @ @ getXPositionStart @ @ " + temp);
return temp;
} else {
return 0;
}
}
private boolean isEventStartTimeVisible(final long start) {
return (start >= mTimeLowerBoundary || start <= mTimeUpperBoundary);
}
private Rect calculateProgramsHitArea() {
mMeasuringRect.top = mTimeBarHeight;
int visibleChannelsHeight = epgData.getChannelCount() * (mChannelLayoutHeight + mChannelLayoutMargin);
mMeasuringRect.bottom = visibleChannelsHeight < getHeight() ? visibleChannelsHeight : getHeight();
mMeasuringRect.left = mChannelLayoutWidth;
mMeasuringRect.right = getWidth();
return mMeasuringRect;
}
public void moveRight() {
if (currentProgram != null) {
List<EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean> events = epgData.getEvents(currentChannelPosition);
if (events != null && events.size() > 0 && (currentProgram.getIntStartTime() == events.get(events.size() - 1).getIntStartTime())) {
//Log.d("wujiang", "moveRight: it is last event");
return;
}
isMoveRight = true;
isMoveLeft = false;
gotoProgram(currentChannelPosition, currentProgram.getIntStopTime() + 1);
invalidate();
int x = 0;
long dur = currentProgram.getIntStopTime() - currentProgram.getIntStartTime();
long currentUpperBound = EPGUtil.roundOfTimeToLowerBound(currentProgram.getIntStartTime()) + HOURS_IN_VIEWPORT_MILLIS;
if (dur > HOURS_IN_VIEWPORT_MILLIS && !isEventStartTimeVisible(currentProgram.getIntStartTime())) {
//Log.d("wujiang", "moveRight: 1111111111111111");
if (EPGUtil.roundOfTimeToLowerBound(currentProgram.getIntStartTime()) != currentProgram.getIntStartTime()) {
x = getXFrom(currentProgram.getIntStartTime() + ((30 * 60 * 1000) - (currentProgram.getIntStartTime() - EPGUtil.roundOfTimeToLowerBound(currentProgram.getIntStartTime()))));
} else {
x = getXFrom(currentProgram.getIntStartTime() + (HOURS_IN_VIEWPORT_MILLIS - 30 * 60 * 1000));
}
//x = getXFrom((currentProgram.getStart() - EPGUtils.roundOfTimeToLowerBound(currentProgram.getStart())) + HOURS_IN_VIEWPORT_MILLIS);
} else if (dur > HOURS_IN_VIEWPORT_MILLIS) {
//Log.d("wujiang", "moveRight: 22222222222");
if (EPGUtil.roundOfTimeToLowerBound(currentProgram.getIntStartTime()) != currentProgram.getIntStartTime()) {
x = getXFrom(currentProgram.getIntStartTime() + ((60 * 60 * 1000) - ((currentProgram.getIntStartTime() - EPGUtil.roundOfTimeToLowerBound(currentProgram.getIntStartTime())))));
} else {
x = getXFrom(currentProgram.getIntStartTime() + (HOURS_IN_VIEWPORT_MILLIS - 60 * 60 * 1000));
}
} else if (EPGUtil.roundOfTimeToLowerBound(currentProgram.getIntStartTime()) != currentProgram.getIntStartTime()) {
//Log.d("wujiang", "moveRight: 33333333333333");
x = getXFrom(currentProgram.getIntStartTime() + ((30 * 60 * 1000) - (currentProgram.getIntStartTime() - EPGUtil.roundOfTimeToLowerBound(currentProgram.getIntStartTime()))));
} else {
//Log.d("wujiang", "moveRight: 444444444444444");
x = getXFrom(currentProgram.getIntStartTime() + (30 * 60 * 1000));
}
//EPGUtils.printTime("MoveRight", mTimeUpperBoundary);
//int x = getXFrom(currentProgram.getEndTime());
//Log.d("wujiang", "moveRight: x = " + x);
//Log.d("wujiang", "moveRight: getScrollX() = " + getScrollX());
//Log.d("wujiang", "moveRight: getWidth() = " + getWidth());
int programAreaX = calculateProgramsHitArea().right + getScrollX();
//Log.d("wujiang", "moveRight: calculateProgramsHitArea().right = " + calculateProgramsHitArea().right);
if (x > programAreaX) {
scrollBy(x - programAreaX - 30, 0);
}
}
}
public void moveLeft() {
if (currentProgram != null) {
if (currentProgram.getIntStartTime() <= mTimeOffset) {
//Log.d("wujiang", "moveLeft: 1111111");
return;
}
isMoveRight = false;
isMoveLeft = true;
gotoProgram(currentChannelPosition, currentProgram.getIntStartTime() - 1);
invalidate();
int x = 0;//getXFrom(currentProgram.getStartTime());
if (currentProgram.getIntStartTime() < mTimeOffset) {
x = getXFrom(mTimeOffset);
} else {
x = getXFrom(EPGUtil.roundOfTimeToLowerBound(currentProgram.getIntStartTime()));
}
int programAreaX = calculateProgramsHitArea().left + getScrollX();
if (x < programAreaX) {
scrollBy(x - programAreaX, 0);
}
} else {
Log.e("wujiang", " @ MoveLeft @ I think CatchUp is enabled");
}
}
public boolean moveDown() {
if (currentProgram != null) {
isMoveRight = false;
isMoveLeft = false;
long time = 0;
if (referenceEvent.getIntStartTime() < mTimeOffset) {
time = mTimeOffset + 1;
} else if (referenceEvent.isCurrent() && referenceEvent.getIntStartTime() < EPGUtil.roundOfTimeToLowerBound(System.currentTimeMillis())) {
time = EPGUtil.roundOfTimeToLowerBound(System.currentTimeMillis()) + 1;
} else {
time = EPGUtil.roundOfTimeToLowerBound(referenceEvent.getIntStartTime()) + 1;
}
//Log.e("wujiang", " moveDown: mTimeOffset = " + mTimeOffset);
//Log.e("wujiang", " moveDown: currentChannelPosition = " + currentChannelPosition);
//Log.e("wujiang", " moveDown: time = " + time);
gotoProgram(currentChannelPosition + 1, time);
invalidate();
int y = getTopFrom(currentChannelPosition);
int programAreaY = calculateProgramsHitArea().bottom + getScrollY() - mChannelLayoutHeight;
if (y > programAreaY) {
scrollBy(0, y - programAreaY);
}
if (currentChannelPosition >= (epgData.getChannelCount() - 1)) {
//Log.d("wujiang", "moveDown: 11111111111");
return true;
}
}
//Log.d("wujiang", "moveDown: 2222222222");
return false;
}
public void moveUp() {
if (currentProgram != null) {
isMoveRight = false;
isMoveLeft = false;
//ORG
//long time = (currentProgram.getStartTime() + currentProgram.getEndTime()) / 2;
long time = 0;
if (referenceEvent.getIntStartTime() < mTimeOffset) {
time = mTimeOffset + 1;
} else if (referenceEvent.isCurrent() && referenceEvent.getIntStartTime() < EPGUtil.roundOfTimeToLowerBound(System.currentTimeMillis())) {
time = EPGUtil.roundOfTimeToLowerBound(System.currentTimeMillis()) + 1;
} else {
time = EPGUtil.roundOfTimeToLowerBound(referenceEvent.getIntStartTime()) + 1;
}
gotoProgram(currentChannelPosition - 1, time);
invalidate();
int y = getTopFrom(currentChannelPosition);
int programAreaY = calculateProgramsHitArea().top + getScrollY();
if (y < programAreaY) {
scrollBy(0, y - programAreaY);
}
}
}
public void moveToDestPosition(int position, int direction) {
if (currentProgram != null) {
isMoveRight = false;
isMoveLeft = false;
long time = 0;
if (referenceEvent.getIntStartTime() < mTimeOffset) {
time = mTimeOffset + 1;
} else if (referenceEvent.isCurrent() && referenceEvent.getIntStartTime() < EPGUtil.roundOfTimeToLowerBound(System.currentTimeMillis())) {
time = EPGUtil.roundOfTimeToLowerBound(System.currentTimeMillis()) + 1;
} else {
time = EPGUtil.roundOfTimeToLowerBound(referenceEvent.getIntStartTime()) + 1;
}
gotoProgram(position, time);
invalidate();
int y = getTopFrom(position);
if (direction == UP_DIRECTION) {
int programAreaY = calculateProgramsHitArea().top + getScrollY();
if (y < programAreaY) {
scrollBy(0, y - programAreaY);
}
} else {
int programAreaY = calculateProgramsHitArea().bottom + getScrollY() - mChannelLayoutHeight;
if (y > programAreaY) {
scrollBy(0, y - programAreaY);
}
}
}
}
}
这里重点是如下几个函数:drawEvents,drawTimebar,drawTimeLine,moveToDestPosition。
2、在显示epg信息的activity里的布局文件中使用自定义EPG View,代码如下:
<!-- 时刻表、节目列表和7天epg -->
<RelativeLayout
android:id="@+id/epg_view_area"
android:layout_width="match_parent"
android:layout_height="235dp"
android:layout_alignParentBottom="true"
android:background="@android:color/transparent"
android:visibility="gone">
<!-- epg 信息的当前时间、节目列表 -->
<LinearLayout
android:id="@+id/recyclerView_channel_list_area"
android:layout_width="272dp"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- epg 信息的当前时间 -->
<TextView
android:id="@+id/epg_date"
android:layout_width="match_parent"
android:layout_height="31dp"
android:background="@color/color_epg_focus"
android:gravity="center"
android:textColor="@color/epg_event_layout_text" />
<!-- 节目列表 -->
<ListView
android:id="@+id/listview_channel_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/translucent_black"
android:dividerHeight="1dp"
android:listSelector="@drawable/epg_channel_recyclerview_item_selector">
</ListView>
</LinearLayout>
<!-- 7天EPG信息 -->
<com.amlogic.dvb_custom_view.EpgView
android:id="@+id/epg_view"
android:layout_width="700dp"
android:layout_height="match_parent"
android:layout_toRightOf="@+id/recyclerView_channel_list_area">
</com.amlogic.dvb_custom_view.EpgView>
</RelativeLayout>
listview_channel_list是显示节目名称的listview,在它的上方显示的是当前EPG信息所属的时间。
3、进入DVB时加载所有节目的EPG信息,一般是7天的EPG。这个时候显示EPG信息的那个activity还没有显示。
public static HashMap<ServiceInfoEntity, List<EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean>> result;
这是一个哈希列表,Key对应的是节目,Value对应的是这个节目7天EPG的链表。
for (int i = 0; i < channel_list.size(); i++) {
ServiceInfoEntity serviceObj = channel_list.get(i);
result.put(serviceObj, loadEpgFromDB(serviceObj, i));
}
把所有节目节目的epg信息存放到result里。
4、在显示EPG信息的activity里加载epg信息,并可以上下左右切换。
public static HashMap<ServiceInfoEntity, List<EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean>> mResult;
public static EPGData mEpgData;
//节目一般情况下会有分组,下面的代码是根据组的index过滤出对应的节目
List<ServiceInfoEntity> serviceInfoEntities = ChannelListUtils.getServicesFromCachedAndDb(AndroidNineMainMenu.this, mChannelGruopInfoList.get(position));
//加载组里的节目对用的EPG信息
mResult.clear();
for (int i = 0; i < serviceInfoEntities.size(); i++) {
ServiceInfoEntity serviceInfoEntity = serviceInfoEntities.get(i);
//DVBPlayer.result就是第3步那里的result
if (DVBPlayer.result.get(serviceInfoEntity) != null) {
mResult.put(serviceInfoEntity, DVBPlayer.result.get(serviceInfoEntity));
}
}
mEpgData = new EPGDataImpl(mResult);
mEpgData.cleanSelection();
mChannelListviewAdapter.setEpgData(mEpgData);
mEpgView.setEPGData(AndroidNineMainMenu.this, mEpgData);
mEpgView.recalculateAndRedraw(false, false);
相关类的代码
public interface EPGData {
ServiceInfoEntity getChannel(int position);
List<EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean> getEvents(int channelPosition);
List<ServiceInfoEntity> getChannels();
//CircularArray<Event> getEventsC(int channelPosition);
EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean getEvent(int channelPosition, int programPosition);
String getStartOverStatus(EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean event);
String getCatchUpStatus(EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean event);
int getChannelCount();
boolean hasData();
void cleanSelection();
}
public class EPGDataImpl implements EPGData {
private List<ServiceInfoEntity> channels = Lists.newArrayList();
private List<List<EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean>> events = Lists.newArrayList();
public EPGDataImpl(Map<ServiceInfoEntity, List<EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean>> data) {
if (data == null || data.isEmpty()) {
Log.d("wujiang", "EPGDataImpl: data == null || data.isEmpty()");
return;
}
channels = Lists.newArrayList(data.keySet());
events = Lists.newArrayList(data.values());
Log.d("wujiang", "EPGDataImpl: channels size = " + channels.size());
Log.d("wujiang", "EPGDataImpl: events size = " + events.size());
}
public List<ServiceInfoEntity> getChannels() {
return channels;
}
public ServiceInfoEntity getChannel(int position) {
if (channels == null || channels.size() < 1) {
return null;
} else {
return channels.get(position);
}
}
public List<EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean> getEvents(int channelPosition) {
if (events == null || events.size() < 1) {
return null;
} else {
return events.get(channelPosition);
}
}
public EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean getEvent(int channelPosition, int programPosition) {
EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean e = null;
try {
e = events.get(channelPosition).get(programPosition);
} catch (Exception ex) {
Log.e("EPGImpl", "" + Log.getStackTraceString(ex));
Log.e("EPGImpl", "channelPosition " + channelPosition + " programPosition " + programPosition);
}
return e;
}
@Override
public String getCatchUpStatus(EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean event) {
/*ServiceInfoEntity tmp = null;
long chNo = event.getChannelNumber();
for(ServiceInfoEntity s : channels) {
if(s.getChannelNumber() == chNo) {
tmp = s;
} else {
tmp = channels.get(0);
}
}
if(tmp == null)
tmp = channels.get(0);
return tmp.getCatchup();*/
return null;
}
@Override
public String getStartOverStatus(EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean event) {
/* ServiceInfoEntity tmp = null;
long chNo = event.getChannelNumber();
for(ServiceInfoEntity s : channels) {
if(s.getChannelNumber() == chNo) {
tmp = s;
} else {
tmp = channels.get(0);
}
}
if(tmp == null)
tmp = channels.get(0);
return tmp.getStartover();*/
return null;
}
public int getChannelCount() {
return channels.size();
}
@Override
public boolean hasData() {
return !channels.isEmpty();
}
@Override
public void cleanSelection() {
for (List<EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean> channelEvents : this.events) {
for (EnhancedScheduleGridBean.ScheduleGridBean.ChannelBean.ProgrammeBean event : channelEvents) {
if (event.isSelected()) event.setSelected(false);
}
}
}
}
当焦点在listview_channel_list时按上下切换epg信息。
/* 显示节目名的ListView Item Selected响应函数 */
mChannelListView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
mChannelListRecyclerViewCurrentPosition = position;
Log.d("wujiang", "mChannelListView->onItemSelected: mChannelListRecyclerViewCurrentPosition = " + mChannelListRecyclerViewCurrentPosition);
Log.d("wujiang", "mChannelListView->onItemSelected: mEpgView.currentChannelPosition = " + mEpgView.currentChannelPosition);
if (mEpgView.currentChannelPosition >= 0) {
if (position > mEpgView.currentChannelPosition) {
mEpgView.moveToDestPosition(position, EpgView.DOWN_DIRECTION);
} else if (position < mEpgView.currentChannelPosition) {
mEpgView.moveToDestPosition(position, EpgView.UP_DIRECTION);
}
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
//左右键切换epg信息
mEpgView.moveLeft();
mEpgView.moveRight();
我这里贴出的都是关键性的代码,如果你确实有需求,那你得好好研究这些代码,肯定对你是有用的。
The End