package com.lancens.wxdoorbell.widget;
import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.os.Handler; import android.os.Message; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.widget.Scroller; import java.io.Serializable; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Locale; /** * Created by WuJinLin on 2017/7/7. */ public class PlaybackView extends View { private static String TAG = "PlaybackView>>"; private Paint mPaint; private static final int SCALE_COLOR = 0xFF7C7C7C; private static final int VIDEO_COLOR = 0xFFffab8a; private static final int MID_COLOR = 0xFF039BE5; private static final int MID_BACKGROUND_COLOR = 0x557C7C7C; private int VIEW_BACKGROUND_COLOR = 0x00000000; private static final float TWO_MIN_SCALE_HEIGHT = 5; private static final float TEN_MIN_SCALE_HEIGHT = 10; private static final float HOUR_SCALE_HEIGHT = 15; private float widthTimes = 1.5f; private List<PlaybackVo> videos = new ArrayList<>(); private float SECOND_WIDTH = 30;//px private float MIN_SECOND_WIDTH = 5; private float MAX_SECOND_WIDTH = 30; private static final int TWO_MINUTE_SCALE_INTERVAL = 120; private static final int TEN_MINUTE_SCALE_INTERVAL = 600; private static final int TWENTY_MINUTE_SCALE_INTERVAL = 1200; private static final int ONE_HOUR_SCALE_INTERVAL = 3600; private static final int TWO_HOUR_SCALE_INTERVAL = 7200; private static final int SCALE_TEXT_SIZE = 12; private int midBackgroundWidth = 5;//dp private float mWidth, mHeight; private float mDensity;// 屏幕密度 dp*mDensity=px private Scroller mScroller; private VelocityTracker mVelocityTracker; private int mMinVelocity; private TimeAlgorithm mValue;// 当前刻度指示时间 private TimeAlgorithm selectValue;//指定移动时间 public PlaybackView(Context context) { this(context, null); } public PlaybackView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public PlaybackView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } private void init(Context context) { mScroller = new Scroller(context); mVelocityTracker = VelocityTracker.obtain(); mDensity = context.getResources().getDisplayMetrics().density; mPaint = new Paint(); mPaint.setColor(SCALE_COLOR); mPaint.setAntiAlias(true); mPaint.setDither(true); mValue = new TimeAlgorithm(System.currentTimeMillis() * 1000); mMinVelocity = ViewConfiguration.get(context).getScaledMinimumFlingVelocity(); // Log.d(TAG, "init: " + mDensity); } public void moveToValue(long micros) { if (micros == mValue.getTimeInMicros()) return; Message msg = Message.obtain(); msg.what = SET_VALUE; selectValue = new TimeAlgorithm(micros); if (isCurrentDay(mValue, selectValue)) { moveX = (selectValue.getTimeInSecond() - mValue.getTimeInSecond()) * SECOND_WIDTH / SET_VALUE_AUTO_MOVE_COUNT; if (Math.abs(moveX) < SECOND_WIDTH && moveX != 0) { moveX = moveX * SECOND_WIDTH / moveX; } // Log.d(TAG, "moveToValue: " + moveX + ">>" + SECOND_WIDTH); handler.sendMessage(msg); } } public void setValue(long micros) { removeAllMessage(); mValue = new TimeAlgorithm(micros); postInvalidate(); if (listener != null) { listener.onValueChanged(mValue.getStringTimeInSecond(), mValue.getTimeInMicros()); } handler.sendEmptyMessageDelayed(DELAY_MOVE_TO_NEARBY_VIDEO, delayMoveToNearbyVideoMs); } private void removeAllMessage() { handler.removeMessages(DELAY_MOVE_TO_NEARBY_VIDEO); handler.removeMessages(SET_VALUE); } public void setViewBackgroundColor(int color) { this.VIEW_BACKGROUND_COLOR = color; } public void setVideos(List<PlaybackVo> videos) { if (videos == null || videos.size() == 0) return; this.videos = videos; moveToNearbyVideo(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { // Log.d(TAG, "onSizeChanged: "); mWidth = w; mHeight = h; MAX_SECOND_WIDTH = mWidth / 1800; MIN_SECOND_WIDTH = mWidth / (60 * 60 * 24); SECOND_WIDTH = MAX_SECOND_WIDTH; super.onSizeChanged(w, h, oldw, oldh); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { // Log.d(TAG, "onLayout: " + changed + ">>left=" + left + ">>top=" + top + ">>right=" + right + ">>bottom=" + bottom); super.onLayout(changed, left, top, right, bottom); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // Log.d(TAG, "onDraw: "); } private int SET_VALUE_AUTO_MOVE_TIME = 100;//ms private int SET_VALUE_AUTO_MOVE_COUNT = 10;//times private float moveX = 0; private static final int SET_VALUE = 0; private static final int DELAY_MOVE_TO_NEARBY_VIDEO = 1; private int delayMoveToNearbyVideoMs = 1000;//ms private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (hasMessages(DELAY_MOVE_TO_NEARBY_VIDEO)) { removeMessages(DELAY_MOVE_TO_NEARBY_VIDEO); } switch (msg.what) { case SET_VALUE: autoMoving(); break; case DELAY_MOVE_TO_NEARBY_VIDEO: moveToNearbyVideo(); break; } } }; private void autoMoving() { TimeAlgorithm value = mValue.addOrSub((int) (moveX / SECOND_WIDTH)); if (moveX > 0) { if (value.getTimeInMicros() > selectValue.getTimeInMicros()) { mValue = new TimeAlgorithm(selectValue.getTimeInMicros()); // Log.d(TAG, "autoMoving: >"); invalidate(); handler.removeMessages(SET_VALUE); } } else if (moveX < 0) { if (value.getTimeInMicros() < selectValue.getTimeInMicros()) { mValue = new TimeAlgorithm(selectValue.getTimeInMicros()); invalidate(); // Log.d(TAG, "autoMoving: <"); handler.removeMessages(SET_VALUE); } } if (mValue.getTimeInMicros() != selectValue.getTimeInMicros()) { moveX(moveX); handler.sendEmptyMessageDelayed(SET_VALUE, SET_VALUE_AUTO_MOVE_TIME / SET_VALUE_AUTO_MOVE_COUNT); } else { if (listener != null) { listener.onVideoStart(mValue.getStringTimeInSecond(), mValue.getTimeInMicros()); } } } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); // Log.d(TAG, "dispatchDraw: "); // canvas.drawColor(VIEW_BACKGROUND_COLOR); drawVideos(canvas); drawScale(canvas); drawMidLine(canvas); } private int VIDEO_PADDING = 1; private void drawVideos(Canvas canvas) { if (videos == null || videos.size() == 0) return; canvas.save(); for (int i = 0; i < videos.size(); i++) { PlaybackVo vo = videos.get(i); float startX = mWidth / 2 + (vo.getStartTA().getTimeInSecond() - mValue.getTimeInSecond()) * SECOND_WIDTH; float endX = mWidth / 2 + (vo.getEndTA().getTimeInSecond() - mValue.getTimeInSecond()) * SECOND_WIDTH; if (endX < 0 || startX > mWidth) continue; RectF rectF = new RectF(startX, VIDEO_PADDING, endX, mHeight - VIDEO_PADDING); mPaint.setColor(VIDEO_COLOR); mPaint.setStyle(Paint.Style.FILL); canvas.drawRect(rectF, mPaint); } canvas.restore(); } private void drawScale(Canvas canvas) { canvas.save(); mPaint.setColor(SCALE_COLOR); mPaint.setStrokeWidth(mDensity); int scaleMode = getScaleMode(); int mod = mValue.mod(scaleMode); float drawWidth = 0; for (int i = 0; drawWidth < mWidth * 1.1; i++) { float height = TWO_MIN_SCALE_HEIGHT; float x = 0; int mode = 0; x = mWidth / 2 + (scaleMode - mod + scaleMode * i) * SECOND_WIDTH; TimeAlgorithm rightTime = mValue.addOrSub(scaleMode - mod + scaleMode * i); String time = rightTime.getStringTimeInMinute(); Rect rect = new Rect(); // Log.d(TAG, "isCurrentDayContainZero: " + rightTime.getStringTimeInSecond() + ">>" + scaleMode // + ">>" + isCurrentDayContainZero(mValue, rightTime) + ">>" + isDrawScaleLine(rightTime) // + ">>" + mValue.getTimeInMillis() + ">>" + mValue.getCurrentMaxTimeInMillis() + ">>" + mValue.getCurrentMinTimeInMillis() + ">>" + rightTime.getTimeInMillis()); if (isCurrentDayContainZero(mValue, rightTime)) { mode = rightTime.getScaleMode(); height = getScaleHeight(rightTime) * mDensity; if (isDrawScaleLine(rightTime)) { canvas.drawLine(x, 0, x, height, mPaint); canvas.drawLine(x, mHeight, x, mHeight - height, mPaint); } mPaint.setTextSize(SCALE_TEXT_SIZE * mDensity); mPaint.getTextBounds(time, 0, time.length(), rect); if (isDrawText(rightTime, rect.width() * widthTimes)) { if (time.equals("00:00")) time = "24:00"; canvas.drawText(time, x - rect.width() / 2, height + rect.height() + 2 * mDensity, mPaint); } } x = mWidth / 2 - (mod + scaleMode * i) * SECOND_WIDTH; TimeAlgorithm leftTime = mValue.addOrSub(-(mod + scaleMode * i)); height = getScaleHeight(leftTime) * mDensity; if (isCurrentDayContainZero(mValue, leftTime)) { if (isDrawScaleLine(leftTime)) { canvas.drawLine(x, 0, x, height, mPaint); canvas.drawLine(x, mHeight, x, mHeight - height, mPaint); } time = leftTime.getStringTimeInMinute(); mPaint.getTextBounds(time, 0, time.length(), rect); mode = leftTime.getScaleMode(); if (isDrawText(leftTime, rect.width() * widthTimes)) { canvas.drawText(time, x - rect.width() / 2, height + rect.height() + 2 * mDensity, mPaint); } } drawWidth += 2 * scaleMode * SECOND_WIDTH; } mPaint.setStrokeWidth(1.5f * mDensity); canvas.drawLine(0, 0, mWidth, 0, mPaint); canvas.drawLine(0, mHeight, mWidth, mHeight, mPaint); canvas.restore(); } private void drawMidLine(Canvas canvas) { canvas.save(); // Log.d(TAG, "drawMidLine: width=" + mWidth + ">>height=" + mHeight); mPaint.setColor(MID_BACKGROUND_COLOR); mPaint.setStyle(Paint.Style.FILL); RectF rectF = new RectF((mWidth - midBackgroundWidth * mDensity) / 2, 0, (mWidth + midBackgroundWidth * mDensity) / 2, mHeight); canvas.drawRect(rectF, mPaint); mPaint.setStrokeWidth(1.5f * mDensity); mPaint.setColor(MID_COLOR); canvas.drawLine(mWidth / 2, 0, mWidth / 2, mHeight, mPaint); canvas.restore(); // Log.d(TAG, "drawMidLine: " + mValue.getStringTimeInSecond()); } private boolean isCurrentDayContainZero(TimeAlgorithm current, TimeAlgorithm compare) { boolean isCurrentDay = true; if (current.getCurrentMaxTimeInMillis() / 1000 + 1 < compare.getTimeInMillis() / 1000) { isCurrentDay = false; } else if (current.getCurrentMinTimeInMillis() > compare.getTimeInMillis()) { isCurrentDay = false; } return isCurrentDay; } private boolean isCurrentDay(TimeAlgorithm current, TimeAlgorithm compare) { boolean isCurrentDay = true; if (current.getCurrentMaxTimeInMillis() / 1000 < compare.getTimeInMillis() / 1000) { isCurrentDay = false; } else if (current.getCurrentMinTimeInMillis() > compare.getTimeInMillis()) { isCurrentDay = false; } return isCurrentDay; } private int getScaleMode() { int mode = TWO_MINUTE_SCALE_INTERVAL; if (ONE_HOUR_SCALE_INTERVAL * SECOND_WIDTH <= TWO_MINUTE_SCALE_INTERVAL * MAX_SECOND_WIDTH) { mode = ONE_HOUR_SCALE_INTERVAL; } else if (TWENTY_MINUTE_SCALE_INTERVAL * SECOND_WIDTH <= TWO_MINUTE_SCALE_INTERVAL * MAX_SECOND_WIDTH) { mode = TWENTY_MINUTE_SCALE_INTERVAL; } else if (TEN_MINUTE_SCALE_INTERVAL * SECOND_WIDTH <= 2 * TWO_MINUTE_SCALE_INTERVAL * MAX_SECOND_WIDTH) { mode = TEN_MINUTE_SCALE_INTERVAL; } return mode; } private boolean isDrawScaleLine(TimeAlgorithm time) { boolean draw = false; switch (time.getScaleMode()) { case TimeAlgorithm.MODE_TWO_MINUTE: draw = TEN_MINUTE_SCALE_INTERVAL * SECOND_WIDTH > TWO_MINUTE_SCALE_INTERVAL * MAX_SECOND_WIDTH * 2; break; case TimeAlgorithm.MODE_TEN_MINUTE: draw = (time.isTwentyMinuteMultiple() && ONE_HOUR_SCALE_INTERVAL * SECOND_WIDTH > 2 * TWO_MINUTE_SCALE_INTERVAL * MAX_SECOND_WIDTH) || (!time.isTwentyMinuteMultiple() && TWENTY_MINUTE_SCALE_INTERVAL * SECOND_WIDTH > 1.5 * TWO_MINUTE_SCALE_INTERVAL * MAX_SECOND_WIDTH); break; case TimeAlgorithm.MODE_HOUR: draw = ONE_HOUR_SCALE_INTERVAL * SECOND_WIDTH > TWO_MINUTE_SCALE_INTERVAL * MAX_SECOND_WIDTH || time.isTwoHourMultiple(); break; } return draw; } private boolean isDrawText(TimeAlgorithm time, float width) { if (time.getScaleMode() < TimeAlgorithm.MODE_TEN_MINUTE) return false; // Log.d(TAG, "isDrawText: " + time.isTwoHourMultiple() + ">>" + time.getStringTimeInSecond()); return TEN_MINUTE_SCALE_INTERVAL * SECOND_WIDTH > width || (TWENTY_MINUTE_SCALE_INTERVAL * SECOND_WIDTH > width && time.isTwentyMinuteMultiple()) || (time.getScaleMode() == TimeAlgorithm.MODE_HOUR && ONE_HOUR_SCALE_INTERVAL * SECOND_WIDTH > width) || time.isTwoHourMultiple(); } private float getScaleHeight(TimeAlgorithm t) { float height = TWO_MIN_SCALE_HEIGHT; switch (t.getScaleMode()) { case TimeAlgorithm.MODE_HOUR: height = HOUR_SCALE_HEIGHT; break; case TimeAlgorithm.MODE_TEN_MINUTE: height = TEN_MIN_SCALE_HEIGHT; break; case TimeAlgorithm.MODE_TWO_MINUTE: height = TWO_MIN_SCALE_HEIGHT; break; } return height; } private float downOneX, downTwoX, downOneY, downTwoY; private int clickCount = 0; private float distance; private boolean needDelay; private long clickTime;//ms @Override public boolean onTouchEvent(MotionEvent event) { mVelocityTracker.addMovement(event); lastX = 0; mScroller.forceFinished(true); // Log.d(TAG, "onTouchEvent: "); switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: handler.removeMessages(DELAY_MOVE_TO_NEARBY_VIDEO); handler.removeMessages(SET_VALUE); downOneX = event.getX(0); downOneY = event.getY(0); clickCount++; if (clickCount == 2 && System.currentTimeMillis() - clickTime > 100) {//防抖 SECOND_WIDTH = MAX_SECOND_WIDTH;//SECOND_WIDTH == MAX_SECOND_WIDTH ? MIN_SECOND_WIDTH : MAX_SECOND_WIDTH; // Log.d(TAG, "onTouchEvent: 恢复 >>" + (System.currentTimeMillis() - clickTime)); invalidate(); } clickTime = System.currentTimeMillis(); handler.postDelayed(new Runnable() { @Override public void run() { clickCount = 0; } }, 200); // Log.d(TAG, "onTouchEvent: ACTION_DOWN " + downOneX + ">>" + event.getPointerCount()); return true; case MotionEvent.ACTION_POINTER_DOWN: if (event.getPointerCount() > 1) { downTwoX = event.getX(1); downTwoY = event.getY(1); } // Log.d(TAG, "onTouchEvent: ACTION_POINTER_DOWN " + downTwoX + ">>" + event.getPointerCount()); break; case MotionEvent.ACTION_MOVE: move(event); break; case MotionEvent.ACTION_POINTER_UP: distance = 0; needDelay = true; handler.postDelayed(new Runnable() { @Override public void run() { needDelay = false; } }, 200); // Log.d(TAG, "onTouchEvent: ACTION_POINTER_UP " + event.getPointerCount()); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: // Log.d(TAG, "onTouchEvent: ACTION_UP"); distance = 0; autoScroll(); needDelay = false; break; } return super.onTouchEvent(event); } private void autoScroll() { if (needDelay) { handler.sendEmptyMessageDelayed(DELAY_MOVE_TO_NEARBY_VIDEO, delayMoveToNearbyVideoMs); return; } mVelocityTracker.computeCurrentVelocity((int) mWidth, Float.MAX_VALUE); float xVelocity = mVelocityTracker.getXVelocity(); if (Math.abs(xVelocity) > mMinVelocity) { // Log.d(TAG, "autoScroll: " + xVelocity + ">>" + mMinVelocity); mScroller.forceFinished(false); mScroller.fling(0, 0, (int) xVelocity, 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0); postInvalidate(); } else if (listener != null) { // Log.d(TAG, "autoScroll: DELAY_MOVE_TO_NEARBY_VIDEO"); handler.sendEmptyMessageDelayed(DELAY_MOVE_TO_NEARBY_VIDEO, delayMoveToNearbyVideoMs); } } private synchronized void move(MotionEvent event) { int num = event.getPointerCount(); if (num > 1) { float d = Math.abs(event.getX(1) - event.getX(0)); distance = Math.abs(downTwoX - downOneX); float scale = 1 + (d - distance) / distance; float width = SECOND_WIDTH; width *= scale; if (width > MAX_SECOND_WIDTH) { width = MAX_SECOND_WIDTH; } else if (width < MIN_SECOND_WIDTH) { width = MIN_SECOND_WIDTH; } if (width != SECOND_WIDTH) { SECOND_WIDTH = width; invalidate(); } // Log.d(TAG, "onTouchEvent: ACTION_MOVE 22 scale= " + scale); downOneX = event.getX(0); downOneY = event.getY(0); downTwoX = event.getX(1); downTwoY = event.getY(1); distance = d; } else { if (!needDelay) { float move = downOneX - event.getX(0); // Log.d(TAG, "onTouchEvent: ACTION_MOVE " + move + ">>" + SECOND_WIDTH); moveX(move); } downOneX = event.getX(0); downOneY = event.getY(0); } } private void moveX(float move) { int sec = (int) (move / SECOND_WIDTH); TimeAlgorithm value = mValue.addOrSub(sec); if (value.getTimeInMillis() < mValue.getCurrentMinTimeInMillis()) { if (mScroller != null) mScroller.forceFinished(true); value.setTimeInMillis(mValue.getCurrentMinTimeInMillis()); } else if (value.getTimeInMillis() > mValue.getCurrentMaxTimeInMillis()) { if (mScroller != null) mScroller.forceFinished(true); value.setTimeInMillis(mValue.getCurrentMaxTimeInMillis()); } if (value.getTimeInMillis() != mValue.getTimeInMillis()) { mValue = value; if (listener != null) { listener.onValueChanged(mValue.getStringTimeInSecond(), mValue.getTimeInMicros()); } postInvalidate(); } } private int lastX = 0; @Override public void computeScroll() { super.computeScroll(); if (mScroller.computeScrollOffset()) { if (mScroller.getCurrX() == mScroller.getFinalX()) { lastX = 0; handler.sendEmptyMessageDelayed(DELAY_MOVE_TO_NEARBY_VIDEO, delayMoveToNearbyVideoMs); // Log.d(TAG, "computeScroll: end DELAY_MOVE_TO_NEARBY_VIDEO"); } else { int xPosition = mScroller.getCurrX(); // Log.d(TAG, "computeScroll: scroll " + lastX + ">>" + xPosition + ">>" + SECOND_WIDTH); if ((lastX - xPosition) / SECOND_WIDTH == 0) { handler.sendEmptyMessageDelayed(DELAY_MOVE_TO_NEARBY_VIDEO, delayMoveToNearbyVideoMs); } else { moveX(lastX - xPosition); } lastX = xPosition; } } else { // Log.d(TAG, "computeScrollOffset: false"); } } private void moveToNearbyVideo() { if (videos == null || videos.size() == 0) { if (listener != null) listener.onNoneVideo(mValue.getStringTimeInSecond(), mValue.getTimeInMicros()); return; } long value = 0; for (int i = 0; i < videos.size(); i++) { PlaybackVo vo = videos.get(i); if (vo.getStartTime() < mValue.getTimeInMicros() && vo.getEndTime() > mValue.getTimeInMicros()) { // Log.d(TAG, "moveToNearbyVideo: between video"); if (listener != null) listener.onVideoStart(mValue.getStringTimeInSecond(), mValue.getTimeInMicros()); return; } if (vo.getStartTime() > mValue.getTimeInMicros()&&isCurrentDay(mValue,vo.getStartTA())) { value = vo.getStartTime(); break; } } // Log.d(TAG, "moveToNearbyVideo: " + value); if (value != 0) { moveToValue(value); } else { if (listener != null) listener.onNoneVideo(mValue.getStringTimeInSecond(), mValue.getTimeInMicros()); } } private float getMaxAbs(float moveOneX, float moveTwoX) { return Math.abs(moveOneX) > Math.abs(moveTwoX) ? Math.abs(moveOneX) : Math.abs(moveTwoX); } public void setOnPlaybackViewListener(PlaybackViewListener listener) { this.listener = listener; listener.onValueChanged(mValue.getStringTimeInSecond(), mValue.getTimeInMicros()); } private PlaybackViewListener listener; public interface PlaybackViewListener { void onValueChanged(String timeInMillis, long timeInMicros); void onVideoStart(String timeInMillis, long timeInMicros); void onNoneVideo(String timeInMillis, long timeInMicros); } public static class TimeAlgorithm { private long time;//microsecond 微秒 public static final int MODE_HOUR = 2; public static final int MODE_TEN_MINUTE = 1; public static final int MODE_TWO_MINUTE = 0; public TimeAlgorithm(long micros) { this.time = micros; } public void setTimeInMillis(long millis) { time = millis * 1000; } public String getStringTimeInSecond() { SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); Date date = new Date(time / 1000); return sdf.format(date); } public String getStringTimeInMinute() { SimpleDateFormat sdf = new SimpleDateFormat("HH:mm"); Date date = new Date(time / 1000); return sdf.format(date); } public boolean isTwentyMinuteMultiple() { Date date = new Date(time / 1000); Calendar calendarObj = Calendar.getInstance(); calendarObj.setTime(date); int m = calendarObj.get(Calendar.MINUTE); int s = calendarObj.get(Calendar.SECOND); return (m * 60 + s) % 1200 == 0; } public long getCurrentMaxTimeInMillis() { Date date = new Date(time / 1000); Calendar calendarObj = Calendar.getInstance(); calendarObj.setTime(date); calendarObj.set(Calendar.HOUR_OF_DAY, 24); calendarObj.set(Calendar.MINUTE, 0); calendarObj.set(Calendar.SECOND, 0); calendarObj.set(Calendar.MILLISECOND, 0); // Log.d(TAG, "getCurrentMaxTimeInMillis: " + (calendarObj.getTimeInMillis() - 1000)); return calendarObj.getTimeInMillis() - 1000; } public long getCurrentMinTimeInMillis() { Date date = new Date(time / 1000); Calendar calendarObj = Calendar.getInstance(); calendarObj.setTime(date); calendarObj.set(Calendar.HOUR_OF_DAY, 0); calendarObj.set(Calendar.MINUTE, 0); calendarObj.set(Calendar.SECOND, 0); calendarObj.set(Calendar.MILLISECOND, 0); // Log.d(TAG, "getCurrentMinTimeInMillis: " + calendarObj.getTimeInMillis()); return calendarObj.getTimeInMillis(); } public boolean isTwoHourMultiple() { Date date = new Date(time / 1000); Calendar calendarObj = Calendar.getInstance(); calendarObj.setTime(date); int h = calendarObj.get(Calendar.HOUR); int m = calendarObj.get(Calendar.MINUTE); int s = calendarObj.get(Calendar.SECOND); return (h * 60 * 60 + m * 60 + s) % (2 * 60 * 60) == 0; } public int getScaleMode() { Date date = new Date(time / 1000); Calendar calendarObj = Calendar.getInstance(); calendarObj.setTime(date); int h = calendarObj.get(Calendar.HOUR_OF_DAY); int m = calendarObj.get(Calendar.MINUTE); int s = calendarObj.get(Calendar.SECOND); int mode = -1; if ((h * 60 * 60 + 60 * m + s) % 3600 == 0) { mode = MODE_HOUR; } else if ((60 * m + s) % 600 == 0) { mode = MODE_TEN_MINUTE; } else if ((60 * m + s) % 120 == 0) { mode = MODE_TWO_MINUTE; } return mode; } // 加上或减去_sec秒 public TimeAlgorithm addOrSub(int _sec) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = new Date(time / 1000); Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.add(Calendar.SECOND, _sec); SimpleDateFormat sdf2 = new SimpleDateFormat("HH:mm:ss"); TimeAlgorithm mt = new TimeAlgorithm(calendar.getTimeInMillis() * 1000); return mt; } public long getTimeInMicros() { return time; } public long getTimeInSecond() { return time / (1000 * 1000); } public long getTimeInMillis() { return time / 1000; } public int mod(int _timeInterval) { Date date = new Date(time / 1000); Calendar calendarObj = Calendar.getInstance(Locale.CHINA); calendarObj.setTime(date); int m = calendarObj.get(Calendar.MINUTE); int s = calendarObj.get(Calendar.SECOND); return (60 * m + s) % _timeInterval; } } public static class PlaybackVo implements Serializable { private long startTime; private long endTime; private long size; private byte type; private TimeAlgorithm startTA; private TimeAlgorithm endTA; public PlaybackVo(long startTime, long endTime, long size, byte type) { this.startTime = startTime; this.endTime = endTime; this.size = size; this.type = type; this.startTA = new TimeAlgorithm(startTime); this.endTA = new TimeAlgorithm(endTime); } public long getStartTime() { return startTime; } public long getEndTime() { return endTime; } public long getSize() { return size; } public void setSize(long size) { this.size = size; } public byte getType() { return type; } public void setType(byte type) { this.type = type; } public TimeAlgorithm getStartTA() { return startTA; } public TimeAlgorithm getEndTA() { return endTA; } } }