From 5dd9798ccdaa67e2bf1e0479f932ba0513e7bc40 Mon Sep 17 00:00:00 2001 From: DreamDSTR <> Date: Tue, 28 Jun 2022 17:20:34 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=80=E5=A7=8B=E6=92=AD=E6=94=BE=E7=95=8C?= =?UTF-8?q?=E9=9D=A2=E7=9B=B8=E5=85=B3UI=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../osc/picasso/RoundTransformation.java | 69 ++- .../osc/player/controller/BaseController.java | 437 ++++++++++++++++++ .../osc/player/controller/VodController.java | 225 +++++++++ .../tvbox/osc/ui/activity/PlayActivity.java | 57 +-- .../tvbox/osc/ui/fragment/UserFragment.java | 18 +- .../shape_player_control_vod_seek.xml | 22 + .../shape_player_control_vod_seek_thumb.xml | 7 + ...e_player_control_vod_seek_thumb_normal.xml | 8 + ...pe_player_control_vod_seek_thumb_press.xml | 8 + ...m_name.xml => shape_thumb_bottom_name.xml} | 0 .../res/layout/activity_projection_play.xml | 12 - app/src/main/res/layout/item_grid.xml | 4 +- app/src/main/res/layout/item_search.xml | 2 +- app/src/main/res/layout/item_user_hot_vod.xml | 6 +- .../res/layout/loadsir_loading_layout.xml | 4 +- .../res/layout/player_vod_control_view.xml | 322 +++++++++++++ 16 files changed, 1127 insertions(+), 74 deletions(-) create mode 100644 app/src/main/java/com/github/tvbox/osc/player/controller/BaseController.java create mode 100644 app/src/main/java/com/github/tvbox/osc/player/controller/VodController.java create mode 100644 app/src/main/res/drawable/shape_player_control_vod_seek.xml create mode 100644 app/src/main/res/drawable/shape_player_control_vod_seek_thumb.xml create mode 100644 app/src/main/res/drawable/shape_player_control_vod_seek_thumb_normal.xml create mode 100644 app/src/main/res/drawable/shape_player_control_vod_seek_thumb_press.xml rename app/src/main/res/drawable/{shape_thumb_buttom_name.xml => shape_thumb_bottom_name.xml} (100%) delete mode 100644 app/src/main/res/layout/activity_projection_play.xml create mode 100644 app/src/main/res/layout/player_vod_control_view.xml diff --git a/app/src/main/java/com/github/tvbox/osc/picasso/RoundTransformation.java b/app/src/main/java/com/github/tvbox/osc/picasso/RoundTransformation.java index 6527cd12..6293ed75 100644 --- a/app/src/main/java/com/github/tvbox/osc/picasso/RoundTransformation.java +++ b/app/src/main/java/com/github/tvbox/osc/picasso/RoundTransformation.java @@ -6,6 +6,7 @@ import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PaintFlagsDrawFilter; +import android.graphics.Path; import android.graphics.RectF; import android.graphics.Shader; @@ -25,7 +26,7 @@ import java.lang.annotation.Target; * @since 2020/12/22 */ public class RoundTransformation implements Transformation { - private int viewWidth, viewHeight; + private int viewWidth, viewHeight, bottomShapeHeight = 0; @RoundType private int mRoundType = RoundType.NONE; private int diameter; @@ -48,6 +49,11 @@ public class RoundTransformation implements Transformation { return this; } + public RoundTransformation bottomShapeHeight(int shapeHeight) { + this.bottomShapeHeight = shapeHeight; + return this; + } + public RoundTransformation roundRadius(int radius, @RoundType int mRoundType) { this.radius = radius; this.diameter = radius * 2; @@ -92,6 +98,63 @@ public class RoundTransformation implements Transformation { return bitmap; } + static Path RoundedRect(float left, float top, float right, float bottom, float rx, float ry, boolean tl, boolean tr, boolean br, boolean bl) { + Path path = new Path(); + if (rx < 0) rx = 0; + if (ry < 0) ry = 0; + float width = right - left; + float height = bottom - top; + if (rx > width / 2) rx = width / 2; + if (ry > height / 2) ry = height / 2; + float widthMinusCorners = (width - (2 * rx)); + float heightMinusCorners = (height - (2 * ry)); + + path.moveTo(right, top + ry); + if (tr) + path.rQuadTo(0, -ry, -rx, -ry);//top-right corner + else { + path.rLineTo(0, -ry); + path.rLineTo(-rx, 0); + } + path.rLineTo(-widthMinusCorners, 0); + if (tl) + path.rQuadTo(-rx, 0, -rx, ry); //top-left corner + else { + path.rLineTo(-rx, 0); + path.rLineTo(0, ry); + } + path.rLineTo(0, heightMinusCorners); + + if (bl) + path.rQuadTo(0, ry, rx, ry);//bottom-left corner + else { + path.rLineTo(0, ry); + path.rLineTo(rx, 0); + } + + path.rLineTo(widthMinusCorners, 0); + if (br) + path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner + else { + path.rLineTo(rx, 0); + path.rLineTo(0, -ry); + } + + path.rLineTo(0, -heightMinusCorners); + + path.close();//Given close, last lineto can be removed. + + return path; + } + + private void drawBottomLabel(Canvas mCanvas, Paint mPaint, float left, float top, float right, float bottom) { + if (bottomShapeHeight <= 0) + return; + mPaint.setShader(null); + mPaint.setColor(0x99000000); + mCanvas.drawPath(RoundedRect(left, bottom - bottomShapeHeight * 2, right, bottom, radius, radius, false, false, true, true), mPaint); + } + private void drawRoundRect(Canvas mCanvas, Paint mPaint, float width, float height) { switch (mRoundType) { case RoundType.NONE: @@ -116,18 +179,22 @@ public class RoundTransformation implements Transformation { case RoundType.ALL: if (viewWidth == width && viewHeight == height) { mCanvas.drawRoundRect(new RectF(0, 0, viewWidth, viewHeight), radius, radius, mPaint); + drawBottomLabel(mCanvas, mPaint, 0, 0, viewWidth, viewHeight); } else if (viewWidth == width && viewHeight != height) { float dis = (height - viewHeight) / 2f; if (isCenterCorp) { mCanvas.translate(0, -dis); mCanvas.drawRoundRect(new RectF(0, dis, viewWidth, viewHeight + dis), radius, radius, mPaint); + drawBottomLabel(mCanvas, mPaint, 0, dis, viewWidth, viewHeight + dis); } else { mCanvas.drawRoundRect(new RectF(0, 0, viewWidth, viewHeight), radius, radius, mPaint); + drawBottomLabel(mCanvas, mPaint, 0, 0, viewWidth, viewHeight); } } else { float dis = (width - viewWidth) / 2f; mCanvas.translate(-dis, 0); mCanvas.drawRoundRect(new RectF(dis, 0, viewWidth + dis, viewHeight), radius, radius, mPaint); + drawBottomLabel(mCanvas, mPaint, dis, 0, viewWidth + dis, viewHeight); } break; case RoundType.TOP: diff --git a/app/src/main/java/com/github/tvbox/osc/player/controller/BaseController.java b/app/src/main/java/com/github/tvbox/osc/player/controller/BaseController.java new file mode 100644 index 00000000..0c422dce --- /dev/null +++ b/app/src/main/java/com/github/tvbox/osc/player/controller/BaseController.java @@ -0,0 +1,437 @@ +package com.github.tvbox.osc.player.controller; + +import android.app.Activity; +import android.content.Context; +import android.media.AudioManager; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.view.GestureDetector; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ProgressBar; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.Map; + +import xyz.doikki.videoplayer.controller.BaseVideoController; +import xyz.doikki.videoplayer.controller.IControlComponent; +import xyz.doikki.videoplayer.controller.IGestureComponent; +import xyz.doikki.videoplayer.player.VideoView; +import xyz.doikki.videoplayer.util.PlayerUtils; + +public abstract class BaseController extends BaseVideoController implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener, View.OnTouchListener { + private GestureDetector mGestureDetector; + private AudioManager mAudioManager; + private boolean mIsGestureEnabled = true; + private int mStreamVolume; + private float mBrightness; + private int mSeekPosition; + private boolean mFirstTouch; + private boolean mChangePosition; + private boolean mChangeBrightness; + private boolean mChangeVolume; + private boolean mCanChangePosition = true; + private boolean mEnableInNormal; + private boolean mCanSlide; + private int mCurPlayState; + + protected Handler mHandler; + + protected HandlerCallback mHandlerCallback; + + protected interface HandlerCallback { + void callback(Message msg); + } + + private boolean mIsDoubleTapTogglePlayEnabled = true; + + + public BaseController(@NonNull Context context) { + super(context); + mHandler = new Handler(new Handler.Callback() { + @Override + public boolean handleMessage(@NonNull Message msg) { + int what = msg.what; + switch (what) { + case 100: { // 亮度+音量调整 + mSlideInfo.setVisibility(VISIBLE); + mSlideInfo.setText(msg.obj.toString()); + break; + } + + case 101: { // 亮度+音量调整 关闭 + mSlideInfo.setVisibility(GONE); + break; + } + default: { + if (mHandlerCallback != null) + mHandlerCallback.callback(msg); + break; + } + } + return false; + } + }); + } + + public BaseController(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public BaseController(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + TextView mSlideInfo; + ProgressBar mLoading; + ViewGroup mPauseRoot; + TextView mPauseTime; + + @Override + protected void initView() { + super.initView(); + mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE); + mGestureDetector = new GestureDetector(getContext(), this); + setOnTouchListener(this); + mSlideInfo = findViewWithTag("vod_control_slide_info"); + mLoading = findViewWithTag("vod_control_loading"); + mPauseRoot = findViewWithTag("vod_control_pause"); + mPauseTime = findViewWithTag("vod_control_pause_t"); + } + + @Override + protected void setProgress(int duration, int position) { + super.setProgress(duration, position); + mPauseTime.setText(PlayerUtils.stringForTime(position) + " / " + PlayerUtils.stringForTime(duration)); + } + + @Override + protected void onPlayStateChanged(int playState) { + super.onPlayStateChanged(playState); + switch (playState) { + case VideoView.STATE_IDLE: + mLoading.setVisibility(GONE); + break; + case VideoView.STATE_PLAYING: + mPauseRoot.setVisibility(GONE); + mLoading.setVisibility(GONE); + break; + case VideoView.STATE_PAUSED: + mPauseRoot.setVisibility(VISIBLE); + mLoading.setVisibility(GONE); + break; + case VideoView.STATE_PREPARED: + case VideoView.STATE_ERROR: + case VideoView.STATE_BUFFERED: + mLoading.setVisibility(GONE); + break; + case VideoView.STATE_PREPARING: + case VideoView.STATE_BUFFERING: + mLoading.setVisibility(VISIBLE); + break; + case VideoView.STATE_PLAYBACK_COMPLETED: + mLoading.setVisibility(GONE); + mPauseRoot.setVisibility(GONE); + break; + } + } + + /** + * 设置是否可以滑动调节进度,默认可以 + */ + public void setCanChangePosition(boolean canChangePosition) { + mCanChangePosition = canChangePosition; + } + + /** + * 是否在竖屏模式下开始手势控制,默认关闭 + */ + public void setEnableInNormal(boolean enableInNormal) { + mEnableInNormal = enableInNormal; + } + + /** + * 是否开启手势控制,默认开启,关闭之后,手势调节进度,音量,亮度功能将关闭 + */ + public void setGestureEnabled(boolean gestureEnabled) { + mIsGestureEnabled = gestureEnabled; + } + + /** + * 是否开启双击播放/暂停,默认开启 + */ + public void setDoubleTapTogglePlayEnabled(boolean enabled) { + mIsDoubleTapTogglePlayEnabled = enabled; + } + + @Override + public void setPlayerState(int playerState) { + super.setPlayerState(playerState); + if (playerState == VideoView.PLAYER_NORMAL) { + mCanSlide = mEnableInNormal; + } else if (playerState == VideoView.PLAYER_FULL_SCREEN) { + mCanSlide = true; + } + } + + @Override + public void setPlayState(int playState) { + super.setPlayState(playState); + mCurPlayState = playState; + } + + protected boolean isInPlaybackState() { + return mControlWrapper != null + && mCurPlayState != VideoView.STATE_ERROR + && mCurPlayState != VideoView.STATE_IDLE + && mCurPlayState != VideoView.STATE_PREPARING + && mCurPlayState != VideoView.STATE_PREPARED + && mCurPlayState != VideoView.STATE_START_ABORT + && mCurPlayState != VideoView.STATE_PLAYBACK_COMPLETED; + } + + @Override + public boolean onTouch(View v, MotionEvent event) { + return mGestureDetector.onTouchEvent(event); + } + + /** + * 手指按下的瞬间 + */ + @Override + public boolean onDown(MotionEvent e) { + if (!isInPlaybackState() //不处于播放状态 + || !mIsGestureEnabled //关闭了手势 + || PlayerUtils.isEdge(getContext(), e)) //处于屏幕边沿 + return true; + mStreamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); + Activity activity = PlayerUtils.scanForActivity(getContext()); + if (activity == null) { + mBrightness = 0; + } else { + mBrightness = activity.getWindow().getAttributes().screenBrightness; + } + mFirstTouch = true; + mChangePosition = false; + mChangeBrightness = false; + mChangeVolume = false; + return true; + } + + /** + * 单击 + */ + @Override + public boolean onSingleTapConfirmed(MotionEvent e) { + if (isInPlaybackState()) { + mControlWrapper.toggleShowState(); + } + return true; + } + + /** + * 双击 + */ + @Override + public boolean onDoubleTap(MotionEvent e) { + if (mIsDoubleTapTogglePlayEnabled && !isLocked() && isInPlaybackState()) togglePlay(); + return true; + } + + /** + * 在屏幕上滑动 + */ + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + if (!isInPlaybackState() //不处于播放状态 + || !mIsGestureEnabled //关闭了手势 + || !mCanSlide //关闭了滑动手势 + || isLocked() //锁住了屏幕 + || PlayerUtils.isEdge(getContext(), e1)) //处于屏幕边沿 + return true; + float deltaX = e1.getX() - e2.getX(); + float deltaY = e1.getY() - e2.getY(); + if (mFirstTouch) { + mChangePosition = Math.abs(distanceX) >= Math.abs(distanceY); + if (!mChangePosition) { + //半屏宽度 + int halfScreen = PlayerUtils.getScreenWidth(getContext(), true) / 2; + if (e2.getX() > halfScreen) { + mChangeVolume = true; + } else { + mChangeBrightness = true; + } + } + + if (mChangePosition) { + //根据用户设置是否可以滑动调节进度来决定最终是否可以滑动调节进度 + mChangePosition = mCanChangePosition; + } + + if (mChangePosition || mChangeBrightness || mChangeVolume) { + for (Map.Entry next : mControlComponents.entrySet()) { + IControlComponent component = next.getKey(); + if (component instanceof IGestureComponent) { + ((IGestureComponent) component).onStartSlide(); + } + } + } + mFirstTouch = false; + } + if (mChangePosition) { + slideToChangePosition(deltaX); + } else if (mChangeBrightness) { + slideToChangeBrightness(deltaY); + } else if (mChangeVolume) { + slideToChangeVolume(deltaY); + } + return true; + } + + protected void slideToChangePosition(float deltaX) { + deltaX = -deltaX; + int width = getMeasuredWidth(); + int duration = (int) mControlWrapper.getDuration(); + int currentPosition = (int) mControlWrapper.getCurrentPosition(); + int position = (int) (deltaX / width * 120000 + currentPosition); + if (position > duration) position = duration; + if (position < 0) position = 0; + for (Map.Entry next : mControlComponents.entrySet()) { + IControlComponent component = next.getKey(); + if (component instanceof IGestureComponent) { + ((IGestureComponent) component).onPositionChange(position, currentPosition, duration); + } + } + updateSeekUI(currentPosition, position, duration); + mSeekPosition = position; + } + + protected void updateSeekUI(int curr, int seekTo, int duration) { + + } + + protected void slideToChangeBrightness(float deltaY) { + Activity activity = PlayerUtils.scanForActivity(getContext()); + if (activity == null) return; + Window window = activity.getWindow(); + WindowManager.LayoutParams attributes = window.getAttributes(); + int height = getMeasuredHeight(); + if (mBrightness == -1.0f) mBrightness = 0.5f; + float brightness = deltaY * 2 / height * 1.0f + mBrightness; + if (brightness < 0) { + brightness = 0f; + } + if (brightness > 1.0f) brightness = 1.0f; + int percent = (int) (brightness * 100); + attributes.screenBrightness = brightness; + window.setAttributes(attributes); + for (Map.Entry next : mControlComponents.entrySet()) { + IControlComponent component = next.getKey(); + if (component instanceof IGestureComponent) { + ((IGestureComponent) component).onBrightnessChange(percent); + } + } + Message msg = Message.obtain(); + msg.what = 100; + msg.obj = "亮度" + percent + "%"; + mHandler.sendMessage(msg); + mHandler.removeMessages(101); + mHandler.sendEmptyMessageDelayed(101, 1000); + } + + protected void slideToChangeVolume(float deltaY) { + int streamMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + int height = getMeasuredHeight(); + float deltaV = deltaY * 2 / height * streamMaxVolume; + float index = mStreamVolume + deltaV; + if (index > streamMaxVolume) index = streamMaxVolume; + if (index < 0) index = 0; + int percent = (int) (index / streamMaxVolume * 100); + mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, (int) index, 0); + for (Map.Entry next : mControlComponents.entrySet()) { + IControlComponent component = next.getKey(); + if (component instanceof IGestureComponent) { + ((IGestureComponent) component).onVolumeChange(percent); + } + } + Message msg = Message.obtain(); + msg.what = 100; + msg.obj = "音量" + percent + "%"; + mHandler.sendMessage(msg); + mHandler.removeMessages(101); + mHandler.sendEmptyMessageDelayed(101, 1000); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + //滑动结束时事件处理 + if (!mGestureDetector.onTouchEvent(event)) { + int action = event.getAction(); + switch (action) { + case MotionEvent.ACTION_UP: + stopSlide(); + if (mSeekPosition > 0) { + mControlWrapper.seekTo(mSeekPosition); + mSeekPosition = 0; + } + break; + case MotionEvent.ACTION_CANCEL: + stopSlide(); + mSeekPosition = 0; + break; + } + } + return super.onTouchEvent(event); + } + + private void stopSlide() { + for (Map.Entry next : mControlComponents.entrySet()) { + IControlComponent component = next.getKey(); + if (component instanceof IGestureComponent) { + ((IGestureComponent) component).onStopSlide(); + } + } + } + + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + return false; + } + + @Override + public void onLongPress(MotionEvent e) { + + } + + @Override + public void onShowPress(MotionEvent e) { + + } + + @Override + public boolean onDoubleTapEvent(MotionEvent e) { + return false; + } + + + @Override + public boolean onSingleTapUp(MotionEvent e) { + return false; + } + + public boolean onKeyEvent(KeyEvent event) { + if (!isInPlaybackState() //不处于播放状态 + || isLocked() //锁住了屏幕 + ) + return false; + return false; + } +} diff --git a/app/src/main/java/com/github/tvbox/osc/player/controller/VodController.java b/app/src/main/java/com/github/tvbox/osc/player/controller/VodController.java new file mode 100644 index 00000000..dc866a18 --- /dev/null +++ b/app/src/main/java/com/github/tvbox/osc/player/controller/VodController.java @@ -0,0 +1,225 @@ +package com.github.tvbox.osc.player.controller; + +import android.content.Context; +import android.os.Message; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.SeekBar; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.github.tvbox.osc.R; + +import org.jetbrains.annotations.NotNull; + +import xyz.doikki.videoplayer.player.VideoView; +import xyz.doikki.videoplayer.util.PlayerUtils; + +import static xyz.doikki.videoplayer.util.PlayerUtils.stringForTime; + +public class VodController extends BaseController { + public VodController(@NonNull @NotNull Context context) { + super(context); + mHandlerCallback = new HandlerCallback() { + @Override + public void callback(Message msg) { + switch (msg.what) { + case 1000: { // seek 刷新 + mProgressRoot.setVisibility(VISIBLE); + break; + } + case 1001: { // seek 关闭 + mProgressRoot.setVisibility(GONE); + break; + } + case 1002: { // 显示底部菜单 + mBottomRoot.setVisibility(VISIBLE); + break; + } + case 1003: { // 隐藏底部菜单 + mBottomRoot.setVisibility(GONE); + break; + } + } + } + }; + } + + SeekBar mSeekBar; + TextView mCurrentTime; + TextView mTotalTime; + boolean mIsDragging; + LinearLayout mProgressRoot; + TextView mProgressText; + ImageView mProgressIcon; + LinearLayout mBottomRoot; + + @Override + protected void initView() { + super.initView(); + mCurrentTime = findViewById(R.id.curr_time); + mTotalTime = findViewById(R.id.total_time); + mSeekBar = findViewById(R.id.seekBar); + mProgressRoot = findViewById(R.id.tv_progress_container); + mProgressIcon = findViewById(R.id.tv_progress_icon); + mProgressText = findViewById(R.id.tv_progress_text); + mBottomRoot = findViewById(R.id.bottom_container); + + mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + int lastProgress = 0; + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (!fromUser) { + return; + } + + long duration = mControlWrapper.getDuration(); + long newPosition = (duration * progress) / seekBar.getMax(); + if (mCurrentTime != null) + mCurrentTime.setText(stringForTime((int) newPosition)); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + mIsDragging = true; + mControlWrapper.stopProgress(); + mControlWrapper.stopFadeOut(); + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + long duration = mControlWrapper.getDuration(); + long newPosition = (duration * seekBar.getProgress()) / seekBar.getMax(); + mControlWrapper.seekTo((int) newPosition); + mIsDragging = false; + mControlWrapper.startProgress(); + mControlWrapper.startFadeOut(); + } + }); + } + + @Override + protected int getLayoutId() { + return R.layout.player_vod_control_view; + } + + @Override + protected void setProgress(int duration, int position) { + if (mIsDragging) { + return; + } + super.setProgress(duration, position); + mCurrentTime.setText(PlayerUtils.stringForTime(position)); + mTotalTime.setText(PlayerUtils.stringForTime(duration)); + if (duration > 0) { + mSeekBar.setEnabled(true); + int pos = (int) (position * 1.0 / duration * mSeekBar.getMax()); + mSeekBar.setProgress(pos); + } else { + mSeekBar.setEnabled(false); + } + int percent = mControlWrapper.getBufferedPercentage(); + if (percent >= 95) { + mSeekBar.setSecondaryProgress(mSeekBar.getMax()); + } else { + mSeekBar.setSecondaryProgress(percent * 10); + } + } + + private boolean simSlideStart = false; + private int simSeekPosition = 0; + private long simSlideOffset = 0; + + public void tvSlideStop() { + if (!simSlideStart) + return; + mControlWrapper.seekTo(simSeekPosition); + if (!mControlWrapper.isPlaying()) + mControlWrapper.start(); + simSlideStart = false; + simSeekPosition = 0; + simSlideOffset = 0; + } + + public void tvSlideStart(int dir) { + int duration = (int) mControlWrapper.getDuration(); + if (duration <= 0) + return; + if (!simSlideStart) { + simSlideStart = true; + } + // 每次10秒 + simSlideOffset += (10000.0f * dir); + int currentPosition = (int) mControlWrapper.getCurrentPosition(); + int position = (int) (simSlideOffset + currentPosition); + if (position > duration) position = duration; + if (position < 0) position = 0; + updateSeekUI(currentPosition, position, duration); + simSeekPosition = position; + } + + @Override + protected void updateSeekUI(int curr, int seekTo, int duration) { + super.updateSeekUI(curr, seekTo, duration); + if (seekTo > curr) { + mProgressIcon.setImageResource(R.drawable.icon_pre); + } else { + mProgressIcon.setImageResource(R.drawable.icon_back); + } + mProgressText.setText(PlayerUtils.stringForTime(seekTo) + " / " + PlayerUtils.stringForTime(duration)); + mHandler.sendEmptyMessage(1000); + mHandler.removeMessages(1001); + mHandler.sendEmptyMessageDelayed(1001, 1000); + } + + @Override + protected void onPlayStateChanged(int playState) { + super.onPlayStateChanged(playState); + switch (playState) { + case VideoView.STATE_PLAYING: + startProgress(); + break; + } + } + + @Override + public boolean onKeyEvent(KeyEvent event) { + if (super.onKeyEvent(event)) { + return true; + } + if (isInPlaybackState()) { + int keyCode = event.getKeyCode(); + int action = event.getAction(); + if (action == KeyEvent.ACTION_DOWN) { + if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT || keyCode == KeyEvent.KEYCODE_DPAD_LEFT) { + tvSlideStart(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT ? 1 : -1); + } else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) { + togglePlay(); + } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { + } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { + } + } else if (action == KeyEvent.ACTION_UP) { + if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT || keyCode == KeyEvent.KEYCODE_DPAD_LEFT) { + tvSlideStop(); + } + } + return super.dispatchKeyEvent(event); + } + return false; + } + + @Override + public boolean onSingleTapConfirmed(MotionEvent e) { + if (isInPlaybackState()) { + mHandler.sendEmptyMessage(1003); + mHandler.removeMessages(1004); + mHandler.sendEmptyMessageDelayed(1004, 3000); + return true; + } + return super.onSingleTapConfirmed(e); + } +} diff --git a/app/src/main/java/com/github/tvbox/osc/ui/activity/PlayActivity.java b/app/src/main/java/com/github/tvbox/osc/ui/activity/PlayActivity.java index fd25f50a..dbf265b6 100644 --- a/app/src/main/java/com/github/tvbox/osc/ui/activity/PlayActivity.java +++ b/app/src/main/java/com/github/tvbox/osc/ui/activity/PlayActivity.java @@ -13,14 +13,12 @@ import com.github.tvbox.osc.base.BaseActivity; import com.github.tvbox.osc.bean.VodInfo; import com.github.tvbox.osc.cache.CacheManager; import com.github.tvbox.osc.event.RefreshEvent; -import com.github.tvbox.osc.player.controller.BoxVideoController; import com.github.tvbox.osc.player.controller.BoxVodControlView; +import com.github.tvbox.osc.player.controller.VodController; import com.github.tvbox.osc.ui.dialog.ParseDialog; -import com.github.tvbox.osc.util.HawkConfig; import com.github.tvbox.osc.util.MD5; import com.github.tvbox.osc.util.PlayerHelper; import com.github.tvbox.osc.viewmodel.SourceViewModel; -import com.orhanobut.hawk.Hawk; import org.greenrobot.eventbus.EventBus; import org.json.JSONObject; @@ -38,7 +36,7 @@ import xyz.doikki.videoplayer.player.VideoView; */ public class PlayActivity extends BaseActivity { private VideoView mVideoView; - private BoxVideoController controller; + private VodController controller; private SourceViewModel sourceViewModel; @Override @@ -86,22 +84,7 @@ public class PlayActivity extends BaseActivity { } }); - controller = new BoxVideoController(this); - - controller.addControlComponent(new GestureView(this)); - BoxVodControlView boxVodControlView = new BoxVodControlView(this); - controller.addControlComponent(boxVodControlView); - boxVodControlView.setVodControlListener(new BoxVodControlView.BoxVodControlListener() { - @Override - public void playNext() { - PlayActivity.this.playNext(); - } - - @Override - public void playPre() { - PlayActivity.this.playPrevious(); - } - }); + controller = new VodController(this); controller.setCanChangePosition(true); controller.setEnableInNormal(true); controller.setGestureEnabled(true); @@ -174,37 +157,17 @@ public class PlayActivity extends BaseActivity { @Override public void onBackPressed() { - if (controller.isBoxTVBottomShow()) { - controller.boxTVBottomToggle(); - } else { - super.onBackPressed(); + if (controller.onBackPressed()) { + return; } + super.onBackPressed(); } @Override public boolean dispatchKeyEvent(KeyEvent event) { - int keyCode = event.getKeyCode(); - int action = event.getAction(); - - if (controller.isBoxTVBottomShow()) { - return super.dispatchKeyEvent(event); - } - - if (action == KeyEvent.ACTION_DOWN) { - if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT || keyCode == KeyEvent.KEYCODE_DPAD_LEFT) { - controller.boxTVSlideStart(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT ? 1 : -1); - } else if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_NUMPAD_ENTER || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || (Hawk.get(HawkConfig.DEBUG_OPEN, false) && keyCode == KeyEvent.KEYCODE_0)) { - controller.boxTVTogglePlay(); - } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { -// playPrevious(); - controller.boxTVBottomToggle(); - } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { -// playNext(); - controller.boxTVBottomToggle(); - } - } else if (action == KeyEvent.ACTION_UP) { - if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT || keyCode == KeyEvent.KEYCODE_DPAD_LEFT) { - controller.boxTVSlideStop(); + if (event != null) { + if (controller.onKeyEvent(event)) { + return true; } } return super.dispatchKeyEvent(event); @@ -288,7 +251,7 @@ public class PlayActivity extends BaseActivity { public void play() { VodInfo.VodSeries vs = mVodInfo.seriesMap.get(mVodInfo.playFlag).get(mVodInfo.playIndex); EventBus.getDefault().post(new RefreshEvent(RefreshEvent.TYPE_REFRESH, mVodInfo.playIndex)); - controller.boxTVRefreshInfo(mVodInfo.name + " " + vs.name + (Hawk.get(HawkConfig.DEBUG_OPEN, false) ? vs.url : "")); + // controller.boxTVRefreshInfo(mVodInfo.name + " " + vs.name + (Hawk.get(HawkConfig.DEBUG_OPEN, false) ? vs.url : "")); tryDismissParse(); diff --git a/app/src/main/java/com/github/tvbox/osc/ui/fragment/UserFragment.java b/app/src/main/java/com/github/tvbox/osc/ui/fragment/UserFragment.java index 8512b19b..8a061cee 100644 --- a/app/src/main/java/com/github/tvbox/osc/ui/fragment/UserFragment.java +++ b/app/src/main/java/com/github/tvbox/osc/ui/fragment/UserFragment.java @@ -32,6 +32,7 @@ import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import java.util.ArrayList; +import java.util.Calendar; /** * @author pj567 @@ -109,20 +110,25 @@ public class UserFragment extends BaseLazyFragment implements View.OnClickListen private void initHomeHotVod(HomeHotVodAdapter adapter) { try { - long time = Hawk.get("douban_hot_date", 0L); - if (System.currentTimeMillis() - time < 6 * 60 * 60 * 1000) { - String json = Hawk.get("douboan_hot", ""); + Calendar cal = Calendar.getInstance(); + int year = cal.get(Calendar.YEAR); + int month = cal.get(Calendar.MONTH) + 1; + int day = cal.get(Calendar.DATE); + String today = String.format("%d%d%d", year, month, day); + String requestDay = Hawk.get("home_hot_day", ""); + if (requestDay.equals(today)) { + String json = Hawk.get("home_hot", ""); if (!json.isEmpty()) { adapter.setNewData(loadHots(json)); return; } } - OkGo.get("https://movie.douban.com/j/new_search_subjects?sort=R&range=0,10&tags=&playable=1&start=0").execute(new AbsCallback() { + OkGo.get("https://movie.douban.com/j/new_search_subjects?sort=U&range=0,10&tags=&playable=1&start=0&year_range=" + year + "," + year).execute(new AbsCallback() { @Override public void onSuccess(Response response) { String netJson = response.body(); - Hawk.put("douban_hot_date", System.currentTimeMillis()); - Hawk.put("douboan_hot", netJson); + Hawk.put("home_hot_day", today); + Hawk.put("home_hot", netJson); mActivity.runOnUiThread(new Runnable() { @Override public void run() { diff --git a/app/src/main/res/drawable/shape_player_control_vod_seek.xml b/app/src/main/res/drawable/shape_player_control_vod_seek.xml new file mode 100644 index 00000000..cd83bbdb --- /dev/null +++ b/app/src/main/res/drawable/shape_player_control_vod_seek.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/shape_player_control_vod_seek_thumb.xml b/app/src/main/res/drawable/shape_player_control_vod_seek_thumb.xml new file mode 100644 index 00000000..061a3c32 --- /dev/null +++ b/app/src/main/res/drawable/shape_player_control_vod_seek_thumb.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/app/src/main/res/drawable/shape_player_control_vod_seek_thumb_normal.xml b/app/src/main/res/drawable/shape_player_control_vod_seek_thumb_normal.xml new file mode 100644 index 00000000..175429f1 --- /dev/null +++ b/app/src/main/res/drawable/shape_player_control_vod_seek_thumb_normal.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/app/src/main/res/drawable/shape_player_control_vod_seek_thumb_press.xml b/app/src/main/res/drawable/shape_player_control_vod_seek_thumb_press.xml new file mode 100644 index 00000000..a02a22e0 --- /dev/null +++ b/app/src/main/res/drawable/shape_player_control_vod_seek_thumb_press.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/app/src/main/res/drawable/shape_thumb_buttom_name.xml b/app/src/main/res/drawable/shape_thumb_bottom_name.xml similarity index 100% rename from app/src/main/res/drawable/shape_thumb_buttom_name.xml rename to app/src/main/res/drawable/shape_thumb_bottom_name.xml diff --git a/app/src/main/res/layout/activity_projection_play.xml b/app/src/main/res/layout/activity_projection_play.xml deleted file mode 100644 index dc0cc1ae..00000000 --- a/app/src/main/res/layout/activity_projection_play.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_grid.xml b/app/src/main/res/layout/item_grid.xml index 6e527184..0f5defa3 100644 --- a/app/src/main/res/layout/item_grid.xml +++ b/app/src/main/res/layout/item_grid.xml @@ -101,7 +101,7 @@ android:id="@+id/tvName" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@drawable/shape_thumb_buttom_name" + android:background="@drawable/shape_thumb_bottom_name" android:ellipsize="marquee" android:marqueeRepeatLimit="marquee_forever" android:padding="@dimen/vs_5" @@ -113,7 +113,7 @@ android:id="@+id/tvActor" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@drawable/shape_thumb_buttom_name" + android:background="@drawable/shape_thumb_bottom_name" android:ellipsize="end" android:gravity="top" android:padding="@dimen/vs_5" diff --git a/app/src/main/res/layout/item_search.xml b/app/src/main/res/layout/item_search.xml index cddf41a3..7c069ba6 100644 --- a/app/src/main/res/layout/item_search.xml +++ b/app/src/main/res/layout/item_search.xml @@ -71,7 +71,7 @@ android:id="@+id/tvName" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@drawable/shape_thumb_buttom_name" + android:background="@drawable/shape_thumb_bottom_name" android:ellipsize="marquee" android:marqueeRepeatLimit="marquee_forever" android:padding="@dimen/vs_5" diff --git a/app/src/main/res/layout/item_user_hot_vod.xml b/app/src/main/res/layout/item_user_hot_vod.xml index 5d0bc213..90cbad05 100644 --- a/app/src/main/res/layout/item_user_hot_vod.xml +++ b/app/src/main/res/layout/item_user_hot_vod.xml @@ -38,7 +38,7 @@ android:paddingRight="@dimen/vs_5" android:singleLine="true" android:textColor="@android:color/white" - android:textSize="@dimen/ts_16" /> + android:textSize="@dimen/ts_20" /> @@ -54,13 +54,13 @@ android:id="@+id/tvName" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@drawable/shape_thumb_buttom_name" + android:background="@drawable/shape_thumb_bottom_name" android:ellipsize="marquee" android:marqueeRepeatLimit="marquee_forever" android:padding="@dimen/vs_5" android:singleLine="true" android:textColor="@android:color/white" - android:textSize="@dimen/ts_20" /> + android:textSize="@dimen/ts_22" /> \ No newline at end of file diff --git a/app/src/main/res/layout/loadsir_loading_layout.xml b/app/src/main/res/layout/loadsir_loading_layout.xml index 1f73c91c..886f95e4 100644 --- a/app/src/main/res/layout/loadsir_loading_layout.xml +++ b/app/src/main/res/layout/loadsir_loading_layout.xml @@ -4,8 +4,8 @@ android:layout_height="match_parent"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file