androidx版本首次提交
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
package com.yunbao.video.activity;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.RadioGroup;
|
||||
|
||||
import com.yunbao.common.Constants;
|
||||
import com.yunbao.common.activity.AbsActivity;
|
||||
import com.yunbao.common.adapter.ImChatFacePagerAdapter;
|
||||
import com.yunbao.common.interfaces.OnFaceClickListener;
|
||||
import com.yunbao.common.utils.ProcessResultUtil;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.bean.VideoCommentBean;
|
||||
import com.yunbao.video.dialog.VideoInputDialogFragment;
|
||||
import com.yunbao.video.views.VideoCommentViewHolder;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2019/3/11.
|
||||
*/
|
||||
|
||||
public abstract class AbsVideoCommentActivity extends AbsActivity implements View.OnClickListener, OnFaceClickListener {
|
||||
|
||||
protected ProcessResultUtil mProcessResultUtil;
|
||||
protected VideoCommentViewHolder mVideoCommentViewHolder;
|
||||
protected VideoInputDialogFragment mVideoInputDialogFragment;
|
||||
private View mFaceView;//表情面板
|
||||
private int mFaceHeight;//表情面板高度
|
||||
|
||||
@Override
|
||||
protected void main() {
|
||||
mProcessResultUtil = new ProcessResultUtil(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int i = v.getId();
|
||||
if (i == R.id.btn_send) {
|
||||
if (mVideoInputDialogFragment != null) {
|
||||
mVideoInputDialogFragment.sendComment();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 打开评论输入框
|
||||
*/
|
||||
public void openCommentInputWindow(boolean openFace, String videoId, String videoUid, VideoCommentBean bean) {
|
||||
if (mFaceView == null) {
|
||||
mFaceView = initFaceView();
|
||||
}
|
||||
VideoInputDialogFragment fragment = new VideoInputDialogFragment();
|
||||
fragment.setVideoInfo(videoId, videoUid);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putBoolean(Constants.VIDEO_FACE_OPEN, openFace);
|
||||
bundle.putInt(Constants.VIDEO_FACE_HEIGHT, mFaceHeight);
|
||||
bundle.putParcelable(Constants.VIDEO_COMMENT_BEAN, bean);
|
||||
fragment.setArguments(bundle);
|
||||
mVideoInputDialogFragment = fragment;
|
||||
fragment.show(getSupportFragmentManager(), "VideoInputDialogFragment");
|
||||
}
|
||||
|
||||
|
||||
public View getFaceView() {
|
||||
if (mFaceView == null) {
|
||||
mFaceView = initFaceView();
|
||||
}
|
||||
return mFaceView;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化表情控件
|
||||
*/
|
||||
private View initFaceView() {
|
||||
LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
View v = inflater.inflate(R.layout.view_chat_face, null);
|
||||
v.measure(0, 0);
|
||||
mFaceHeight = v.getMeasuredHeight();
|
||||
v.findViewById(R.id.btn_send).setOnClickListener(this);
|
||||
final RadioGroup radioGroup = (RadioGroup) v.findViewById(R.id.radio_group);
|
||||
ViewPager viewPager = (ViewPager) v.findViewById(R.id.viewPager);
|
||||
viewPager.setOffscreenPageLimit(10);
|
||||
ImChatFacePagerAdapter adapter = new ImChatFacePagerAdapter(mContext, this);
|
||||
viewPager.setAdapter(adapter);
|
||||
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
((RadioButton) radioGroup.getChildAt(position)).setChecked(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
for (int i = 0, pageCount = adapter.getCount(); i < pageCount; i++) {
|
||||
RadioButton radioButton = (RadioButton) inflater.inflate(R.layout.view_chat_indicator, radioGroup, false);
|
||||
radioButton.setId(i + 10000);
|
||||
if (i == 0) {
|
||||
radioButton.setChecked(true);
|
||||
}
|
||||
radioGroup.addView(radioButton);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示评论
|
||||
*/
|
||||
public void openCommentWindow(String videoId, String videoUid) {
|
||||
if (mVideoCommentViewHolder == null) {
|
||||
mVideoCommentViewHolder = new VideoCommentViewHolder(mContext, (ViewGroup) findViewById(R.id.root));
|
||||
mVideoCommentViewHolder.addToParent();
|
||||
}
|
||||
mVideoCommentViewHolder.setVideoInfo(videoId, videoUid);
|
||||
mVideoCommentViewHolder.showBottom();
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏评论
|
||||
*/
|
||||
public void hideCommentWindow(boolean commentSuccess) {
|
||||
if (mVideoCommentViewHolder != null) {
|
||||
mVideoCommentViewHolder.hideBottom();
|
||||
if (commentSuccess) {
|
||||
mVideoCommentViewHolder.needRefresh();
|
||||
}
|
||||
}
|
||||
mVideoInputDialogFragment = null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onFaceClick(String str, int faceImageRes) {
|
||||
if (mVideoInputDialogFragment != null) {
|
||||
mVideoInputDialogFragment.onFaceClick(str, faceImageRes);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFaceDeleteClick() {
|
||||
if (mVideoInputDialogFragment != null) {
|
||||
mVideoInputDialogFragment.onFaceDeleteClick();
|
||||
}
|
||||
}
|
||||
|
||||
public void release() {
|
||||
if (mVideoCommentViewHolder != null) {
|
||||
mVideoCommentViewHolder.release();
|
||||
}
|
||||
if (mProcessResultUtil != null) {
|
||||
mProcessResultUtil.release();
|
||||
}
|
||||
mVideoCommentViewHolder = null;
|
||||
mVideoInputDialogFragment = null;
|
||||
mProcessResultUtil = null;
|
||||
}
|
||||
|
||||
public void releaseVideoInputDialog() {
|
||||
mVideoInputDialogFragment = null;
|
||||
}
|
||||
|
||||
//获取位置
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
Constants.xIndex = (int) ev.getRawX();
|
||||
Constants.yindex = (int) ev.getRawY();
|
||||
}
|
||||
return super.dispatchTouchEvent(ev);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
package com.yunbao.video.activity;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Dialog;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.media.MediaMetadataRetriever;
|
||||
import android.text.TextUtils;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.yunbao.common.CommonAppConfig;
|
||||
import com.yunbao.common.HtmlConfig;
|
||||
import com.yunbao.common.bean.ConfigBean;
|
||||
import com.yunbao.common.http.HttpCallback;
|
||||
import com.yunbao.common.interfaces.CommonCallback;
|
||||
import com.yunbao.common.utils.DateFormatUtil;
|
||||
import com.yunbao.common.utils.DialogUitl;
|
||||
import com.yunbao.common.utils.DownloadUtil;
|
||||
import com.yunbao.common.utils.StringUtil;
|
||||
import com.yunbao.common.utils.ToastUtil;
|
||||
import com.yunbao.common.utils.WordUtil;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.bean.VideoBean;
|
||||
import com.yunbao.video.event.VideoDeleteEvent;
|
||||
import com.yunbao.video.event.VideoShareEvent;
|
||||
import com.yunbao.video.http.VideoHttpConsts;
|
||||
import com.yunbao.video.http.VideoHttpUtil;
|
||||
import com.yunbao.video.utils.VideoLocalUtil;
|
||||
import com.yunbao.video.utils.VideoStorge;
|
||||
import com.yunbao.video.views.VideoScrollViewHolder;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2019/2/28.
|
||||
*/
|
||||
|
||||
public abstract class AbsVideoPlayActivity extends AbsVideoCommentActivity {
|
||||
|
||||
protected VideoScrollViewHolder mVideoScrollViewHolder;
|
||||
private Dialog mDownloadVideoDialog;
|
||||
private ClipboardManager mClipboardManager;
|
||||
// private MobCallback mMobCallback;
|
||||
// private MobShareUtil mMobShareUtil;
|
||||
private DownloadUtil mDownloadUtil;
|
||||
private ConfigBean mConfigBean;
|
||||
private VideoBean mShareVideoBean;
|
||||
protected String mVideoKey;
|
||||
private boolean mPaused;
|
||||
|
||||
|
||||
@Override
|
||||
protected void main() {
|
||||
super.main();
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
CommonAppConfig.getInstance().getConfig(new CommonCallback<ConfigBean>() {
|
||||
@Override
|
||||
public void callback(ConfigBean bean) {
|
||||
mConfigBean = bean;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 复制视频链接
|
||||
*/
|
||||
public void copyLink(VideoBean videoBean) {
|
||||
if (videoBean == null) {
|
||||
return;
|
||||
}
|
||||
if (mClipboardManager == null) {
|
||||
mClipboardManager = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
}
|
||||
ClipData clipData = ClipData.newPlainText("text", videoBean.getHref());
|
||||
mClipboardManager.setPrimaryClip(clipData);
|
||||
ToastUtil.show(WordUtil.getString(R.string.copy_success));
|
||||
}
|
||||
|
||||
/**
|
||||
* 分享页面链接
|
||||
*/
|
||||
public void shareVideoPage(String type, VideoBean videoBean) {
|
||||
if (videoBean == null || mConfigBean == null) {
|
||||
return;
|
||||
}
|
||||
// if (mMobCallback == null) {
|
||||
// mMobCallback = new MobCallback() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(Object data) {
|
||||
// if (mShareVideoBean == null) {
|
||||
// return;
|
||||
// }
|
||||
// VideoHttpUtil.setVideoShare(mShareVideoBean.getId(), new HttpCallback() {
|
||||
// @Override
|
||||
// public void onSuccess(int code, String msg, String[] info) {
|
||||
// if (code == 0 && info.length > 0 && mShareVideoBean != null) {
|
||||
// JSONObject obj = JSON.parseObject(info[0]);
|
||||
// EventBus.getDefault().post(new VideoShareEvent(mShareVideoBean.getId(), obj.getString("shares")));
|
||||
// } else {
|
||||
// ToastUtil.show(msg);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onError() {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onCancel() {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFinish() {
|
||||
//
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
mShareVideoBean = videoBean;
|
||||
// ShareData data = new ShareData();
|
||||
// data.setTitle(mConfigBean.getVideoShareTitle());
|
||||
// data.setDes(mConfigBean.getVideoShareDes());
|
||||
// data.setImgUrl(videoBean.getThumbs());
|
||||
// String webUrl = HtmlConfig.SHARE_VIDEO + videoBean.getId();
|
||||
// data.setWebUrl(webUrl);
|
||||
// if (mMobShareUtil == null) {
|
||||
// mMobShareUtil = new MobShareUtil();
|
||||
// }
|
||||
// mMobShareUtil.execute(type, data, mMobCallback);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 下载视频
|
||||
*/
|
||||
public void downloadVideo(final VideoBean videoBean) {
|
||||
if (mProcessResultUtil == null || videoBean == null || TextUtils.isEmpty(videoBean.getHref())) {
|
||||
return;
|
||||
}
|
||||
mProcessResultUtil.requestPermissions(new String[]{
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
}, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mDownloadVideoDialog = DialogUitl.loadingDialog(mContext);
|
||||
mDownloadVideoDialog.show();
|
||||
if (mDownloadUtil == null) {
|
||||
mDownloadUtil = new DownloadUtil();
|
||||
}
|
||||
String fileName = "YB_VIDEO_" + videoBean.getTitle() + "_" + DateFormatUtil.getCurTimeString() + ".mp4";
|
||||
mDownloadUtil.download(videoBean.getTag(), CommonAppConfig.VIDEO_PATH, fileName, videoBean.getHref(), new DownloadUtil.Callback() {
|
||||
@Override
|
||||
public void onSuccess(File file) {
|
||||
ToastUtil.show(R.string.video_download_success);
|
||||
if (mDownloadVideoDialog != null && mDownloadVideoDialog.isShowing()) {
|
||||
mDownloadVideoDialog.dismiss();
|
||||
}
|
||||
mDownloadVideoDialog = null;
|
||||
String path = file.getAbsolutePath();
|
||||
try {
|
||||
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
|
||||
mmr.setDataSource(path);
|
||||
String d = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
|
||||
if (StringUtil.isInt(d)) {
|
||||
long duration = Long.parseLong(d);
|
||||
VideoLocalUtil.saveVideoInfo(mContext, path, duration);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgress(int progress) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
ToastUtil.show(R.string.video_download_failed);
|
||||
if (mDownloadVideoDialog != null && mDownloadVideoDialog.isShowing()) {
|
||||
mDownloadVideoDialog.dismiss();
|
||||
}
|
||||
mDownloadVideoDialog = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除视频
|
||||
*/
|
||||
public void deleteVideo(final VideoBean videoBean) {
|
||||
VideoHttpUtil.videoDelete(videoBean.getId(), new HttpCallback() {
|
||||
@Override
|
||||
public void onSuccess(int code, String msg, String[] info) {
|
||||
if (code == 0) {
|
||||
if (mVideoScrollViewHolder != null) {
|
||||
EventBus.getDefault().post(new VideoDeleteEvent(videoBean.getId()));
|
||||
mVideoScrollViewHolder.deleteVideo(videoBean);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public boolean isPaused() {
|
||||
return mPaused;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
mPaused = true;
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mPaused = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
super.release();
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.SET_VIDEO_SHARE);
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.VIDEO_DELETE);
|
||||
if (mDownloadVideoDialog != null && mDownloadVideoDialog.isShowing()) {
|
||||
mDownloadVideoDialog.dismiss();
|
||||
}
|
||||
if (mVideoScrollViewHolder != null) {
|
||||
mVideoScrollViewHolder.release();
|
||||
}
|
||||
// if (mMobShareUtil != null) {
|
||||
// mMobShareUtil.release();
|
||||
// }
|
||||
VideoStorge.getInstance().removeDataHelper(mVideoKey);
|
||||
mDownloadVideoDialog = null;
|
||||
mVideoScrollViewHolder = null;
|
||||
// mMobShareUtil = null;
|
||||
}
|
||||
|
||||
|
||||
public void setVideoScrollViewHolder(VideoScrollViewHolder videoScrollViewHolder) {
|
||||
mVideoScrollViewHolder = videoScrollViewHolder;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.yunbao.video.activity;
|
||||
|
||||
import android.content.Intent;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
|
||||
import com.yunbao.common.Constants;
|
||||
import com.yunbao.common.activity.AbsActivity;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.adapter.VideoChooseAdapter;
|
||||
import com.yunbao.video.bean.VideoChooseBean;
|
||||
import com.yunbao.common.custom.ItemDecoration;
|
||||
import com.yunbao.common.interfaces.CommonCallback;
|
||||
import com.yunbao.common.interfaces.OnItemClickListener;
|
||||
import com.yunbao.video.utils.VideoLocalUtil;
|
||||
import com.yunbao.common.utils.WordUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/10.
|
||||
* 选择本地视频
|
||||
*/
|
||||
|
||||
public class VideoChooseActivity extends AbsActivity implements OnItemClickListener<VideoChooseBean> {
|
||||
|
||||
private long mMaxDuration;
|
||||
private RecyclerView mRecyclerView;
|
||||
private View mNoData;
|
||||
private VideoLocalUtil mVideoLocalUtil;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_video_choose;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void main() {
|
||||
setTitle(WordUtil.getString(R.string.video_local));
|
||||
mMaxDuration = getIntent().getLongExtra(Constants.VIDEO_DURATION, 15000);
|
||||
mNoData = findViewById(R.id.no_data);
|
||||
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
|
||||
mRecyclerView.setHasFixedSize(true);
|
||||
mRecyclerView.setLayoutManager(new GridLayoutManager(mContext, 4, GridLayoutManager.VERTICAL, false));
|
||||
ItemDecoration decoration = new ItemDecoration(mContext, 0x00000000, 1, 1);
|
||||
decoration.setOnlySetItemOffsetsButNoDraw(true);
|
||||
mRecyclerView.addItemDecoration(decoration);
|
||||
mVideoLocalUtil = new VideoLocalUtil();
|
||||
mVideoLocalUtil.getLocalVideoList(new CommonCallback<List<VideoChooseBean>>() {
|
||||
@Override
|
||||
public void callback(List<VideoChooseBean> videoList) {
|
||||
if (videoList == null || videoList.size() == 0) {
|
||||
if (mNoData != null && mNoData.getVisibility() != View.VISIBLE) {
|
||||
mNoData.setVisibility(View.VISIBLE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (mRecyclerView != null) {
|
||||
VideoChooseAdapter adapter = new VideoChooseAdapter(mContext, videoList);
|
||||
adapter.setOnItemClickListener(VideoChooseActivity.this);
|
||||
mRecyclerView.setAdapter(adapter);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(VideoChooseBean bean, int position) {
|
||||
// if (bean.getDuration() > mMaxDuration + 1000) {
|
||||
// ToastUtil.show(R.string.video_duration_error);
|
||||
// return;
|
||||
// }
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(Constants.VIDEO_PATH, bean.getVideoPath());
|
||||
intent.putExtra(Constants.VIDEO_DURATION, bean.getDuration());
|
||||
setResult(RESULT_OK, intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
if (mVideoLocalUtil != null) {
|
||||
mVideoLocalUtil.release();
|
||||
}
|
||||
mVideoLocalUtil = null;
|
||||
mRecyclerView = null;
|
||||
mNoData = null;
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,940 @@
|
||||
package com.yunbao.video.activity;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.media.MediaMetadataRetriever;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AccelerateInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.tencent.ugc.TXVideoEditConstants;
|
||||
import com.tencent.ugc.TXVideoEditer;
|
||||
import com.tencent.ugc.TXVideoInfoReader;
|
||||
import com.yunbao.common.Constants;
|
||||
import com.yunbao.common.activity.AbsActivity;
|
||||
import com.yunbao.common.utils.DialogUitl;
|
||||
import com.yunbao.common.utils.L;
|
||||
import com.yunbao.common.utils.StringUtil;
|
||||
import com.yunbao.common.utils.ToastUtil;
|
||||
import com.yunbao.common.utils.WordUtil;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.bean.MusicBean;
|
||||
import com.yunbao.video.utils.VideoLocalUtil;
|
||||
import com.yunbao.video.views.VideoEditCutViewHolder;
|
||||
import com.yunbao.video.views.VideoEditFilterViewHolder;
|
||||
import com.yunbao.video.views.VideoEditMusicViewHolder;
|
||||
import com.yunbao.video.views.VideoMusicViewHolder;
|
||||
import com.yunbao.video.views.VideoProcessViewHolder;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/6.
|
||||
* 视频编辑activity
|
||||
*/
|
||||
|
||||
public class VideoEditActivity extends AbsActivity implements
|
||||
VideoProcessViewHolder.ActionListener,//预处理控件点击取消回调
|
||||
TXVideoEditer.TXVideoProcessListener, //视频编辑前预处理进度回调
|
||||
TXVideoEditer.TXThumbnailListener, //视频编辑前预处理中生成每一帧缩略图回调
|
||||
TXVideoEditer.TXVideoPreviewListener,
|
||||
TXVideoEditer.TXVideoGenerateListener {
|
||||
|
||||
private static final String TAG = "VideoEditActivity";
|
||||
private static final int STATUS_NONE = 0;
|
||||
private static final int STATUS_PLAY = 1;
|
||||
private static final int STATUS_PAUSE = 2;
|
||||
private static final int STATUS_PREVIEW_AT_TIME = 3;
|
||||
|
||||
public static void forward(Context context, long videoDuration, String videoPath, boolean fromRecord, boolean hasOriginBgm) {
|
||||
Intent intent = new Intent(context, VideoEditActivity.class);
|
||||
intent.putExtra(Constants.VIDEO_DURATION, videoDuration);
|
||||
intent.putExtra(Constants.VIDEO_PATH, videoPath);
|
||||
intent.putExtra(Constants.VIDEO_FROM_RECORD, fromRecord);
|
||||
intent.putExtra(Constants.VIDEO_HAS_BGM, hasOriginBgm);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
private ViewGroup mRoot;
|
||||
private View mGroup;
|
||||
private View mBtnNext;
|
||||
private View mBtnPlay;
|
||||
private ObjectAnimator mPlayBtnAnimator;//暂停按钮的动画
|
||||
private TXVideoEditer mVideoEditer;
|
||||
private List<Bitmap> mBitmapList;//视频每一帧的缩略图
|
||||
private long mVideoDuration;//视频总长度
|
||||
private String mOriginVideoPath;//原视频路径
|
||||
private boolean mFromRecord;
|
||||
private long mCutStartTime;//裁剪的起始时间
|
||||
private long mCutEndTime;//裁剪的结束时间
|
||||
private MusicBean mMusicBean;//背景音乐
|
||||
private boolean mHasOriginBgm;//是否在录制的时候有背景音乐
|
||||
private VideoMusicViewHolder mMusicViewHolder;//音乐
|
||||
private VideoEditFilterViewHolder mFilterViewHolder;//滤镜
|
||||
private VideoEditMusicViewHolder mVolumeViewHolder;//音量
|
||||
private VideoEditCutViewHolder mCutViewHolder;//裁剪
|
||||
private String mGenerateVideoPath;//生成视频的路径
|
||||
private VideoProcessViewHolder mVideoProcessViewHolder;//视频预处理进度条
|
||||
private VideoProcessViewHolder mVideoGenerateViewHolder;//视频生成进度条
|
||||
private int mSaveType;
|
||||
private boolean mPaused;//生命周期暂停
|
||||
private long mPreviewAtTime;
|
||||
private int mPLayStatus = STATUS_NONE;
|
||||
private MediaMetadataRetriever mMetadataRetriever;
|
||||
private MyHandler mHandler;
|
||||
private int mSdkErrorWaitCount;//sdk预处理回调异常的时候,设置30秒等待时间
|
||||
private static final int MAX_WAIT_COUNT = 120;
|
||||
private boolean mSdkError;
|
||||
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_video_edit;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isStatusBarWhite() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void main() {
|
||||
mRoot = (ViewGroup) findViewById(R.id.root);
|
||||
mGroup = findViewById(R.id.group);
|
||||
mBtnNext = findViewById(R.id.btn_next);
|
||||
mBtnPlay = findViewById(R.id.btn_play);
|
||||
//暂停按钮动画
|
||||
mPlayBtnAnimator = ObjectAnimator.ofPropertyValuesHolder(mBtnPlay,
|
||||
PropertyValuesHolder.ofFloat("scaleX", 4f, 0.8f, 1f),
|
||||
PropertyValuesHolder.ofFloat("scaleY", 4f, 0.8f, 1f),
|
||||
PropertyValuesHolder.ofFloat("alpha", 0f, 1f));
|
||||
mPlayBtnAnimator.setDuration(150);
|
||||
mPlayBtnAnimator.setInterpolator(new AccelerateInterpolator());
|
||||
mSaveType = Constants.VIDEO_SAVE_SAVE_AND_PUB;
|
||||
Intent intent = getIntent();
|
||||
mVideoDuration = intent.getLongExtra(Constants.VIDEO_DURATION, 0);
|
||||
mOriginVideoPath = intent.getStringExtra(Constants.VIDEO_PATH);
|
||||
mFromRecord = intent.getBooleanExtra(Constants.VIDEO_FROM_RECORD, false);
|
||||
mHasOriginBgm = intent.getBooleanExtra(Constants.VIDEO_HAS_BGM, false);
|
||||
if (mVideoDuration <= 0 || TextUtils.isEmpty(mOriginVideoPath)) {
|
||||
ToastUtil.show(WordUtil.getString(R.string.video_edit_status_error));
|
||||
deleteOriginVideoFile();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
mVideoEditer = new TXVideoEditer(mContext);
|
||||
mVideoEditer.setVideoPath(mOriginVideoPath);
|
||||
mVideoEditer.setVideoProcessListener(this);
|
||||
mVideoEditer.setThumbnailListener(this);
|
||||
mVideoEditer.setTXVideoPreviewListener(this);
|
||||
mVideoEditer.setVideoGenerateListener(this);
|
||||
mCutStartTime = 0;
|
||||
mCutEndTime = mVideoDuration;
|
||||
startPreProcess();
|
||||
}
|
||||
|
||||
private void deleteOriginVideoFile() {
|
||||
if (mFromRecord && !TextUtils.isEmpty(mOriginVideoPath)) {
|
||||
File file = new File(mOriginVideoPath);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示开始播放按钮
|
||||
*/
|
||||
private void showPlayBtn() {
|
||||
if (mBtnPlay != null && mBtnPlay.getVisibility() != View.VISIBLE) {
|
||||
mBtnPlay.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏开始播放按钮
|
||||
*/
|
||||
private void hidePlayBtn() {
|
||||
if (mBtnPlay != null && mBtnPlay.getVisibility() == View.VISIBLE) {
|
||||
mBtnPlay.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 点击切换播放和暂停
|
||||
*/
|
||||
private void clickTogglePlay() {
|
||||
switch (mPLayStatus) {
|
||||
case STATUS_PLAY:
|
||||
mPLayStatus = STATUS_PAUSE;
|
||||
if (mVideoEditer != null) {
|
||||
mVideoEditer.pausePlay();
|
||||
}
|
||||
break;
|
||||
case STATUS_PAUSE:
|
||||
mPLayStatus = STATUS_PLAY;
|
||||
if (mVideoEditer != null) {
|
||||
mVideoEditer.resumePlay();
|
||||
}
|
||||
break;
|
||||
case STATUS_PREVIEW_AT_TIME:
|
||||
mPLayStatus = STATUS_PLAY;
|
||||
if (mVideoEditer != null) {
|
||||
if (mPreviewAtTime > mCutStartTime && mPreviewAtTime < mCutEndTime) {
|
||||
mVideoEditer.startPlayFromTime(mPreviewAtTime, mCutEndTime);
|
||||
} else {
|
||||
mVideoEditer.startPlayFromTime(mCutStartTime, mCutEndTime);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (mPLayStatus == STATUS_PAUSE) {
|
||||
showPlayBtn();
|
||||
if (mPlayBtnAnimator != null) {
|
||||
mPlayBtnAnimator.start();
|
||||
}
|
||||
} else {
|
||||
hidePlayBtn();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 开启视频预览
|
||||
*/
|
||||
private void startVideoPreview() {
|
||||
if (mVideoEditer == null) {
|
||||
return;
|
||||
}
|
||||
FrameLayout layout = (FrameLayout) findViewById(R.id.video_container);
|
||||
TXVideoEditConstants.TXPreviewParam param = new TXVideoEditConstants.TXPreviewParam();
|
||||
param.videoView = layout;
|
||||
param.renderMode = TXVideoEditConstants.PREVIEW_RENDER_MODE_FILL_EDGE;
|
||||
mVideoEditer.initWithPreview(param);
|
||||
startPlay();
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始播放
|
||||
*/
|
||||
private void startPlay() {
|
||||
if (mVideoEditer != null) {
|
||||
mPLayStatus = STATUS_PLAY;
|
||||
mVideoEditer.startPlayFromTime(mCutStartTime, mCutEndTime);
|
||||
hidePlayBtn();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 预览播放回调
|
||||
*/
|
||||
@Override
|
||||
public void onPreviewProgress(int time) {
|
||||
if (mPLayStatus == STATUS_PLAY && mCutViewHolder != null) {
|
||||
mCutViewHolder.onVideoProgressChanged(time);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 预览播放回调
|
||||
*/
|
||||
@Override
|
||||
public void onPreviewFinished() {
|
||||
if (mPLayStatus == STATUS_PLAY) {
|
||||
startPlay();//播放结束后,重新开始播放
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成视频进度回调
|
||||
*/
|
||||
@Override
|
||||
public void onGenerateProgress(float progress) {
|
||||
if (mVideoGenerateViewHolder != null) {
|
||||
mVideoGenerateViewHolder.setProgress((int) (progress * 100));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成视频结束回调
|
||||
*/
|
||||
@Override
|
||||
public void onGenerateComplete(TXVideoEditConstants.TXGenerateResult result) {
|
||||
L.e(TAG, "onGenerateComplete------->");
|
||||
if (result.retCode == TXVideoEditConstants.GENERATE_RESULT_OK) {
|
||||
L.e(TAG, "onGenerateComplete------->生成视频成功");
|
||||
ToastUtil.show(R.string.video_generate_success);
|
||||
switch (mSaveType) {
|
||||
case Constants.VIDEO_SAVE_SAVE://仅保存
|
||||
saveGenerateVideoInfo();
|
||||
break;
|
||||
case Constants.VIDEO_SAVE_PUB://仅发布
|
||||
VideoPublishActivity.forward(mContext, mGenerateVideoPath, mSaveType,mMusicBean != null ? mMusicBean.getId() : 0);
|
||||
break;
|
||||
case Constants.VIDEO_SAVE_SAVE_AND_PUB://保存并发布
|
||||
saveGenerateVideoInfo();
|
||||
VideoPublishActivity.forward(mContext, mGenerateVideoPath, mSaveType,mMusicBean != null ? mMusicBean.getId() : 0);
|
||||
break;
|
||||
}
|
||||
finish();
|
||||
} else {
|
||||
ToastUtil.show(R.string.video_generate_failed);
|
||||
if (mVideoGenerateViewHolder != null) {
|
||||
mVideoGenerateViewHolder.removeFromParent();
|
||||
}
|
||||
if (mBtnNext != null) {
|
||||
mBtnNext.setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 把新生成的视频保存到ContentProvider,在选择上传的时候能找到
|
||||
*/
|
||||
private void saveGenerateVideoInfo() {
|
||||
VideoLocalUtil.saveVideoInfo(mContext, mGenerateVideoPath, mCutEndTime - mCutStartTime);
|
||||
}
|
||||
|
||||
public void videoEditClick(View v) {
|
||||
int i = v.getId();
|
||||
if (i == R.id.btn_music) {
|
||||
clickMusic();
|
||||
|
||||
} else if (i == R.id.btn_music_volume) {
|
||||
clickMusicVolume();
|
||||
|
||||
} else if (i == R.id.btn_filter) {
|
||||
clickFilter();
|
||||
|
||||
} else if (i == R.id.btn_cut) {
|
||||
clickCut();
|
||||
|
||||
} else if (i == R.id.btn_special) {
|
||||
clickSpecial();
|
||||
|
||||
} else if (i == R.id.btn_next) {
|
||||
clickNext();
|
||||
|
||||
} else if (i == R.id.group) {
|
||||
clickTogglePlay();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击音乐
|
||||
*/
|
||||
private void clickMusic() {
|
||||
hideGroup();
|
||||
if (mMusicViewHolder == null) {
|
||||
mMusicViewHolder = new VideoMusicViewHolder(mContext, mRoot);
|
||||
mMusicViewHolder.setActionListener(new VideoMusicViewHolder.ActionListener() {
|
||||
@Override
|
||||
public void onChooseMusic(MusicBean bean) {
|
||||
if (mVideoEditer != null && bean != null) {
|
||||
String bgmPath = bean.getLocalPath();
|
||||
if (TextUtils.isEmpty(bgmPath)) {
|
||||
return;
|
||||
}
|
||||
long bgmDuration = 0;
|
||||
if (mMetadataRetriever == null) {
|
||||
mMetadataRetriever = new MediaMetadataRetriever();
|
||||
}
|
||||
try {
|
||||
mMetadataRetriever.setDataSource(bgmPath);
|
||||
String duration = mMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
|
||||
bgmDuration = Long.parseLong(duration);
|
||||
} catch (Exception e) {
|
||||
bgmDuration = 0;
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (bgmDuration == 0) {
|
||||
return;
|
||||
}
|
||||
bean.setDuration(bgmDuration);
|
||||
mVideoEditer.setBGM(bgmPath);
|
||||
mVideoEditer.setBGMVolume(0.8f);
|
||||
if (mHasOriginBgm) {
|
||||
mVideoEditer.setVideoVolume(0);
|
||||
}
|
||||
mMusicBean = bean;
|
||||
if (mVolumeViewHolder != null) {
|
||||
mVolumeViewHolder.setMusicBean(bean);
|
||||
}
|
||||
mVideoEditer.stopPlay();
|
||||
startPlay();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHide() {
|
||||
showGroup();
|
||||
}
|
||||
});
|
||||
mMusicViewHolder.addToParent();
|
||||
mMusicViewHolder.subscribeActivityLifeCycle();
|
||||
}
|
||||
mMusicViewHolder.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击音量
|
||||
*/
|
||||
private void clickMusicVolume() {
|
||||
hideGroup();
|
||||
if (mVolumeViewHolder == null) {
|
||||
mVolumeViewHolder = new VideoEditMusicViewHolder(mContext, mRoot, mHasOriginBgm,mMusicBean);
|
||||
mVolumeViewHolder.setActionListener(new VideoEditMusicViewHolder.ActionListener() {
|
||||
@Override
|
||||
public void onHide() {
|
||||
showGroup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOriginalVolumeChanged(float value) {
|
||||
if (mVideoEditer != null) {
|
||||
mVideoEditer.setVideoVolume(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBgmVolumeChanged(float value) {
|
||||
if (mVideoEditer != null) {
|
||||
mVideoEditer.setBGMVolume(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBgmCancelClick() {
|
||||
if (mVideoEditer != null) {
|
||||
mVideoEditer.setVideoVolume(0.8f);
|
||||
mVideoEditer.setBGM(null);
|
||||
mVideoEditer.stopPlay();
|
||||
startPlay();
|
||||
}
|
||||
mMusicBean = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBgmCutTimeChanged(long startTime, long endTime) {
|
||||
if (mVideoEditer != null) {
|
||||
mVideoEditer.setBGMStartTime(startTime, endTime);
|
||||
}
|
||||
}
|
||||
});
|
||||
mVolumeViewHolder.addToParent();
|
||||
}
|
||||
mVolumeViewHolder.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击滤镜
|
||||
*/
|
||||
private void clickFilter() {
|
||||
hideGroup();
|
||||
if (mFilterViewHolder == null) {
|
||||
mFilterViewHolder = new VideoEditFilterViewHolder(mContext, mRoot);
|
||||
mFilterViewHolder.setActionListener(new VideoEditFilterViewHolder.ActionListener() {
|
||||
@Override
|
||||
public void onHide() {
|
||||
showGroup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFilterChanged(Bitmap bitmap) {
|
||||
if (mVideoEditer != null) {
|
||||
mVideoEditer.setFilter(bitmap);
|
||||
}
|
||||
}
|
||||
});
|
||||
mFilterViewHolder.addToParent();
|
||||
}
|
||||
mFilterViewHolder.show();
|
||||
}
|
||||
|
||||
private void showCutViewHolder(boolean showSpecial) {
|
||||
if (mCutViewHolder == null) {
|
||||
mCutViewHolder = new VideoEditCutViewHolder(mContext, mRoot, mVideoDuration);
|
||||
mCutViewHolder.setActionListener(new VideoEditCutViewHolder.ActionListener() {
|
||||
@Override
|
||||
public void onHide() {
|
||||
showGroup();
|
||||
if (mPLayStatus != STATUS_PLAY) {
|
||||
clickTogglePlay();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSeekChanged(long currentTimeMs) {
|
||||
previewAtTime(currentTimeMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCutTimeChanged(long startTime, long endTime) {
|
||||
mCutStartTime = startTime;
|
||||
mCutEndTime = endTime;
|
||||
if (mVideoEditer != null) {
|
||||
mVideoEditer.setCutFromTime(startTime, endTime);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSpecialStart(int effect, long currentTimeMs) {
|
||||
if (mVideoEditer != null) {
|
||||
if (mPLayStatus == STATUS_NONE || mPLayStatus == STATUS_PREVIEW_AT_TIME) {
|
||||
mVideoEditer.startPlayFromTime(mPreviewAtTime, mCutEndTime);
|
||||
} else if (mPLayStatus == STATUS_PAUSE) {
|
||||
mVideoEditer.resumePlay();
|
||||
}
|
||||
mPLayStatus = STATUS_PLAY;
|
||||
mVideoEditer.startEffect(effect, currentTimeMs);
|
||||
}
|
||||
hidePlayBtn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSpecialEnd(int effect, long currentTimeMs) {
|
||||
if (mVideoEditer != null) {
|
||||
mVideoEditer.pausePlay();
|
||||
mPLayStatus = STATUS_PAUSE;
|
||||
mVideoEditer.stopEffect(effect, currentTimeMs);
|
||||
}
|
||||
showPlayBtn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSpecialCancel(long currentTimeMs) {
|
||||
if (mVideoEditer != null) {
|
||||
mVideoEditer.deleteLastEffect();
|
||||
previewAtTime(currentTimeMs);
|
||||
}
|
||||
}
|
||||
});
|
||||
mCutViewHolder.addToParent();
|
||||
}
|
||||
mCutViewHolder.show(showSpecial);
|
||||
}
|
||||
|
||||
|
||||
private void previewAtTime(long currentTimeMs) {
|
||||
if (mVideoEditer != null) {
|
||||
mVideoEditer.pausePlay();
|
||||
mVideoEditer.previewAtTime(currentTimeMs);
|
||||
}
|
||||
mPLayStatus = STATUS_PREVIEW_AT_TIME;
|
||||
mPreviewAtTime = currentTimeMs;
|
||||
showPlayBtn();
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击裁剪
|
||||
*/
|
||||
private void clickCut() {
|
||||
hideGroup();
|
||||
showCutViewHolder(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击特效
|
||||
*/
|
||||
private void clickSpecial() {
|
||||
hideGroup();
|
||||
showCutViewHolder(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击下一步,生成视频
|
||||
*/
|
||||
private void clickNext() {
|
||||
//产品要求把选择上传类型去掉
|
||||
// DialogUitl.showStringArrayDialog(mContext, new Integer[]{
|
||||
// R.string.video_save_save,
|
||||
// R.string.video_save_pub,
|
||||
// R.string.video_save_save_and_pub
|
||||
// }, new DialogUitl.StringArrayDialogCallback() {
|
||||
// @Override
|
||||
// public void onItemClick(String text, int tag) {
|
||||
// switch (tag) {
|
||||
// case R.string.video_save_save:
|
||||
// mSaveType = Constants.VIDEO_SAVE_SAVE;
|
||||
// break;
|
||||
// case R.string.video_save_pub:
|
||||
// mSaveType = Constants.VIDEO_SAVE_PUB;
|
||||
// break;
|
||||
// case R.string.video_save_save_and_pub:
|
||||
// mSaveType = Constants.VIDEO_SAVE_SAVE_AND_PUB;
|
||||
// break;
|
||||
// }
|
||||
// startGenerateVideo();
|
||||
// }
|
||||
// });
|
||||
|
||||
startGenerateVideo();
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始生成视频
|
||||
*/
|
||||
private void startGenerateVideo() {
|
||||
L.e(TAG, "startGenerateVideo------->生成视频");
|
||||
if (mVideoEditer == null) {
|
||||
return;
|
||||
}
|
||||
mBtnNext.setEnabled(false);
|
||||
mVideoEditer.stopPlay();
|
||||
mVideoEditer.cancel();
|
||||
mVideoGenerateViewHolder = new VideoProcessViewHolder(mContext, mRoot, WordUtil.getString(R.string.video_process_2));
|
||||
mVideoGenerateViewHolder.setActionListener(new VideoProcessViewHolder.ActionListener() {
|
||||
@Override
|
||||
public void onCancelProcessClick() {
|
||||
exit();
|
||||
}
|
||||
});
|
||||
mVideoGenerateViewHolder.addToParent();
|
||||
mVideoEditer.setCutFromTime(mCutStartTime, mCutEndTime);
|
||||
mGenerateVideoPath = StringUtil.generateVideoOutputPath();
|
||||
mVideoEditer.generateVideo(TXVideoEditConstants.VIDEO_COMPRESSED_720P, mGenerateVideoPath);
|
||||
}
|
||||
|
||||
private void showGroup() {
|
||||
if (mGroup != null && mGroup.getVisibility() != View.VISIBLE) {
|
||||
mGroup.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void hideGroup() {
|
||||
if (mGroup != null && mGroup.getVisibility() == View.VISIBLE) {
|
||||
mGroup.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
DialogUitl.showSimpleDialog(mContext, WordUtil.getString(R.string.video_edit_exit), new DialogUitl.SimpleCallback() {
|
||||
@Override
|
||||
public void onConfirmClick(Dialog dialog, String content) {
|
||||
exit();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void exit() {
|
||||
if (mCutViewHolder != null && mCutViewHolder.isShowed()) {
|
||||
mCutViewHolder.hide();
|
||||
return;
|
||||
}
|
||||
if (mVolumeViewHolder != null && mVolumeViewHolder.isShowed()) {
|
||||
mVolumeViewHolder.hide();
|
||||
return;
|
||||
}
|
||||
if (mMusicViewHolder != null && mMusicViewHolder.isShowed()) {
|
||||
mMusicViewHolder.hide();
|
||||
return;
|
||||
}
|
||||
if (mFilterViewHolder != null && mFilterViewHolder.isShowed()) {
|
||||
mFilterViewHolder.hide();
|
||||
return;
|
||||
}
|
||||
release();
|
||||
deleteOriginVideoFile();
|
||||
VideoEditActivity.super.onBackPressed();
|
||||
}
|
||||
|
||||
private void release() {
|
||||
if (mHandler != null) {
|
||||
mHandler.release();
|
||||
}
|
||||
if (mMetadataRetriever != null) {
|
||||
mMetadataRetriever.release();
|
||||
}
|
||||
if (mFilterViewHolder != null) {
|
||||
mFilterViewHolder.release();
|
||||
}
|
||||
if (mMusicViewHolder != null) {
|
||||
mMusicViewHolder.release();
|
||||
}
|
||||
if (mVolumeViewHolder != null) {
|
||||
mVolumeViewHolder.release();
|
||||
}
|
||||
if (mCutViewHolder != null) {
|
||||
mCutViewHolder.release();
|
||||
}
|
||||
if (mVideoEditer != null) {
|
||||
mVideoEditer.deleteAllEffect();
|
||||
mVideoEditer.stopPlay();
|
||||
mVideoEditer.cancel();
|
||||
mVideoEditer.setVideoProcessListener(null);
|
||||
mVideoEditer.setThumbnailListener(null);
|
||||
mVideoEditer.setTXVideoPreviewListener(null);
|
||||
mVideoEditer.setVideoGenerateListener(null);
|
||||
mVideoEditer.release();
|
||||
}
|
||||
if (mVideoProcessViewHolder != null) {
|
||||
mVideoProcessViewHolder.setActionListener(null);
|
||||
}
|
||||
if (mVideoGenerateViewHolder != null) {
|
||||
mVideoGenerateViewHolder.setActionListener(null);
|
||||
}
|
||||
if (mBitmapList != null) {
|
||||
for (Bitmap bitmap : mBitmapList) {
|
||||
if (bitmap != null) {
|
||||
bitmap.recycle();
|
||||
}
|
||||
}
|
||||
mBitmapList.clear();
|
||||
}
|
||||
mHandler = null;
|
||||
mMetadataRetriever = null;
|
||||
mFilterViewHolder = null;
|
||||
mVideoEditer = null;
|
||||
mMusicViewHolder = null;
|
||||
mVolumeViewHolder = null;
|
||||
mCutViewHolder = null;
|
||||
mVideoProcessViewHolder = null;
|
||||
mVideoGenerateViewHolder = null;
|
||||
mBitmapList = null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mPaused = true;
|
||||
if (mVideoEditer != null && mPLayStatus == STATUS_PLAY) {
|
||||
mVideoEditer.pausePlay();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if (mPaused) {
|
||||
if (mVideoEditer != null && mPLayStatus == STATUS_PLAY) {
|
||||
mVideoEditer.resumePlay();
|
||||
}
|
||||
}
|
||||
mPaused = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
release();
|
||||
super.onDestroy();
|
||||
L.e(TAG, "VideoEditActivity------->onDestroy");
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始预处理
|
||||
*/
|
||||
private void startPreProcess() {
|
||||
mVideoProcessViewHolder = new VideoProcessViewHolder(mContext, mRoot, WordUtil.getString(R.string.video_process_1));
|
||||
mVideoProcessViewHolder.addToParent();
|
||||
mVideoProcessViewHolder.setActionListener(this);
|
||||
if (mHandler == null) {
|
||||
mHandler = new MyHandler(this);
|
||||
}
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
TXVideoEditConstants.TXVideoInfo info = TXVideoInfoReader.getInstance().getVideoFileInfo(mOriginVideoPath);
|
||||
if (mHandler != null) {
|
||||
if (info == null) {
|
||||
mHandler.sendEmptyMessage(MyHandler.ERROR);
|
||||
} else {
|
||||
mHandler.sendEmptyMessage(MyHandler.SUCCESS);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (mHandler != null) {
|
||||
mHandler.sendEmptyMessage(MyHandler.ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行预处理
|
||||
*/
|
||||
private void doPreProcess() {
|
||||
try {
|
||||
if (mVideoEditer != null) {
|
||||
mBitmapList = new ArrayList<>();
|
||||
int thumbnailCount = (int) Math.floor(mVideoDuration / 1000f);
|
||||
TXVideoEditConstants.TXThumbnail thumbnail = new TXVideoEditConstants.TXThumbnail();
|
||||
thumbnail.count = thumbnailCount;
|
||||
thumbnail.width = 60;
|
||||
thumbnail.height = 100;
|
||||
mVideoEditer.setThumbnail(thumbnail);
|
||||
mVideoEditer.processVideo();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
processFailed();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 录制结束后,视频预处理进度回调
|
||||
*/
|
||||
@Override
|
||||
public void onProcessProgress(float progress) {
|
||||
int p = (int) (progress * 100);
|
||||
if (p > 0 && p <= 100) {
|
||||
if (mVideoProcessViewHolder != null) {
|
||||
mVideoProcessViewHolder.setProgress(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 录制结束后,视频预处理的回调
|
||||
*/
|
||||
@Override
|
||||
public void onProcessComplete(TXVideoEditConstants.TXGenerateResult result) {
|
||||
if (result.retCode == TXVideoEditConstants.GENERATE_RESULT_OK) {
|
||||
if (mVideoProcessViewHolder != null && mVideoProcessViewHolder.getProgress() == 0) {
|
||||
if (!mSdkError) {
|
||||
mSdkError = true;
|
||||
sdkProgressError();
|
||||
}
|
||||
} else {
|
||||
processCompleted();
|
||||
}
|
||||
} else {
|
||||
L.e(TAG, "视频预处理错误------->" + result.descMsg);
|
||||
processFailed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 制结束后,获取缩略图的回调
|
||||
*/
|
||||
@Override
|
||||
public void onThumbnail(int i, long l, Bitmap bitmap) {
|
||||
if (mBitmapList != null) {
|
||||
mBitmapList.add(new SoftReference<>(bitmap).get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 点击取消预处理的按钮
|
||||
*/
|
||||
@Override
|
||||
public void onCancelProcessClick() {
|
||||
ToastUtil.show(WordUtil.getString(R.string.video_process_cancel));
|
||||
deleteOriginVideoFile();
|
||||
release();
|
||||
finish();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 预处理失败
|
||||
*/
|
||||
private void processFailed() {
|
||||
deleteOriginVideoFile();
|
||||
ToastUtil.show(R.string.video_process_failed);
|
||||
release();
|
||||
finish();
|
||||
}
|
||||
|
||||
private void processCompleted() {
|
||||
L.e(TAG, "视频预处理----->完成");
|
||||
if (mVideoProcessViewHolder != null) {
|
||||
mVideoProcessViewHolder.setProgress(100);
|
||||
}
|
||||
if (mHandler != null) {
|
||||
mHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
startVideoPreview();
|
||||
if (mVideoProcessViewHolder != null) {
|
||||
mVideoProcessViewHolder.removeFromParent();
|
||||
mVideoProcessViewHolder.setActionListener(null);
|
||||
}
|
||||
mVideoProcessViewHolder = null;
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sdk 预处理回调异常
|
||||
*/
|
||||
private void sdkProgressError() {
|
||||
mSdkErrorWaitCount++;
|
||||
int p = (int) (mSdkErrorWaitCount * 100f / MAX_WAIT_COUNT);
|
||||
if (p > 0 && p <= 100) {
|
||||
if (mVideoProcessViewHolder != null) {
|
||||
mVideoProcessViewHolder.setProgress(p);
|
||||
}
|
||||
}
|
||||
if (p >= 100) {
|
||||
processCompleted();
|
||||
} else {
|
||||
if (mHandler != null) {
|
||||
mHandler.sendEmptyMessageDelayed(MyHandler.SDK_PROGRESS_ERROR, 250);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<Bitmap> getBitmapList() {
|
||||
return mBitmapList;
|
||||
}
|
||||
|
||||
|
||||
private static class MyHandler extends Handler {
|
||||
|
||||
private static final int SUCCESS = 1;
|
||||
private static final int ERROR = 0;
|
||||
private static final int SDK_PROGRESS_ERROR = 2;//sdk 预处理回调异常
|
||||
|
||||
private VideoEditActivity mVideoEditActivity;
|
||||
|
||||
public MyHandler(VideoEditActivity recordActivity) {
|
||||
mVideoEditActivity = new WeakReference<>(recordActivity).get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (mVideoEditActivity != null) {
|
||||
switch (msg.what) {
|
||||
case SUCCESS:
|
||||
mVideoEditActivity.doPreProcess();
|
||||
break;
|
||||
case ERROR:
|
||||
mVideoEditActivity.processFailed();
|
||||
break;
|
||||
case SDK_PROGRESS_ERROR:
|
||||
mVideoEditActivity.sdkProgressError();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void release() {
|
||||
removeCallbacksAndMessages(null);
|
||||
mVideoEditActivity = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package com.yunbao.video.activity;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.binioter.guideview.Guide;
|
||||
import com.binioter.guideview.GuideBuilder;
|
||||
import com.yunbao.common.Constants;
|
||||
import com.yunbao.common.utils.L;
|
||||
import com.yunbao.common.utils.SpUtil;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.bean.VideoBean;
|
||||
import com.yunbao.video.utils.LottieComponent;
|
||||
import com.yunbao.video.utils.VideoStorge;
|
||||
import com.yunbao.video.views.VideoScrollViewHolder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/11/26.
|
||||
*/
|
||||
|
||||
public class VideoPlayActivity extends AbsVideoPlayActivity {
|
||||
|
||||
private View viewBottom;
|
||||
private ImageView btn_back;
|
||||
|
||||
public static void forward(Context context, int position, String videoKey, int page) {
|
||||
Intent intent = new Intent(context, VideoPlayActivity.class);
|
||||
intent.putExtra(Constants.VIDEO_POSITION, position);
|
||||
intent.putExtra(Constants.VIDEO_KEY, videoKey);
|
||||
intent.putExtra(Constants.VIDEO_PAGE, page);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
|
||||
public static void forwardSingle(Context context, VideoBean videoBean) {
|
||||
if (videoBean == null) {
|
||||
return;
|
||||
}
|
||||
List<VideoBean> list = new ArrayList<>();
|
||||
list.add(videoBean);
|
||||
VideoStorge.getInstance().put(Constants.VIDEO_SINGLE, list);
|
||||
Intent intent = new Intent(context, VideoPlayActivity.class);
|
||||
intent.putExtra(Constants.VIDEO_POSITION, 0);
|
||||
intent.putExtra(Constants.VIDEO_KEY, Constants.VIDEO_SINGLE);
|
||||
intent.putExtra(Constants.VIDEO_PAGE, 1);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_video_play;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isStatusBarWhite() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void main() {
|
||||
super.main();
|
||||
Intent intent = getIntent();
|
||||
mVideoKey = intent.getStringExtra(Constants.VIDEO_KEY);
|
||||
if (TextUtils.isEmpty(mVideoKey)) {
|
||||
return;
|
||||
}
|
||||
int position = intent.getIntExtra(Constants.VIDEO_POSITION, 0);
|
||||
int page = intent.getIntExtra(Constants.VIDEO_PAGE, 1);
|
||||
mVideoScrollViewHolder = new VideoScrollViewHolder(mContext, (ViewGroup) findViewById(R.id.container), position, mVideoKey, page);
|
||||
mVideoScrollViewHolder.addToParent();
|
||||
mVideoScrollViewHolder.subscribeActivityLifeCycle();
|
||||
viewBottom = findViewById(R.id.viewBottom);
|
||||
viewBottom.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
boolean read = SpUtil.getInstance().getBooleanValue(SpUtil.READ_VIDEO_GUIDE);
|
||||
if (!read) {
|
||||
showGuideView();
|
||||
}
|
||||
}
|
||||
});
|
||||
btn_back = findViewById(R.id.btn_back);
|
||||
btn_back.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("ResourceType")
|
||||
public void showGuideView() {
|
||||
final GuideBuilder builder1 = new GuideBuilder();
|
||||
builder1.setTargetView(viewBottom)
|
||||
.setAlpha(180)
|
||||
.setHighTargetCorner(20)
|
||||
.setHighTargetPadding(0)
|
||||
.setExitAnimationId(android.R.anim.fade_out);
|
||||
builder1.setOnVisibilityChangedListener(new GuideBuilder.OnVisibilityChangedListener() {
|
||||
@Override
|
||||
public void onShown() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss() {
|
||||
SpUtil.getInstance().setBooleanValue(SpUtil.READ_VIDEO_GUIDE, true);
|
||||
// Toast.makeText(VideoPlayActivity.this, "引导层消失了", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
||||
builder1.addComponent(new LottieComponent());
|
||||
Guide guide = builder1.createGuide();
|
||||
guide.setShouldCheckLocInWindow(false);
|
||||
guide.show(VideoPlayActivity.this);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
release();
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
release();
|
||||
super.onDestroy();
|
||||
L.e("VideoPlayActivity------->onDestroy");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,494 @@
|
||||
package com.yunbao.video.activity;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.media.MediaMetadataRetriever;
|
||||
import android.os.Bundle;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.tencent.rtmp.ITXLivePlayListener;
|
||||
import com.tencent.rtmp.TXLiveConstants;
|
||||
import com.tencent.rtmp.TXLivePlayConfig;
|
||||
import com.tencent.rtmp.TXLivePlayer;
|
||||
import com.tencent.rtmp.ui.TXCloudVideoView;
|
||||
import com.yunbao.common.CommonAppConfig;
|
||||
import com.yunbao.common.Constants;
|
||||
import com.yunbao.common.activity.AbsActivity;
|
||||
import com.yunbao.common.bean.ConfigBean;
|
||||
import com.yunbao.common.http.CommonHttpConsts;
|
||||
import com.yunbao.common.http.CommonHttpUtil;
|
||||
import com.yunbao.common.http.HttpCallback;
|
||||
import com.yunbao.common.interfaces.CommonCallback;
|
||||
import com.yunbao.common.utils.DialogUitl;
|
||||
import com.yunbao.common.utils.L;
|
||||
import com.yunbao.common.utils.ToastUtil;
|
||||
import com.yunbao.common.utils.WordUtil;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.adapter.VideoPubShareAdapter;
|
||||
import com.yunbao.video.http.VideoHttpConsts;
|
||||
import com.yunbao.video.http.VideoHttpUtil;
|
||||
import com.yunbao.video.upload.VideoUploadBean;
|
||||
import com.yunbao.video.upload.VideoUploadCallback;
|
||||
import com.yunbao.video.upload.VideoUploadQnImpl;
|
||||
import com.yunbao.video.upload.VideoUploadStrategy;
|
||||
import com.yunbao.video.upload.VideoUploadTxImpl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import top.zibin.luban.Luban;
|
||||
import top.zibin.luban.OnCompressListener;
|
||||
import top.zibin.luban.OnRenameListener;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/10.
|
||||
* 视频发布
|
||||
*/
|
||||
|
||||
public class VideoPublishActivity extends AbsActivity implements ITXLivePlayListener, View.OnClickListener {
|
||||
|
||||
|
||||
public static void forward(Context context, String videoPath, int saveType, int musicId) {
|
||||
Intent intent = new Intent(context, VideoPublishActivity.class);
|
||||
intent.putExtra(Constants.VIDEO_PATH, videoPath);
|
||||
intent.putExtra(Constants.VIDEO_SAVE_TYPE, saveType);
|
||||
intent.putExtra(Constants.VIDEO_MUSIC_ID, musicId);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
private static final String TAG = "VideoPublishActivity";
|
||||
private TextView mNum;
|
||||
private TextView mLocation;
|
||||
private TXCloudVideoView mTXCloudVideoView;
|
||||
private TXLivePlayer mPlayer;
|
||||
private String mVideoPath;
|
||||
private boolean mPlayStarted;//播放是否开始了
|
||||
private boolean mPaused;//生命周期暂停
|
||||
private RecyclerView mRecyclerView;
|
||||
private ConfigBean mConfigBean;
|
||||
private VideoPubShareAdapter mAdapter;
|
||||
private VideoUploadStrategy mUploadStrategy;
|
||||
private EditText mInput;
|
||||
private String mVideoTitle;//视频标题
|
||||
private Dialog mLoading;
|
||||
// private MobShareUtil mMobShareUtil;
|
||||
private int mSaveType;
|
||||
private int mMusicId;
|
||||
private View mBtnPub;
|
||||
private int mVideoLastProgress;
|
||||
private CheckBox mCheckBox;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_video_publish;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void main() {
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
setTitle(WordUtil.getString(R.string.video_pub));
|
||||
Intent intent = getIntent();
|
||||
mVideoPath = intent.getStringExtra(Constants.VIDEO_PATH);
|
||||
mSaveType = intent.getIntExtra(Constants.VIDEO_SAVE_TYPE, Constants.VIDEO_SAVE_SAVE_AND_PUB);
|
||||
if (TextUtils.isEmpty(mVideoPath)) {
|
||||
return;
|
||||
}
|
||||
mMusicId = intent.getIntExtra(Constants.VIDEO_MUSIC_ID, 0);
|
||||
mBtnPub = findViewById(R.id.btn_pub);
|
||||
mBtnPub.setOnClickListener(this);
|
||||
mRecyclerView = findViewById(R.id.recyclerView);
|
||||
mRecyclerView.setHasFixedSize(true);
|
||||
mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false));
|
||||
CommonAppConfig.getInstance().getConfig(new CommonCallback<ConfigBean>() {
|
||||
@Override
|
||||
public void callback(ConfigBean bean) {
|
||||
mConfigBean = bean;
|
||||
if (mRecyclerView != null) {
|
||||
mAdapter = new VideoPubShareAdapter(mContext, bean);
|
||||
mRecyclerView.setAdapter(mAdapter);
|
||||
}
|
||||
}
|
||||
});
|
||||
mNum = (TextView) findViewById(R.id.num);
|
||||
mInput = (EditText) findViewById(R.id.input);
|
||||
mInput.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
if (mNum != null) {
|
||||
mNum.setText(s.length() + "/50");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
|
||||
}
|
||||
});
|
||||
mLocation = findViewById(R.id.location);
|
||||
mLocation.setText(CommonAppConfig.getInstance().getCity());
|
||||
mCheckBox = findViewById(R.id.checkbox);
|
||||
mCheckBox.setOnClickListener(this);
|
||||
mTXCloudVideoView = findViewById(R.id.video_view);
|
||||
mPlayer = new TXLivePlayer(mContext);
|
||||
mPlayer.setConfig(new TXLivePlayConfig());
|
||||
mPlayer.setPlayerView(mTXCloudVideoView);
|
||||
mPlayer.enableHardwareDecode(false);
|
||||
mPlayer.setRenderRotation(TXLiveConstants.RENDER_ROTATION_PORTRAIT);
|
||||
mPlayer.setRenderMode(TXLiveConstants.RENDER_MODE_FULL_FILL_SCREEN);
|
||||
mPlayer.setPlayListener(this);
|
||||
int result = mPlayer.startPlay(mVideoPath, TXLivePlayer.PLAY_TYPE_LOCAL_VIDEO);
|
||||
if (result == 0) {
|
||||
mPlayStarted = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPlayEvent(int e, Bundle bundle) {
|
||||
switch (e) {
|
||||
case TXLiveConstants.PLAY_EVT_PLAY_END://播放结束
|
||||
onReplay();
|
||||
break;
|
||||
case TXLiveConstants.PLAY_EVT_CHANGE_RESOLUTION:
|
||||
onVideoSizeChanged(bundle.getInt("EVT_PARAM1", 0), bundle.getInt("EVT_PARAM2", 0));
|
||||
break;
|
||||
case TXLiveConstants.PLAY_EVT_PLAY_PROGRESS:
|
||||
int progress = bundle.getInt("EVT_PLAY_PROGRESS_MS");
|
||||
if (mVideoLastProgress == progress) {
|
||||
onReplay();
|
||||
} else {
|
||||
mVideoLastProgress = progress;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetStatus(Bundle bundle) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取到视频宽高回调
|
||||
*/
|
||||
public void onVideoSizeChanged(float videoWidth, float videoHeight) {
|
||||
if (mTXCloudVideoView != null && videoWidth > 0 && videoHeight > 0) {
|
||||
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mTXCloudVideoView.getLayoutParams();
|
||||
if (videoWidth / videoHeight > 0.5625f) {//横屏 9:16=0.5625
|
||||
params.height = (int) (mTXCloudVideoView.getWidth() / videoWidth * videoHeight);
|
||||
params.gravity = Gravity.CENTER;
|
||||
mTXCloudVideoView.requestLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 循环播放
|
||||
*/
|
||||
private void onReplay() {
|
||||
if (mPlayStarted && mPlayer != null) {
|
||||
mPlayer.seek(0);
|
||||
mPlayer.resume();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mPaused = true;
|
||||
if (mPlayStarted && mPlayer != null) {
|
||||
mPlayer.pause();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if (mPaused && mPlayStarted && mPlayer != null) {
|
||||
mPlayer.resume();
|
||||
}
|
||||
mPaused = false;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
CommonHttpUtil.cancel(CommonHttpConsts.GET_CONFIG);
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.SAVE_UPLOAD_VIDEO_INFO);
|
||||
mPlayStarted = false;
|
||||
if (mPlayer != null) {
|
||||
mPlayer.stopPlay(false);
|
||||
mPlayer.setPlayListener(null);
|
||||
}
|
||||
if (mUploadStrategy != null) {
|
||||
mUploadStrategy.cancel();
|
||||
}
|
||||
// if (mMobShareUtil != null) {
|
||||
// mMobShareUtil.release();
|
||||
// }
|
||||
mPlayer = null;
|
||||
mUploadStrategy = null;
|
||||
// mMobShareUtil = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
DialogUitl.showSimpleDialog(mContext, WordUtil.getString(R.string.video_give_up_pub), new DialogUitl.SimpleCallback() {
|
||||
@Override
|
||||
public void onConfirmClick(Dialog dialog, String content) {
|
||||
if (mSaveType == Constants.VIDEO_SAVE_PUB) {
|
||||
if (!TextUtils.isEmpty(mVideoPath)) {
|
||||
File file = new File(mVideoPath);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
release();
|
||||
VideoPublishActivity.super.onBackPressed();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
release();
|
||||
super.onDestroy();
|
||||
L.e(TAG, "-------->onDestroy");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int i = v.getId();
|
||||
if (i == R.id.btn_pub) {
|
||||
publishVideo();
|
||||
|
||||
} else if (i == R.id.checkbox) {
|
||||
clickCheckBox();
|
||||
}
|
||||
}
|
||||
|
||||
private void clickCheckBox() {
|
||||
if (mCheckBox == null || mLocation == null) {
|
||||
return;
|
||||
}
|
||||
if (mCheckBox.isChecked()) {
|
||||
mLocation.setEnabled(true);
|
||||
mLocation.setText(CommonAppConfig.getInstance().getCity());
|
||||
} else {
|
||||
mLocation.setEnabled(false);
|
||||
mLocation.setText(WordUtil.getString(R.string.mars));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发布视频
|
||||
*/
|
||||
private void publishVideo() {
|
||||
if (mConfigBean == null) {
|
||||
return;
|
||||
}
|
||||
mBtnPub.setEnabled(false);
|
||||
String title = mInput.getText().toString().trim();
|
||||
//产品要求把视频描述判断去掉
|
||||
// if (TextUtils.isEmpty(title)) {
|
||||
// ToastUtil.show(R.string.video_title_empty);
|
||||
// return;
|
||||
// }
|
||||
mVideoTitle = title;
|
||||
if (TextUtils.isEmpty(mVideoPath)) {
|
||||
return;
|
||||
}
|
||||
mLoading = DialogUitl.loadingDialog(mContext, WordUtil.getString(R.string.video_pub_ing));
|
||||
mLoading.show();
|
||||
Bitmap bitmap = null;
|
||||
//生成视频封面图
|
||||
MediaMetadataRetriever mmr = null;
|
||||
try {
|
||||
mmr = new MediaMetadataRetriever();
|
||||
mmr.setDataSource(mVideoPath);
|
||||
bitmap = mmr.getFrameAtTime(0, MediaMetadataRetriever.OPTION_CLOSEST);
|
||||
} catch (Exception e) {
|
||||
bitmap = null;
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (mmr != null) {
|
||||
mmr.release();
|
||||
}
|
||||
}
|
||||
if (bitmap == null) {
|
||||
ToastUtil.show(R.string.video_cover_img_failed);
|
||||
onFailed();
|
||||
return;
|
||||
}
|
||||
final String coverImagePath = mVideoPath.replace(".mp4", ".jpg");
|
||||
File imageFile = new File(coverImagePath);
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(imageFile);
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
|
||||
fos.flush();
|
||||
fos.close();
|
||||
} catch (Exception e) {
|
||||
imageFile = null;
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (fos != null) {
|
||||
try {
|
||||
fos.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bitmap != null) {
|
||||
bitmap.recycle();
|
||||
}
|
||||
if (imageFile == null) {
|
||||
ToastUtil.show(R.string.video_cover_img_failed);
|
||||
onFailed();
|
||||
return;
|
||||
}
|
||||
final File finalImageFile = imageFile;
|
||||
//用鲁班压缩图片
|
||||
Luban.with(this)
|
||||
.load(finalImageFile)
|
||||
.setFocusAlpha(false)
|
||||
.ignoreBy(8)//8k以下不压缩
|
||||
.setTargetDir(CommonAppConfig.VIDEO_PATH)
|
||||
.setRenameListener(new OnRenameListener() {
|
||||
@Override
|
||||
public String rename(String filePath) {
|
||||
filePath = filePath.substring(filePath.lastIndexOf("/") + 1);
|
||||
return filePath.replace(".jpg", "_c.jpg");
|
||||
}
|
||||
})
|
||||
.setCompressListener(new OnCompressListener() {
|
||||
@Override
|
||||
public void onStart() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(File file) {
|
||||
if (finalImageFile.exists()) {
|
||||
finalImageFile.delete();
|
||||
}
|
||||
uploadVideoFile(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
uploadVideoFile(finalImageFile);
|
||||
}
|
||||
}).launch();
|
||||
}
|
||||
|
||||
private void onFailed() {
|
||||
if (mLoading != null) {
|
||||
mLoading.dismiss();
|
||||
}
|
||||
if (mBtnPub != null) {
|
||||
mBtnPub.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传封面图片
|
||||
*/
|
||||
private void uploadVideoFile(File imageFile) {
|
||||
if (mConfigBean.getVideoCloudType() == 1) {
|
||||
mUploadStrategy = new VideoUploadQnImpl(mConfigBean);
|
||||
} else {
|
||||
mUploadStrategy = new VideoUploadTxImpl(mConfigBean);
|
||||
}
|
||||
mUploadStrategy.upload(new VideoUploadBean(new File(mVideoPath), imageFile), new VideoUploadCallback() {
|
||||
@Override
|
||||
public void onSuccess(VideoUploadBean bean) {
|
||||
if (mSaveType == Constants.VIDEO_SAVE_PUB) {
|
||||
bean.deleteFile();
|
||||
}
|
||||
saveUploadVideoInfo(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure() {
|
||||
ToastUtil.show(R.string.video_pub_failed);
|
||||
onFailed();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 把视频上传后的信息保存在服务器
|
||||
*/
|
||||
private void saveUploadVideoInfo(VideoUploadBean bean) {
|
||||
VideoHttpUtil.saveUploadVideoInfo(mVideoTitle, bean.getResultImageUrl(), bean.getResultVideoUrl(), mMusicId, mCheckBox != null && mCheckBox.isChecked(), new HttpCallback() {
|
||||
@Override
|
||||
public void onSuccess(int code, String msg, String[] info) {
|
||||
if (code == 0 && info.length > 0) {
|
||||
if (mConfigBean != null && mConfigBean.getVideoAuditSwitch() == 1) {
|
||||
ToastUtil.show(R.string.video_pub_success_2);
|
||||
} else {
|
||||
ToastUtil.show(R.string.video_pub_success);
|
||||
}
|
||||
if (mAdapter != null) {
|
||||
String shareType = mAdapter.getShareType();
|
||||
if (shareType != null) {
|
||||
JSONObject obj = JSON.parseObject(info[0]);
|
||||
shareVideoPage(shareType, obj.getString("id"), obj.getString("thumb_s"));
|
||||
}
|
||||
}
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
if (mLoading != null) {
|
||||
mLoading.dismiss();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 分享页面链接
|
||||
*/
|
||||
public void shareVideoPage(String shareType, String videoId, String videoImageUrl) {
|
||||
// ShareData data = new ShareData();
|
||||
// data.setTitle(mConfigBean.getVideoShareTitle());
|
||||
// data.setDes(mConfigBean.getVideoShareDes());
|
||||
// data.setImgUrl(videoImageUrl);
|
||||
// String webUrl = HtmlConfig.SHARE_VIDEO + videoId;
|
||||
// data.setWebUrl(webUrl);
|
||||
// if (mMobShareUtil == null) {
|
||||
// mMobShareUtil = new MobShareUtil();
|
||||
// }
|
||||
// mMobShareUtil.execute(shareType, data, null);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,143 @@
|
||||
package com.yunbao.video.activity;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.yunbao.common.Constants;
|
||||
import com.yunbao.common.activity.AbsActivity;
|
||||
import com.yunbao.common.http.HttpCallback;
|
||||
import com.yunbao.common.interfaces.KeyBoardHeightChangeListener;
|
||||
import com.yunbao.common.utils.KeyBoardHeightUtil;
|
||||
import com.yunbao.common.utils.ToastUtil;
|
||||
import com.yunbao.common.utils.WordUtil;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.adapter.VideoReportAdapter;
|
||||
import com.yunbao.video.bean.VideoReportBean;
|
||||
import com.yunbao.video.http.VideoHttpConsts;
|
||||
import com.yunbao.video.http.VideoHttpUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/15.
|
||||
* 视频举报
|
||||
*/
|
||||
|
||||
public class VideoReportActivity extends AbsActivity implements VideoReportAdapter.ActionListener, KeyBoardHeightChangeListener {
|
||||
|
||||
public static void forward(Context context, String videoId) {
|
||||
Intent intent = new Intent(context, VideoReportActivity.class);
|
||||
intent.putExtra(Constants.VIDEO_ID, videoId);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
private String mVideoId;
|
||||
private RecyclerView mRecyclerView;
|
||||
private VideoReportAdapter mAdapter;
|
||||
private KeyBoardHeightUtil mKeyBoardHeightUtil;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_video_report;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void main() {
|
||||
setTitle(WordUtil.getString(R.string.report));
|
||||
mVideoId = getIntent().getStringExtra(Constants.VIDEO_ID);
|
||||
mRecyclerView = findViewById(R.id.recyclerView);
|
||||
mRecyclerView.setHasFixedSize(true);
|
||||
mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false));
|
||||
mKeyBoardHeightUtil = new KeyBoardHeightUtil(mContext, findViewById(android.R.id.content), this);
|
||||
VideoHttpUtil.getVideoReportList(new HttpCallback() {
|
||||
@Override
|
||||
public void onSuccess(int code, String msg, String[] info) {
|
||||
if (code == 0) {
|
||||
List<VideoReportBean> list = JSON.parseArray(Arrays.toString(info), VideoReportBean.class);
|
||||
mAdapter = new VideoReportAdapter(mContext, list);
|
||||
mAdapter.setActionListener(VideoReportActivity.this);
|
||||
if (mRecyclerView != null) {
|
||||
mRecyclerView.setAdapter(mAdapter);
|
||||
}
|
||||
if (mKeyBoardHeightUtil != null) {
|
||||
mKeyBoardHeightUtil.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReportClick(VideoReportBean bean, String text) {
|
||||
if (TextUtils.isEmpty(mVideoId)) {
|
||||
return;
|
||||
}
|
||||
if (bean == null) {
|
||||
ToastUtil.show(R.string.video_report_tip_3);
|
||||
return;
|
||||
}
|
||||
String content = bean.getName();
|
||||
if (!TextUtils.isEmpty(text)) {
|
||||
content += " " + text;
|
||||
}
|
||||
VideoHttpUtil.videoReport(mVideoId, bean.getId(), content, mReportCallback);
|
||||
}
|
||||
|
||||
private HttpCallback mReportCallback = new HttpCallback() {
|
||||
@Override
|
||||
public void onSuccess(int code, String msg, String[] info) {
|
||||
if (code == 0) {
|
||||
ToastUtil.show(R.string.video_report_tip_4);
|
||||
onBackPressed();
|
||||
} else {
|
||||
ToastUtil.show(msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onKeyBoardHeightChanged(int visibleHeight, int keyboardHeight) {
|
||||
if (mRecyclerView != null) {
|
||||
mRecyclerView.setTranslationY(-keyboardHeight);
|
||||
}
|
||||
if (keyboardHeight > 0 && mAdapter != null) {
|
||||
mRecyclerView.smoothScrollToPosition(mAdapter.getItemCount() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSoftInputShowed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private void release() {
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.GET_VIDEO_REPORT_LIST);
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.VIDEO_REPORT);
|
||||
if (mKeyBoardHeightUtil != null) {
|
||||
mKeyBoardHeightUtil.release();
|
||||
}
|
||||
mKeyBoardHeightUtil = null;
|
||||
if (mAdapter != null) {
|
||||
mAdapter.setActionListener(null);
|
||||
}
|
||||
mAdapter = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
release();
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
release();
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
309
video/src/main/java/com/yunbao/video/adapter/MusicAdapter.java
Normal file
309
video/src/main/java/com/yunbao/video/adapter/MusicAdapter.java
Normal file
@@ -0,0 +1,309 @@
|
||||
package com.yunbao.video.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.ScaleAnimation;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.yunbao.common.Constants;
|
||||
import com.yunbao.common.adapter.RefreshAdapter;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.bean.MusicBean;
|
||||
import com.yunbao.common.glide.ImgLoader;
|
||||
import com.yunbao.common.http.HttpCallback;
|
||||
import com.yunbao.video.http.VideoHttpConsts;
|
||||
import com.yunbao.video.http.VideoHttpUtil;
|
||||
import com.yunbao.video.interfaces.VideoMusicActionListener;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/6/20.
|
||||
*/
|
||||
|
||||
public class MusicAdapter extends RefreshAdapter<MusicBean> {
|
||||
|
||||
private static final int HEAD = 1;
|
||||
private static final int NORMAL = 0;
|
||||
private ImageView mStarView;
|
||||
private MusicBean mCollectMusicBean;
|
||||
private Drawable mStarDrawable;//收藏图标
|
||||
private Drawable mUnStarDrawable;//取消收藏图标
|
||||
private Drawable mPlayDrawable;//播放按钮
|
||||
private Drawable mPauseDrawable;//暂停按钮
|
||||
private Animation mAnimation;
|
||||
private int mCheckedPosition = -1;
|
||||
private VideoMusicActionListener mActionListener;
|
||||
private View.OnClickListener mOnStarClickListener;
|
||||
private View.OnClickListener mOnUseClickListener;
|
||||
private View.OnClickListener mOnClickListener;
|
||||
|
||||
public MusicAdapter(Context context) {
|
||||
super(context);
|
||||
mStarDrawable = ContextCompat.getDrawable(context, R.mipmap.icon_video_music_collect_1);
|
||||
mUnStarDrawable = ContextCompat.getDrawable(context, R.mipmap.icon_video_music_collect_0);
|
||||
mPlayDrawable = ContextCompat.getDrawable(context, R.mipmap.icon_video_music_play);
|
||||
mPauseDrawable = ContextCompat.getDrawable(context, R.mipmap.icon_video_music_pause);
|
||||
mAnimation = new ScaleAnimation(1f, 0.3f, 1f, 0.3f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
|
||||
mAnimation.setDuration(200);
|
||||
mAnimation.setRepeatCount(1);
|
||||
mAnimation.setRepeatMode(Animation.REVERSE);
|
||||
mAnimation.setAnimationListener(new Animation.AnimationListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {
|
||||
if (mStarView != null && mCollectMusicBean != null) {
|
||||
if (mCollectMusicBean.getCollect() == 1) {
|
||||
mStarView.setImageResource(R.mipmap.icon_video_music_collect_1);
|
||||
} else {
|
||||
mStarView.setImageResource(R.mipmap.icon_video_music_collect_0);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
mOnStarClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (!canClick()) {
|
||||
return;
|
||||
}
|
||||
Object tag = v.getTag();
|
||||
if (tag == null) {
|
||||
return;
|
||||
}
|
||||
int position = (int) tag;
|
||||
mCollectMusicBean = mList.get(position);
|
||||
mStarView = (ImageView) v;
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.SET_MUSIC_COLLECT);
|
||||
VideoHttpUtil.setMusicCollect(mCollectMusicBean.getId(), new HttpCallback() {
|
||||
@Override
|
||||
public void onSuccess(int code, String msg, String[] info) {
|
||||
if (code == 0 && info.length > 0) {
|
||||
int collect = JSON.parseObject(info[0]).getIntValue("iscollect");
|
||||
if (mCollectMusicBean != null) {
|
||||
mCollectMusicBean.setCollect(collect);
|
||||
if (mStarView != null && mAnimation != null) {
|
||||
mStarView.startAnimation(mAnimation);
|
||||
}
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onCollect(MusicAdapter.this, mCollectMusicBean.getId(), collect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
mOnUseClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (!canClick()) {
|
||||
return;
|
||||
}
|
||||
Object tag = v.getTag();
|
||||
if (tag == null) {
|
||||
return;
|
||||
}
|
||||
int position = (int) tag;
|
||||
MusicBean bean = mList.get(position);
|
||||
if (bean == null) {
|
||||
return;
|
||||
}
|
||||
bean.setExpand(false);
|
||||
notifyItemChanged(position, Constants.PAYLOAD);
|
||||
mCheckedPosition = -1;
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onStopMusic();
|
||||
mActionListener.onUseClick(bean);
|
||||
}
|
||||
}
|
||||
};
|
||||
mOnClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Object tag = v.getTag();
|
||||
if (tag == null) {
|
||||
return;
|
||||
}
|
||||
int position = (int) tag;
|
||||
MusicBean bean = mList.get(position);
|
||||
if (bean == null) {
|
||||
return;
|
||||
}
|
||||
if (mCheckedPosition == position) {
|
||||
mCheckedPosition = -1;
|
||||
bean.setExpand(false);
|
||||
notifyItemChanged(position, Constants.PAYLOAD);
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onStopMusic();
|
||||
}
|
||||
} else {
|
||||
if (mCheckedPosition >= 0 && mCheckedPosition < mList.size()) {
|
||||
MusicBean checkedMusicBean = mList.get(mCheckedPosition);
|
||||
checkedMusicBean.setExpand(false);
|
||||
notifyItemChanged(mCheckedPosition, Constants.PAYLOAD);
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onStopMusic();
|
||||
}
|
||||
}
|
||||
bean.setExpand(true);
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onPlayMusic(MusicAdapter.this, bean, position);
|
||||
}
|
||||
mCheckedPosition = position;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void setActionListener(VideoMusicActionListener actionListener) {
|
||||
mActionListener = actionListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
if (position == 0) {
|
||||
return HEAD;
|
||||
}
|
||||
return NORMAL;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new Vh(mInflater.inflate(viewType == HEAD ? R.layout.item_music_head : R.layout.item_music, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder vh, int position, @NonNull List payloads) {
|
||||
Object payload = payloads.size() > 0 ? payloads.get(0) : null;
|
||||
((Vh) vh).setData(mList.get(position), position, payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mList.size();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 显示使用按钮
|
||||
*/
|
||||
public void expand(int position) {
|
||||
if (position >= 0 && position < mList.size()) {
|
||||
MusicBean bean = mList.get(position);
|
||||
if (bean != null) {
|
||||
bean.setExpand(true);
|
||||
notifyItemChanged(position, Constants.PAYLOAD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏使用按钮
|
||||
*/
|
||||
public void collapse() {
|
||||
if (mCheckedPosition >= 0 && mCheckedPosition < mList.size()) {
|
||||
MusicBean bean = mList.get(mCheckedPosition);
|
||||
if (bean != null) {
|
||||
bean.setExpand(false);
|
||||
notifyItemChanged(mCheckedPosition, Constants.PAYLOAD);
|
||||
}
|
||||
mCheckedPosition = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 收藏数据发生变化
|
||||
*/
|
||||
public void collectChanged(MusicAdapter adapter, int musicId, int isCollect) {
|
||||
if (adapter != this) {
|
||||
for (int i = 0, size = mList.size(); i < size; i++) {
|
||||
MusicBean bean = mList.get(i);
|
||||
if (bean != null && bean.getId() == musicId) {
|
||||
bean.setCollect(isCollect);
|
||||
notifyItemChanged(i, Constants.PAYLOAD);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Vh extends RecyclerView.ViewHolder {
|
||||
|
||||
ImageView mImg;
|
||||
TextView mTitle;
|
||||
TextView mAuthor;
|
||||
TextView mLength;
|
||||
ImageView mBtnCollect;
|
||||
View mBtnUse;
|
||||
ImageView mBtnPlay;
|
||||
|
||||
public Vh(View itemView) {
|
||||
super(itemView);
|
||||
mImg = (ImageView) itemView.findViewById(R.id.img);
|
||||
mTitle = (TextView) itemView.findViewById(R.id.title);
|
||||
mAuthor = (TextView) itemView.findViewById(R.id.author);
|
||||
mLength = (TextView) itemView.findViewById(R.id.length);
|
||||
mBtnPlay = (ImageView) itemView.findViewById(R.id.btn_play);
|
||||
mBtnCollect = (ImageView) itemView.findViewById(R.id.btn_collect);
|
||||
mBtnUse = itemView.findViewById(R.id.btn_use);
|
||||
mBtnCollect.setOnClickListener(mOnStarClickListener);
|
||||
mBtnUse.setOnClickListener(mOnUseClickListener);
|
||||
itemView.setOnClickListener(mOnClickListener);
|
||||
}
|
||||
|
||||
void setData(MusicBean bean, int position, Object payload) {
|
||||
itemView.setTag(position);
|
||||
mBtnCollect.setTag(position);
|
||||
mBtnUse.setTag(position);
|
||||
if (payload == null) {
|
||||
ImgLoader.display(mContext,bean.getImgUrl(), mImg);
|
||||
mTitle.setText(bean.getTitle());
|
||||
mAuthor.setText(bean.getAuthor());
|
||||
mLength.setText(bean.getLength());
|
||||
}
|
||||
if (bean.getCollect() == 1) {
|
||||
mBtnCollect.setImageDrawable(mStarDrawable);
|
||||
} else {
|
||||
mBtnCollect.setImageDrawable(mUnStarDrawable);
|
||||
}
|
||||
if (bean.isExpand()) {
|
||||
mBtnPlay.setImageDrawable(mPauseDrawable);
|
||||
if (mBtnUse.getVisibility() != View.VISIBLE) {
|
||||
mBtnUse.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
mBtnPlay.setImageDrawable(mPlayDrawable);
|
||||
if (mBtnUse.getVisibility() == View.VISIBLE) {
|
||||
mBtnUse.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.yunbao.video.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.bean.MusicClassBean;
|
||||
import com.yunbao.common.glide.ImgLoader;
|
||||
import com.yunbao.common.interfaces.OnItemClickListener;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/7/26.
|
||||
*/
|
||||
|
||||
public class MusicClassAdapter extends RecyclerView.Adapter<MusicClassAdapter.Vh> {
|
||||
|
||||
private Context mContext;
|
||||
private List<MusicClassBean> mList;
|
||||
private LayoutInflater mInflater;
|
||||
private View.OnClickListener mOnClickListener;
|
||||
private OnItemClickListener<MusicClassBean> mOnItemClickListener;
|
||||
|
||||
public MusicClassAdapter(Context context, List<MusicClassBean> list) {
|
||||
mContext=context;
|
||||
mList = list;
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mOnClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Object tag = v.getTag();
|
||||
if (tag != null && mOnItemClickListener != null) {
|
||||
mOnItemClickListener.onItemClick((MusicClassBean) tag, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void setOnItemClickListener(OnItemClickListener<MusicClassBean> onItemClickListener) {
|
||||
mOnItemClickListener = onItemClickListener;
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Vh onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new Vh(mInflater.inflate(R.layout.item_music_class, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull Vh vh, int position) {
|
||||
vh.setData(mList.get(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mList.size();
|
||||
}
|
||||
|
||||
class Vh extends RecyclerView.ViewHolder {
|
||||
|
||||
ImageView mImg;
|
||||
TextView mText;
|
||||
|
||||
public Vh(View itemView) {
|
||||
super(itemView);
|
||||
mImg = (ImageView) itemView.findViewById(R.id.img);
|
||||
mText = (TextView) itemView.findViewById(R.id.text);
|
||||
itemView.setOnClickListener(mOnClickListener);
|
||||
}
|
||||
|
||||
void setData(MusicClassBean bean) {
|
||||
itemView.setTag(bean);
|
||||
ImgLoader.display(mContext,bean.getImg_url(), mImg);
|
||||
mText.setText(bean.getTitle());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.yunbao.video.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.bean.VideoChooseBean;
|
||||
import com.yunbao.common.glide.ImgLoader;
|
||||
import com.yunbao.common.interfaces.OnItemClickListener;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/6/20.
|
||||
*/
|
||||
|
||||
public class VideoChooseAdapter extends RecyclerView.Adapter<VideoChooseAdapter.Vh> {
|
||||
|
||||
private Context mContext;
|
||||
private List<VideoChooseBean> mList;
|
||||
private LayoutInflater mInflater;
|
||||
private View.OnClickListener mOnClickListener;
|
||||
private OnItemClickListener<VideoChooseBean> mOnItemClickListener;
|
||||
|
||||
public VideoChooseAdapter(Context context, List<VideoChooseBean> list) {
|
||||
mContext=context;
|
||||
mList = list;
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mOnClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Object tag = v.getTag();
|
||||
if (tag != null && mOnItemClickListener != null) {
|
||||
mOnItemClickListener.onItemClick((VideoChooseBean) tag, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void setOnItemClickListener(OnItemClickListener<VideoChooseBean> listener) {
|
||||
mOnItemClickListener = listener;
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Vh onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new Vh(mInflater.inflate(R.layout.item_video_choose_local, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull Vh vh, int position) {
|
||||
vh.setData(mList.get(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mList.size();
|
||||
}
|
||||
|
||||
class Vh extends RecyclerView.ViewHolder {
|
||||
|
||||
ImageView mCover;
|
||||
TextView mDuration;
|
||||
|
||||
public Vh(View itemView) {
|
||||
super(itemView);
|
||||
mCover = (ImageView) itemView.findViewById(R.id.cover);
|
||||
mDuration = (TextView) itemView.findViewById(R.id.duration);
|
||||
itemView.setOnClickListener(mOnClickListener);
|
||||
}
|
||||
|
||||
void setData(VideoChooseBean bean) {
|
||||
itemView.setTag(bean);
|
||||
ImgLoader.displayVideoThumb(mContext,bean.getVideoPath(), mCover);
|
||||
mDuration.setText(bean.getDurationString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,395 @@
|
||||
package com.yunbao.video.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.ScaleAnimation;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.yunbao.common.CommonAppConfig;
|
||||
import com.yunbao.common.Constants;
|
||||
import com.yunbao.common.adapter.RefreshAdapter;
|
||||
import com.yunbao.common.bean.UserBean;
|
||||
import com.yunbao.common.glide.ImgLoader;
|
||||
import com.yunbao.common.http.HttpCallback;
|
||||
import com.yunbao.common.utils.ToastUtil;
|
||||
import com.yunbao.live.activity.LiveReportActivity;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.bean.VideoCommentBean;
|
||||
import com.yunbao.video.http.VideoHttpUtil;
|
||||
import com.yunbao.video.utils.VideoTextRender;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/3.
|
||||
*/
|
||||
|
||||
public class VideoCommentAdapter extends RefreshAdapter<VideoCommentBean> {
|
||||
|
||||
private static final int PARENT = 1;
|
||||
private static final int CHILD = 2;
|
||||
private Drawable mLikeDrawable;
|
||||
private Drawable mUnLikeDrawable;
|
||||
private int mLikeColor;
|
||||
private int mUnLikeColor;
|
||||
private ScaleAnimation mLikeAnimation;
|
||||
private View.OnClickListener mOnClickListener;
|
||||
private View.OnLongClickListener mOnLongClickListener;
|
||||
private View.OnClickListener mLikeClickListener;
|
||||
private View.OnClickListener mExpandClickListener;
|
||||
private View.OnClickListener mCollapsedClickListener;
|
||||
private ActionListener mActionListener;
|
||||
private ImageView mCurLikeImageView;
|
||||
private int mCurLikeCommentPosition;
|
||||
private VideoCommentBean mCurLikeCommentBean;
|
||||
private HttpCallback mLikeCommentCallback;
|
||||
|
||||
public VideoCommentAdapter(Context context) {
|
||||
super(context);
|
||||
mOnClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Object tag = v.getTag();
|
||||
if (tag != null && mOnItemClickListener != null) {
|
||||
mOnItemClickListener.onItemClick(((VideoCommentBean) tag), 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
mOnLongClickListener = new View.OnLongClickListener() {
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
Object tag = v.getTag();
|
||||
if (tag != null && mOnItemClickListener != null) {
|
||||
mOnItemLongClickListener.onItemLongClick(((VideoCommentBean) tag), -1, v);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
mLikeDrawable = ContextCompat.getDrawable(context, R.drawable.bg_video_comment_like_1);
|
||||
mUnLikeDrawable = ContextCompat.getDrawable(context, R.drawable.bg_video_comment_like_0);
|
||||
mLikeColor = ContextCompat.getColor(context, R.color.red);
|
||||
;
|
||||
mUnLikeColor = ContextCompat.getColor(context, R.color.gray3);
|
||||
mLikeAnimation = new ScaleAnimation(1f, 0.5f, 1f, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
|
||||
mLikeAnimation.setDuration(200);
|
||||
mLikeAnimation.setRepeatCount(1);
|
||||
mLikeAnimation.setRepeatMode(Animation.REVERSE);
|
||||
mLikeAnimation.setAnimationListener(new Animation.AnimationListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {
|
||||
if (mCurLikeCommentBean != null) {
|
||||
if (mCurLikeImageView != null) {
|
||||
mCurLikeImageView.setImageDrawable(mCurLikeCommentBean.getIsLike() == 1 ? mLikeDrawable : mUnLikeDrawable);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
mLikeCommentCallback = new HttpCallback() {
|
||||
@Override
|
||||
public void onSuccess(int code, String msg, String[] info) {
|
||||
if (code == 0 && info.length > 0 && mCurLikeCommentBean != null) {
|
||||
JSONObject obj = JSON.parseObject(info[0]);
|
||||
int like = obj.getIntValue("islike");
|
||||
String likeNum = obj.getString("likes");
|
||||
if (mCurLikeCommentBean != null) {
|
||||
mCurLikeCommentBean.setIsLike(like);
|
||||
mCurLikeCommentBean.setLikeNum(likeNum);
|
||||
notifyItemChanged(mCurLikeCommentPosition, Constants.PAYLOAD);
|
||||
}
|
||||
if (mCurLikeImageView != null && mLikeAnimation != null) {
|
||||
mCurLikeImageView.startAnimation(mLikeAnimation);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
mLikeClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Object tag = v.getTag();
|
||||
if (tag == null) {
|
||||
return;
|
||||
}
|
||||
VideoCommentBean bean = (VideoCommentBean) tag;
|
||||
String uid = bean.getUid();
|
||||
if (!TextUtils.isEmpty(uid) && uid.equals(CommonAppConfig.getInstance().getUid())) {
|
||||
ToastUtil.show(R.string.video_comment_cannot_self);
|
||||
return;
|
||||
}
|
||||
mCurLikeImageView = (ImageView) v;
|
||||
mCurLikeCommentPosition = bean.getPosition();
|
||||
mCurLikeCommentBean = bean;
|
||||
VideoHttpUtil.setCommentLike(bean.getId(), mLikeCommentCallback);
|
||||
}
|
||||
};
|
||||
mExpandClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Object tag = v.getTag();
|
||||
if (tag != null && mActionListener != null) {
|
||||
mActionListener.onExpandClicked((VideoCommentBean) tag);
|
||||
}
|
||||
}
|
||||
};
|
||||
mCollapsedClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Object tag = v.getTag();
|
||||
if (tag != null && mActionListener != null) {
|
||||
mActionListener.onCollapsedClicked((VideoCommentBean) tag);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
int count = 0;
|
||||
for (int i = 0, size = mList.size(); i < size; i++) {
|
||||
count++;
|
||||
List<VideoCommentBean> childList = mList.get(i).getChildList();
|
||||
if (childList != null) {
|
||||
count += childList.size();
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private VideoCommentBean getItem(int position) {
|
||||
int index = 0;
|
||||
for (int i = 0, size = mList.size(); i < size; i++) {
|
||||
VideoCommentBean parentNode = mList.get(i);
|
||||
if (index == position) {
|
||||
return parentNode;
|
||||
}
|
||||
index++;
|
||||
List<VideoCommentBean> childList = mList.get(i).getChildList();
|
||||
if (childList != null) {
|
||||
for (int j = 0, childSize = childList.size(); j < childSize; j++) {
|
||||
if (position == index) {
|
||||
return childList.get(j);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 展开子评论
|
||||
*
|
||||
* @param childNode 在这个子评论下面插入子评论
|
||||
* @param insertCount 插入的子评论的个数
|
||||
*/
|
||||
public void insertReplyList(VideoCommentBean childNode, int insertCount) {
|
||||
//这种方式也能达到 notifyItemRangeInserted 的效果,而且不容易出问题
|
||||
if (mRecyclerView != null) {
|
||||
mRecyclerView.scrollToPosition(childNode.getPosition());
|
||||
}
|
||||
//notifyItemRangeChanged(childNode.getPosition(), getItemCount(), Constants.PAYLOAD);
|
||||
notifyItemRangeChanged(childNode.getPosition(), getItemCount(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 收起子评论
|
||||
*
|
||||
* @param childNode 在这个子评论下面收起子评论
|
||||
* @param removeCount 被收起的子评论的个数
|
||||
*/
|
||||
public void removeReplyList(VideoCommentBean childNode, int removeCount) {
|
||||
//这种方式也能达到 notifyItemRangeRemoved 的效果,而且不容易出问题
|
||||
if (mRecyclerView != null) {
|
||||
mRecyclerView.scrollToPosition(childNode.getPosition());
|
||||
}
|
||||
//notifyItemRangeChanged(childNode.getPosition(), getItemCount(), Constants.PAYLOAD);
|
||||
notifyItemRangeChanged(childNode.getPosition(), getItemCount(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
VideoCommentBean bean = getItem(position);
|
||||
if (bean != null && bean.isParentNode()) {
|
||||
return PARENT;
|
||||
}
|
||||
return CHILD;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
if (viewType == PARENT) {
|
||||
return new ParentVh(mInflater.inflate(R.layout.item_video_comment_parent, parent, false));
|
||||
}
|
||||
return new ChildVh(mInflater.inflate(R.layout.item_video_comment_child, parent, false));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder vh, int position, @NonNull List payloads) {
|
||||
VideoCommentBean bean = getItem(position);
|
||||
if (bean != null) {
|
||||
bean.setPosition(position);
|
||||
Object payload = payloads.size() > 0 ? payloads.get(0) : null;
|
||||
if (vh instanceof ParentVh) {
|
||||
((ParentVh) vh).setData(bean, payload);
|
||||
} else if (vh instanceof ChildVh) {
|
||||
((ChildVh) vh).setData(bean, payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Vh extends RecyclerView.ViewHolder {
|
||||
|
||||
TextView mName;
|
||||
TextView mContent;
|
||||
TextView mTime, report;
|
||||
|
||||
public Vh(View itemView) {
|
||||
super(itemView);
|
||||
mName = (TextView) itemView.findViewById(R.id.name);
|
||||
mContent = (TextView) itemView.findViewById(R.id.content);
|
||||
mTime = (TextView) itemView.findViewById(R.id.time);
|
||||
itemView.setOnClickListener(mOnClickListener);
|
||||
itemView.setOnLongClickListener(mOnLongClickListener);
|
||||
|
||||
report = (TextView) itemView.findViewById(R.id.report);
|
||||
}
|
||||
|
||||
void setData(final VideoCommentBean bean, Object payload) {
|
||||
itemView.setTag(bean);
|
||||
if (payload == null) {
|
||||
UserBean u = bean.getUserBean();
|
||||
if (u != null) {
|
||||
mName.setText(u.getUserNiceName());
|
||||
}
|
||||
mContent.setText(VideoTextRender.renderVideoComment(bean.getContent(), ""));
|
||||
mTime.setText(bean.getDatetime());
|
||||
}
|
||||
|
||||
report.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
LiveReportActivity.forward(mContext, bean.getId());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class ParentVh extends Vh {
|
||||
|
||||
ImageView mBtnLike;
|
||||
TextView mLikeNum;
|
||||
ImageView mAvatar;
|
||||
|
||||
|
||||
public ParentVh(View itemView) {
|
||||
super(itemView);
|
||||
mBtnLike = (ImageView) itemView.findViewById(R.id.btn_like);
|
||||
mLikeNum = (TextView) itemView.findViewById(R.id.like_num);
|
||||
mBtnLike.setOnClickListener(mLikeClickListener);
|
||||
mAvatar = itemView.findViewById(R.id.avatar);
|
||||
}
|
||||
|
||||
void setData(VideoCommentBean bean, Object payload) {
|
||||
super.setData(bean, payload);
|
||||
if (payload == null) {
|
||||
UserBean u = bean.getUserBean();
|
||||
if (u != null) {
|
||||
ImgLoader.displayAvatar(mContext, u.getAvatar(), mAvatar);
|
||||
}
|
||||
}
|
||||
mBtnLike.setTag(bean);
|
||||
boolean like = bean.getIsLike() == 1;
|
||||
mBtnLike.setImageDrawable(like ? mLikeDrawable : mUnLikeDrawable);
|
||||
mLikeNum.setText(bean.getLikeNum());
|
||||
mLikeNum.setTextColor(like ? mLikeColor : mUnLikeColor);
|
||||
}
|
||||
}
|
||||
|
||||
class ChildVh extends Vh {
|
||||
|
||||
View mBtnGroup;
|
||||
View mBtnExpand;//展开按钮
|
||||
View mBtnbCollapsed;//收起按钮
|
||||
|
||||
public ChildVh(View itemView) {
|
||||
super(itemView);
|
||||
mBtnGroup = itemView.findViewById(R.id.btn_group);
|
||||
mBtnExpand = itemView.findViewById(R.id.btn_expand);
|
||||
mBtnbCollapsed = itemView.findViewById(R.id.btn_collapsed);
|
||||
mBtnExpand.setOnClickListener(mExpandClickListener);
|
||||
mBtnbCollapsed.setOnClickListener(mCollapsedClickListener);
|
||||
}
|
||||
|
||||
void setData(VideoCommentBean bean, Object payload) {
|
||||
super.setData(bean, payload);
|
||||
mBtnExpand.setTag(bean);
|
||||
mBtnbCollapsed.setTag(bean);
|
||||
VideoCommentBean parentNodeBean = bean.getParentNodeBean();
|
||||
if (bean.needShowExpand(parentNodeBean)) {
|
||||
if (mBtnGroup.getVisibility() != View.VISIBLE) {
|
||||
mBtnGroup.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (mBtnbCollapsed.getVisibility() == View.VISIBLE) {
|
||||
mBtnbCollapsed.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
if (mBtnExpand.getVisibility() != View.VISIBLE) {
|
||||
mBtnExpand.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else if (bean.needShowCollapsed(parentNodeBean)) {
|
||||
if (mBtnGroup.getVisibility() != View.VISIBLE) {
|
||||
mBtnGroup.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (mBtnExpand.getVisibility() == View.VISIBLE) {
|
||||
mBtnExpand.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
if (mBtnbCollapsed.getVisibility() != View.VISIBLE) {
|
||||
mBtnbCollapsed.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
if (mBtnGroup.getVisibility() == View.VISIBLE) {
|
||||
mBtnGroup.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface ActionListener {
|
||||
void onExpandClicked(VideoCommentBean commentBean);
|
||||
|
||||
void onCollapsedClicked(VideoCommentBean commentBean);
|
||||
}
|
||||
|
||||
public void setActionListener(ActionListener actionListener) {
|
||||
mActionListener = actionListener;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.yunbao.video.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.yunbao.common.Constants;
|
||||
import com.yunbao.common.bean.ConfigBean;
|
||||
import com.yunbao.video.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/10/19.
|
||||
* 视频发布分享
|
||||
*/
|
||||
|
||||
public class VideoPubShareAdapter extends RecyclerView.Adapter<VideoPubShareAdapter.Vh> {
|
||||
|
||||
// private List<MobBean> mList;
|
||||
private LayoutInflater mInflater;
|
||||
private View.OnClickListener mOnClickListener;
|
||||
private int mCheckedPosition;
|
||||
|
||||
public VideoPubShareAdapter(Context context, ConfigBean configBean) {
|
||||
// mList = new ArrayList<>();
|
||||
if (configBean != null) {
|
||||
// List<MobBean> list = MobBean.getVideoShareTypeList(configBean.getVideoShareTypes());
|
||||
// mList.addAll(list);
|
||||
}
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mCheckedPosition = -1;
|
||||
mOnClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Object tag = v.getTag();
|
||||
if (tag == null) {
|
||||
return;
|
||||
}
|
||||
int position = (int) tag;
|
||||
if (position == mCheckedPosition) {
|
||||
// mList.get(position).setChecked(false);
|
||||
notifyItemChanged(mCheckedPosition, Constants.PAYLOAD);
|
||||
mCheckedPosition = -1;
|
||||
return;
|
||||
}
|
||||
// if (mCheckedPosition >= 0 && mCheckedPosition < mList.size()) {
|
||||
// mList.get(mCheckedPosition).setChecked(false);
|
||||
// notifyItemChanged(mCheckedPosition, Constants.PAYLOAD);
|
||||
// }
|
||||
// MobBean bean = mList.get(position);
|
||||
// bean.setChecked(true);
|
||||
notifyItemChanged(position, Constants.PAYLOAD);
|
||||
mCheckedPosition = position;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Vh onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new Vh(mInflater.inflate(R.layout.item_video_pub_share, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull Vh vh, int position) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull Vh vh, int position, @NonNull List<Object> payloads) {
|
||||
Object payload = payloads.size() > 0 ? payloads.get(0) : null;
|
||||
// vh.setData(mList.get(position), position, payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
// return mList.size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
class Vh extends RecyclerView.ViewHolder {
|
||||
|
||||
ImageView mIcon;
|
||||
TextView mName;
|
||||
|
||||
public Vh(View itemView) {
|
||||
super(itemView);
|
||||
mIcon = (ImageView) itemView.findViewById(R.id.icon);
|
||||
mName = (TextView) itemView.findViewById(R.id.name);
|
||||
itemView.setOnClickListener(mOnClickListener);
|
||||
}
|
||||
|
||||
// void setData(MobBean bean, int position, Object payload) {
|
||||
// itemView.setTag(position);
|
||||
// if (payload == null) {
|
||||
// mName.setText(bean.getName());
|
||||
// }
|
||||
// mIcon.setImageResource(bean.isChecked() ? bean.getIcon1() : bean.getIcon2());
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
public String getShareType() {
|
||||
// if (mCheckedPosition >= 0 && mCheckedPosition < mList.size()) {
|
||||
// return mList.get(mCheckedPosition).getType();
|
||||
// }
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
package com.yunbao.video.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.yunbao.common.Constants;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.bean.VideoReportBean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/15.
|
||||
*/
|
||||
|
||||
public class VideoReportAdapter extends RecyclerView.Adapter {
|
||||
|
||||
private static final int HEAD = -1;
|
||||
private static final int FOOT = -2;
|
||||
private static final int NORMAL = 0;
|
||||
private static final int NORMAL_LAST = 1;
|
||||
|
||||
private List<VideoReportBean> mList;
|
||||
private LayoutInflater mInflater;
|
||||
private Drawable mCheckedDrawable;
|
||||
private Drawable mUnCheckedDrawable;
|
||||
private int mCheckedPosition;
|
||||
private View.OnClickListener mOnClickListener;
|
||||
private View.OnClickListener mReportListener;
|
||||
private FootVh mFootVh;
|
||||
private ActionListener mActionListener;
|
||||
private VideoReportBean mCurVideoReportBean;
|
||||
|
||||
public VideoReportAdapter(Context context, List<VideoReportBean> list) {
|
||||
mList = list;
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mCheckedDrawable = ContextCompat.getDrawable(context, R.mipmap.icon_cash_radio_1);
|
||||
mUnCheckedDrawable = ContextCompat.getDrawable(context, R.mipmap.icon_cash_radio_0);
|
||||
mCheckedPosition = -1;
|
||||
mOnClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Object tag = v.getTag();
|
||||
if (tag == null) {
|
||||
return;
|
||||
}
|
||||
int position = (int) tag;
|
||||
VideoReportBean bean = mList.get(position - 1);
|
||||
if (mCheckedPosition == position) {
|
||||
bean.setChecked(false);
|
||||
notifyItemChanged(position, Constants.PAYLOAD);
|
||||
mCheckedPosition = -1;
|
||||
mCurVideoReportBean = null;
|
||||
} else {
|
||||
if (mCheckedPosition >= 0) {
|
||||
mList.get(mCheckedPosition - 1).setChecked(false);
|
||||
notifyItemChanged(mCheckedPosition, Constants.PAYLOAD);
|
||||
}
|
||||
bean.setChecked(true);
|
||||
notifyItemChanged(position, Constants.PAYLOAD);
|
||||
mCheckedPosition = position;
|
||||
mCurVideoReportBean = bean;
|
||||
}
|
||||
}
|
||||
};
|
||||
mReportListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mFootVh != null) {
|
||||
mFootVh.submit();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
if (position == 0) {
|
||||
return HEAD;
|
||||
} else if (position == mList.size() + 1) {
|
||||
return FOOT;
|
||||
} else {
|
||||
if (position == mList.size()) {
|
||||
return NORMAL_LAST;
|
||||
}
|
||||
return NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
if (viewType == HEAD) {
|
||||
return new HeadVh(mInflater.inflate(R.layout.item_video_report_head, parent, false));
|
||||
} else if (viewType == FOOT) {
|
||||
if (mFootVh == null) {
|
||||
mFootVh = new FootVh(mInflater.inflate(R.layout.item_video_report_foot, parent, false));
|
||||
}
|
||||
return mFootVh;
|
||||
} else {
|
||||
if (viewType == NORMAL_LAST) {
|
||||
return new Vh(mInflater.inflate(R.layout.item_video_report_2, parent, false));
|
||||
}
|
||||
return new Vh(mInflater.inflate(R.layout.item_video_report, parent, false));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder vh, int position) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder vh, int position, @NonNull List payloads) {
|
||||
Object payload = payloads.size() > 0 ? payloads.get(0) : null;
|
||||
if (vh instanceof Vh) {
|
||||
((Vh) vh).setData(mList.get(position - 1), position, payload);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mList.size() + 2;
|
||||
}
|
||||
|
||||
class HeadVh extends RecyclerView.ViewHolder {
|
||||
|
||||
public HeadVh(View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
}
|
||||
|
||||
class FootVh extends RecyclerView.ViewHolder {
|
||||
|
||||
EditText mEditText;
|
||||
|
||||
public FootVh(View itemView) {
|
||||
super(itemView);
|
||||
mEditText = itemView.findViewById(R.id.edit);
|
||||
itemView.findViewById(R.id.btn_report).setOnClickListener(mReportListener);
|
||||
}
|
||||
|
||||
void submit() {
|
||||
String text = mEditText.getText().toString().trim();
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onReportClick(mCurVideoReportBean, text);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Vh extends RecyclerView.ViewHolder {
|
||||
|
||||
ImageView mImg;
|
||||
TextView mText;
|
||||
|
||||
public Vh(View itemView) {
|
||||
super(itemView);
|
||||
mImg = itemView.findViewById(R.id.img);
|
||||
mText = itemView.findViewById(R.id.text);
|
||||
itemView.setOnClickListener(mOnClickListener);
|
||||
}
|
||||
|
||||
void setData(VideoReportBean bean, int position, Object payload) {
|
||||
if (payload == null) {
|
||||
itemView.setTag(position);
|
||||
mText.setText(bean.getName());
|
||||
}
|
||||
mImg.setImageDrawable(bean.isChecked() ? mCheckedDrawable : mUnCheckedDrawable);
|
||||
}
|
||||
}
|
||||
|
||||
public interface ActionListener {
|
||||
void onReportClick(VideoReportBean bean, String text);
|
||||
}
|
||||
|
||||
public void setActionListener(ActionListener actionListener) {
|
||||
mActionListener = actionListener;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,408 @@
|
||||
package com.yunbao.video.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Handler;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.PagerSnapHelper;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.yunbao.common.custom.ItemSlideHelper;
|
||||
import com.yunbao.common.utils.ClickUtil;
|
||||
import com.yunbao.common.utils.ToastUtil;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.activity.AbsVideoPlayActivity;
|
||||
import com.yunbao.video.bean.VideoBean;
|
||||
import com.yunbao.video.utils.VideoIconUtil;
|
||||
import com.yunbao.video.views.VideoPlayWrapViewHolder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/11/27.
|
||||
*/
|
||||
|
||||
public class VideoScrollAdapter extends RecyclerView.Adapter<VideoScrollAdapter.Vh> implements ItemSlideHelper.Callback {
|
||||
|
||||
private static final String TAG = "VideoScrollAdapter";
|
||||
private static final int COUNT = 50;//接口每页返回多少条
|
||||
private Context mContext;
|
||||
private List<VideoBean> mList;
|
||||
private SparseArray<VideoPlayWrapViewHolder> mMap;
|
||||
private int mCurPosition;
|
||||
private ActionListener mActionListener;
|
||||
private boolean mFirstLoad;
|
||||
private RecyclerView mRecyclerView;
|
||||
private LinearLayoutManager mLayoutManager;
|
||||
private Drawable[] mLikeAnimDrawables;
|
||||
private Handler mHandler;
|
||||
|
||||
public VideoScrollAdapter(Context context, List<VideoBean> list, int curPosition) {
|
||||
mContext = context;
|
||||
mList = list;
|
||||
mCurPosition = curPosition;
|
||||
mMap = new SparseArray<>();
|
||||
mFirstLoad = true;
|
||||
List<Integer> likeImageList = VideoIconUtil.getVideoLikeAnim();//点赞帧动画
|
||||
mLikeAnimDrawables = new Drawable[likeImageList.size()];
|
||||
for (int i = 0, length = mLikeAnimDrawables.length; i < length; i++) {
|
||||
mLikeAnimDrawables[i] = ContextCompat.getDrawable(context, likeImageList.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
public void setActionListener(ActionListener actionListener) {
|
||||
mActionListener = actionListener;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Vh onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
VideoPlayWrapViewHolder vpvh = new VideoPlayWrapViewHolder(mContext, parent);
|
||||
vpvh.setLikeAnimDrawables(mLikeAnimDrawables);
|
||||
return new Vh(vpvh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull Vh vh, int position) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull Vh vh, int position, @NonNull List<Object> payloads) {
|
||||
Object payload = payloads.size() > 0 ? payloads.get(0) : null;
|
||||
vh.setData(mList.get(position), position, payload);
|
||||
if (mFirstLoad) {
|
||||
mFirstLoad = false;
|
||||
VideoPlayWrapViewHolder vpvh = mMap.get(mCurPosition);
|
||||
if (vpvh != null && mActionListener != null) {
|
||||
vpvh.onPageSelected();
|
||||
mActionListener.onPageSelected(vpvh, mList.size() >= COUNT && mCurPosition == mList.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onViewRecycled(@NonNull Vh vh) {
|
||||
vh.reycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mList.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 视频数据发生变化,更新item
|
||||
*/
|
||||
public void onVideoBeanChanged(String changedVideoId) {
|
||||
// if (TextUtils.isEmpty(changedVideoId)) {
|
||||
// return;
|
||||
// }
|
||||
// for (int i = 0, size = mList.size(); i < size; i++) {
|
||||
// VideoBean bean = mList.get(i);
|
||||
// if (bean != null) {
|
||||
// if (changedVideoId.equals(bean.getId())) {
|
||||
// notifyItemChanged(i, Constants.PAYLOAD);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除视频
|
||||
*/
|
||||
public void deleteVideo(VideoBean videoBean) {
|
||||
// if (videoBean == null) {
|
||||
// return;
|
||||
// }
|
||||
// String videoId = videoBean.getId();
|
||||
// if (TextUtils.isEmpty(videoId)) {
|
||||
// return;
|
||||
// }
|
||||
// for (int i = 0, size = mList.size(); i < size; i++) {
|
||||
// VideoBean bean = mList.get(i);
|
||||
// if (videoId.equals(bean.getId())) {
|
||||
// mList.remove(i);
|
||||
// notifyItemRemoved(i);
|
||||
// size = mList.size();
|
||||
// if (size > 0) {
|
||||
// notifyItemRangeChanged(i, size);
|
||||
// if (mHandler == null) {
|
||||
// mHandler = new Handler();
|
||||
// }
|
||||
// mHandler.postDelayed(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// mCurPosition = -1;
|
||||
// findCurVideo();
|
||||
// }
|
||||
// }, 500);
|
||||
// } else {
|
||||
// if (mActionListener != null) {
|
||||
// mActionListener.onVideoDeleteAll();
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* ItemSlideHelper回调
|
||||
*/
|
||||
@Override
|
||||
public int getHorizontalRange(RecyclerView.ViewHolder holder) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ItemSlideHelper回调
|
||||
*/
|
||||
@Override
|
||||
public RecyclerView.ViewHolder getChildViewHolder(View childView) {
|
||||
if (mRecyclerView != null && childView != null) {
|
||||
return mRecyclerView.getChildViewHolder(childView);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* ItemSlideHelper回调
|
||||
*/
|
||||
@Override
|
||||
public View findTargetView(float x, float y) {
|
||||
return mRecyclerView.findChildViewUnder(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useLeftScroll() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLeftScroll(RecyclerView.ViewHolder vh) {
|
||||
if (((AbsVideoPlayActivity) mContext).isPaused()) {
|
||||
return;
|
||||
}
|
||||
if (!ClickUtil.canClick()) {
|
||||
return;
|
||||
}
|
||||
if (vh != null) {
|
||||
VideoPlayWrapViewHolder vpvh = ((Vh) vh).mVideoPlayWrapViewHolder;
|
||||
if (vpvh != null) {
|
||||
vpvh.clickAvatar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Vh extends RecyclerView.ViewHolder {
|
||||
|
||||
VideoPlayWrapViewHolder mVideoPlayWrapViewHolder;
|
||||
|
||||
public Vh(VideoPlayWrapViewHolder videoPlayWrapViewHolder) {
|
||||
super(videoPlayWrapViewHolder.getContentView());
|
||||
mVideoPlayWrapViewHolder = videoPlayWrapViewHolder;
|
||||
}
|
||||
|
||||
void setData(VideoBean bean, int position, Object payload) {
|
||||
if (mVideoPlayWrapViewHolder != null) {
|
||||
mMap.put(position, mVideoPlayWrapViewHolder);
|
||||
mVideoPlayWrapViewHolder.setData(bean, payload);
|
||||
}
|
||||
}
|
||||
|
||||
void reycle() {
|
||||
if (mVideoPlayWrapViewHolder != null) {
|
||||
mVideoPlayWrapViewHolder.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(@NonNull Vh vh) {
|
||||
VideoPlayWrapViewHolder vpvh = vh.mVideoPlayWrapViewHolder;
|
||||
if (vpvh != null) {
|
||||
vpvh.onPageOutWindow();
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onPageOutWindow(vpvh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewAttachedToWindow(@NonNull Vh vh) {
|
||||
VideoPlayWrapViewHolder vpvh = vh.mVideoPlayWrapViewHolder;
|
||||
if (vpvh != null) {
|
||||
vpvh.onPageInWindow();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToRecyclerView(@NonNull final RecyclerView recyclerView) {
|
||||
mRecyclerView = recyclerView;
|
||||
mRecyclerView.addOnItemTouchListener(new ItemSlideHelper(mContext, this));
|
||||
mLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
|
||||
mLayoutManager.setInitialPrefetchItemCount(4);
|
||||
recyclerView.scrollToPosition(mCurPosition);
|
||||
PagerSnapHelper pagerSnapHelper = new PagerSnapHelper();
|
||||
pagerSnapHelper.attachToRecyclerView(recyclerView);
|
||||
recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
||||
findCurVideo();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void findCurVideo() {
|
||||
int position = mLayoutManager.findFirstCompletelyVisibleItemPosition();
|
||||
if (position >= 0 && mCurPosition != position) {
|
||||
if (mHandler != null) {
|
||||
mHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
VideoPlayWrapViewHolder vh = mMap.get(position);
|
||||
if (vh != null && mActionListener != null) {
|
||||
vh.onPageSelected();
|
||||
boolean needLoadMore = false;
|
||||
if (position == mList.size() - 1) {
|
||||
if (mList.size() < COUNT) {
|
||||
ToastUtil.show(R.string.video_no_more_video);
|
||||
} else {
|
||||
needLoadMore = true;
|
||||
}
|
||||
}
|
||||
mActionListener.onPageSelected(vh, needLoadMore);
|
||||
}
|
||||
mCurPosition = position;
|
||||
if (position == 0) {
|
||||
ToastUtil.show(R.string.video_scroll_top);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入数据
|
||||
*/
|
||||
public void insertList(List<VideoBean> list) {
|
||||
// if (list != null && list.size() > 0 && mList != null && mRecyclerView != null) {
|
||||
// int position = mList.size();
|
||||
// mList.addAll(list);
|
||||
// notifyItemRangeInserted(position, list.size());
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 刷新列表
|
||||
*/
|
||||
public void setList(List<VideoBean> list) {
|
||||
// if (list != null && list.size() > 0 && mList != null && mRecyclerView != null) {
|
||||
// mList.clear();
|
||||
// mList.addAll(list);
|
||||
// mFirstLoad = true;
|
||||
// mCurPosition = 0;
|
||||
// notifyDataSetChanged();
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* 关注发生变化
|
||||
*/
|
||||
public void onFollowChanged(boolean needExclude, String excludeVideoId, String toUid, int isAttention) {
|
||||
// if (mList != null && !TextUtils.isEmpty(toUid) && !TextUtils.isEmpty(excludeVideoId)) {
|
||||
// for (int i = 0, size = mList.size(); i < size; i++) {
|
||||
// VideoBean videoBean = mList.get(i);
|
||||
// if (videoBean != null) {
|
||||
// if (needExclude && excludeVideoId.equals(videoBean.getId())) {
|
||||
// continue;
|
||||
// }
|
||||
// if (toUid.equals(videoBean.getUid())) {
|
||||
// videoBean.setAttent(isAttention);
|
||||
// notifyItemChanged(i, Constants.PAYLOAD);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* 点赞发生变化
|
||||
*/
|
||||
public void onLikeChanged(boolean needExclude, String videoId, int like, String likeNum) {
|
||||
// if (mList != null && !TextUtils.isEmpty(videoId)) {
|
||||
// for (int i = 0, size = mList.size(); i < size; i++) {
|
||||
// VideoBean videoBean = mList.get(i);
|
||||
// if (videoBean != null && videoId.equals(videoBean.getId()) && !needExclude) {
|
||||
// videoBean.setLike(like);
|
||||
// videoBean.setLikeNum(likeNum);
|
||||
// notifyItemChanged(i, Constants.PAYLOAD);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* 评论数发生变化
|
||||
*/
|
||||
public void onCommentChanged(String videoId, String commentNum) {
|
||||
// if (mList != null && !TextUtils.isEmpty(videoId)) {
|
||||
// for (int i = 0, size = mList.size(); i < size; i++) {
|
||||
// VideoBean videoBean = mList.get(i);
|
||||
// if (videoBean != null && videoId.equals(videoBean.getId())) {
|
||||
// videoBean.setCommentNum(commentNum);
|
||||
// notifyItemChanged(i, Constants.PAYLOAD);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* 分享数发生变化
|
||||
*/
|
||||
public void onShareChanged(String videoId, String shareNum) {
|
||||
// if (mList != null && !TextUtils.isEmpty(videoId)) {
|
||||
// for (int i = 0, size = mList.size(); i < size; i++) {
|
||||
// VideoBean videoBean = mList.get(i);
|
||||
// if (videoBean != null && videoId.equals(videoBean.getId())) {
|
||||
// videoBean.setShareNum(shareNum);
|
||||
// notifyItemChanged(i, Constants.PAYLOAD);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
public void release() {
|
||||
mActionListener = null;
|
||||
if (mHandler != null) {
|
||||
mHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
mHandler = null;
|
||||
}
|
||||
|
||||
|
||||
public interface ActionListener {
|
||||
void onPageSelected(VideoPlayWrapViewHolder vh, boolean needLoadMore);
|
||||
|
||||
void onPageOutWindow(VideoPlayWrapViewHolder vh);
|
||||
|
||||
void onVideoDeleteAll();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.yunbao.video.adapter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.yunbao.video.R;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/10/19.
|
||||
* 视频分享
|
||||
*/
|
||||
|
||||
public class VideoShareAdapter extends RecyclerView.Adapter<VideoShareAdapter.Vh> {
|
||||
|
||||
// private List<MobBean> mList;
|
||||
private LayoutInflater mInflater;
|
||||
private View.OnClickListener mOnClickListener;
|
||||
// private OnItemClickListener<MobBean> mOnItemClickListener;
|
||||
|
||||
// public VideoShareAdapter(Context context, List<MobBean> list) {
|
||||
// mList = list;
|
||||
// mInflater = LayoutInflater.from(context);
|
||||
// mOnClickListener = new View.OnClickListener() {
|
||||
// @Override
|
||||
// public void onClick(View v) {
|
||||
// Object tag = v.getTag();
|
||||
// if (tag != null) {
|
||||
// if (mOnItemClickListener != null) {
|
||||
// mOnItemClickListener.onItemClick((MobBean) tag, 0);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
|
||||
// public void setOnItemClickListener(OnItemClickListener<MobBean> onItemClickListener) {
|
||||
// mOnItemClickListener = onItemClickListener;
|
||||
// }
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Vh onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new Vh(mInflater.inflate(R.layout.item_video_share, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull Vh vh, int position) {
|
||||
// vh.setData(mList.get(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
// return mList.size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
class Vh extends RecyclerView.ViewHolder {
|
||||
|
||||
ImageView mIcon;
|
||||
TextView mName;
|
||||
|
||||
public Vh(View itemView) {
|
||||
super(itemView);
|
||||
mIcon = (ImageView) itemView.findViewById(R.id.icon);
|
||||
mName = (TextView) itemView.findViewById(R.id.name);
|
||||
itemView.setOnClickListener(mOnClickListener);
|
||||
}
|
||||
|
||||
// void setData(MobBean bean) {
|
||||
// itemView.setTag(bean);
|
||||
// mIcon.setImageResource(bean.getIcon1());
|
||||
// mName.setText(bean.getName());
|
||||
// }
|
||||
}
|
||||
}
|
||||
169
video/src/main/java/com/yunbao/video/bean/MusicBean.java
Normal file
169
video/src/main/java/com/yunbao/video/bean/MusicBean.java
Normal file
@@ -0,0 +1,169 @@
|
||||
package com.yunbao.video.bean;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/6/20.
|
||||
*/
|
||||
|
||||
public class MusicBean implements Parcelable {
|
||||
private int id;
|
||||
private String title;
|
||||
private String author;
|
||||
private String imgUrl;
|
||||
private String length;
|
||||
private String fileUrl;
|
||||
private String useNum;
|
||||
private String localPath;//本地存储的路径
|
||||
private int collect;//是否收藏
|
||||
private boolean expand;
|
||||
private long mDuration;
|
||||
|
||||
public MusicBean() {
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
@JSONField(name = "img_url")
|
||||
public String getImgUrl() {
|
||||
return imgUrl;
|
||||
}
|
||||
|
||||
@JSONField(name = "img_url")
|
||||
public void setImgUrl(String imgUrl) {
|
||||
this.imgUrl = imgUrl;
|
||||
}
|
||||
|
||||
public String getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public void setLength(String length) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
@JSONField(name = "file_url")
|
||||
public String getFileUrl() {
|
||||
return fileUrl;
|
||||
}
|
||||
|
||||
@JSONField(name = "file_url")
|
||||
public void setFileUrl(String fileUrl) {
|
||||
this.fileUrl = fileUrl;
|
||||
}
|
||||
|
||||
@JSONField(name = "use_nums")
|
||||
public String getUseNum() {
|
||||
return useNum;
|
||||
}
|
||||
|
||||
@JSONField(name = "use_nums")
|
||||
public void setUseNum(String useNum) {
|
||||
this.useNum = useNum;
|
||||
}
|
||||
|
||||
|
||||
public String getLocalPath() {
|
||||
return localPath;
|
||||
}
|
||||
|
||||
public void setLocalPath(String localPath) {
|
||||
this.localPath = localPath;
|
||||
}
|
||||
|
||||
public boolean isExpand() {
|
||||
return expand;
|
||||
}
|
||||
|
||||
public void setExpand(boolean expand) {
|
||||
this.expand = expand;
|
||||
}
|
||||
|
||||
@JSONField(name = "iscollect")
|
||||
public int getCollect() {
|
||||
return collect;
|
||||
}
|
||||
|
||||
@JSONField(name = "iscollect")
|
||||
public void setCollect(int collect) {
|
||||
this.collect = collect;
|
||||
}
|
||||
|
||||
public long getDuration() {
|
||||
return mDuration;
|
||||
}
|
||||
|
||||
public void setDuration(long duration) {
|
||||
mDuration = duration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public MusicBean(Parcel in) {
|
||||
this.id = in.readInt();
|
||||
this.title = in.readString();
|
||||
this.author = in.readString();
|
||||
this.imgUrl = in.readString();
|
||||
this.length = in.readString();
|
||||
this.fileUrl = in.readString();
|
||||
this.useNum = in.readString();
|
||||
this.localPath = in.readString();
|
||||
this.collect = in.readInt();
|
||||
this.mDuration=in.readLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(this.id);
|
||||
dest.writeString(this.title);
|
||||
dest.writeString(this.author);
|
||||
dest.writeString(this.imgUrl);
|
||||
dest.writeString(this.length);
|
||||
dest.writeString(this.fileUrl);
|
||||
dest.writeString(this.useNum);
|
||||
dest.writeString(this.localPath);
|
||||
dest.writeInt(this.collect);
|
||||
dest.writeLong(this.mDuration);
|
||||
}
|
||||
|
||||
public static final Creator<MusicBean> CREATOR = new Creator<MusicBean>() {
|
||||
@Override
|
||||
public MusicBean[] newArray(int size) {
|
||||
return new MusicBean[size];
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicBean createFromParcel(Parcel in) {
|
||||
return new MusicBean(in);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.yunbao.video.bean;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/7/26.
|
||||
*/
|
||||
|
||||
public class MusicClassBean {
|
||||
private String id;
|
||||
private String title;
|
||||
private String img_url;
|
||||
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getImg_url() {
|
||||
return img_url;
|
||||
}
|
||||
|
||||
public void setImg_url(String img_url) {
|
||||
this.img_url = img_url;
|
||||
}
|
||||
}
|
||||
351
video/src/main/java/com/yunbao/video/bean/VideoBean.java
Normal file
351
video/src/main/java/com/yunbao/video/bean/VideoBean.java
Normal file
@@ -0,0 +1,351 @@
|
||||
package com.yunbao.video.bean;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.yunbao.common.bean.UserBean;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2017/10/25.
|
||||
*/
|
||||
|
||||
public class VideoBean implements Parcelable {
|
||||
private String id;
|
||||
private String uid;
|
||||
private String title;
|
||||
private String thumb;
|
||||
private String thumbs;
|
||||
private String href;
|
||||
private String likeNum;
|
||||
private String viewNum;
|
||||
private String commentNum;
|
||||
private String stepNum;
|
||||
private String shareNum;
|
||||
private String addtime;
|
||||
private String lat;
|
||||
private String lng;
|
||||
private String city;
|
||||
private UserBean userBean;
|
||||
private String datetime;
|
||||
private String distance;
|
||||
private int step;//是否踩过
|
||||
private int like;//是否赞过
|
||||
private int attent;//是否关注过作者
|
||||
private int status;
|
||||
private int musicId;
|
||||
private MusicBean musicInfo;
|
||||
|
||||
public VideoBean() {
|
||||
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setUid(String uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getThumb() {
|
||||
return thumb;
|
||||
}
|
||||
|
||||
public void setThumb(String thumb) {
|
||||
this.thumb = thumb;
|
||||
}
|
||||
|
||||
@JSONField(name = "thumb_s")
|
||||
public String getThumbs() {
|
||||
return thumbs;
|
||||
}
|
||||
|
||||
@JSONField(name = "thumb_s")
|
||||
public void setThumbs(String thumbs) {
|
||||
this.thumbs = thumbs;
|
||||
}
|
||||
|
||||
public String getHref() {
|
||||
return href;
|
||||
}
|
||||
|
||||
public void setHref(String href) {
|
||||
this.href = href;
|
||||
}
|
||||
|
||||
@JSONField(name = "likes")
|
||||
public String getLikeNum() {
|
||||
return likeNum;
|
||||
}
|
||||
|
||||
@JSONField(name = "likes")
|
||||
public void setLikeNum(String likeNum) {
|
||||
this.likeNum = likeNum;
|
||||
}
|
||||
|
||||
@JSONField(name = "views")
|
||||
public String getViewNum() {
|
||||
return viewNum;
|
||||
}
|
||||
|
||||
@JSONField(name = "views")
|
||||
public void setViewNum(String viewNum) {
|
||||
this.viewNum = viewNum;
|
||||
}
|
||||
|
||||
@JSONField(name = "comments")
|
||||
public String getCommentNum() {
|
||||
return commentNum;
|
||||
}
|
||||
|
||||
@JSONField(name = "comments")
|
||||
public void setCommentNum(String commentNum) {
|
||||
this.commentNum = commentNum;
|
||||
}
|
||||
|
||||
@JSONField(name = "steps")
|
||||
public String getStepNum() {
|
||||
return stepNum;
|
||||
}
|
||||
|
||||
@JSONField(name = "steps")
|
||||
public void setStepNum(String stepNum) {
|
||||
this.stepNum = stepNum;
|
||||
}
|
||||
|
||||
@JSONField(name = "shares")
|
||||
public String getShareNum() {
|
||||
return shareNum;
|
||||
}
|
||||
|
||||
@JSONField(name = "shares")
|
||||
public void setShareNum(String shareNum) {
|
||||
this.shareNum = shareNum;
|
||||
}
|
||||
|
||||
public String getAddtime() {
|
||||
return addtime;
|
||||
}
|
||||
|
||||
public void setAddtime(String addtime) {
|
||||
this.addtime = addtime;
|
||||
}
|
||||
|
||||
public String getLat() {
|
||||
return lat;
|
||||
}
|
||||
|
||||
public void setLat(String lat) {
|
||||
this.lat = lat;
|
||||
}
|
||||
|
||||
public String getLng() {
|
||||
return lng;
|
||||
}
|
||||
|
||||
public void setLng(String lng) {
|
||||
this.lng = lng;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
|
||||
@JSONField(name = "userinfo")
|
||||
public UserBean getUserBean() {
|
||||
return userBean;
|
||||
}
|
||||
|
||||
@JSONField(name = "userinfo")
|
||||
public void setUserBean(UserBean userBean) {
|
||||
this.userBean = userBean;
|
||||
}
|
||||
|
||||
public String getDatetime() {
|
||||
return datetime;
|
||||
}
|
||||
|
||||
public void setDatetime(String datetime) {
|
||||
this.datetime = datetime;
|
||||
}
|
||||
|
||||
@JSONField(name = "isstep")
|
||||
public int getStep() {
|
||||
return step;
|
||||
}
|
||||
|
||||
@JSONField(name = "isstep")
|
||||
public void setStep(int step) {
|
||||
this.step = step;
|
||||
}
|
||||
|
||||
@JSONField(name = "islike")
|
||||
public int getLike() {
|
||||
return like;
|
||||
}
|
||||
|
||||
@JSONField(name = "islike")
|
||||
public void setLike(int like) {
|
||||
this.like = like;
|
||||
}
|
||||
|
||||
@JSONField(name = "isattent")
|
||||
public int getAttent() {
|
||||
return attent;
|
||||
}
|
||||
|
||||
@JSONField(name = "isattent")
|
||||
public void setAttent(int attent) {
|
||||
this.attent = attent;
|
||||
}
|
||||
|
||||
public String getDistance() {
|
||||
return distance;
|
||||
}
|
||||
|
||||
public void setDistance(String distance) {
|
||||
this.distance = distance;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
@JSONField(name = "music_id")
|
||||
public int getMusicId() {
|
||||
return musicId;
|
||||
}
|
||||
|
||||
@JSONField(name = "music_id")
|
||||
public void setMusicId(int musicId) {
|
||||
this.musicId = musicId;
|
||||
}
|
||||
|
||||
@JSONField(name = "musicinfo")
|
||||
public MusicBean getMusicInfo() {
|
||||
return musicInfo;
|
||||
}
|
||||
|
||||
@JSONField(name = "musicinfo")
|
||||
public void setMusicInfo(MusicBean musicInfo) {
|
||||
this.musicInfo = musicInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(this.id);
|
||||
dest.writeString(this.uid);
|
||||
dest.writeString(this.title);
|
||||
dest.writeString(this.thumb);
|
||||
dest.writeString(this.thumbs);
|
||||
dest.writeString(this.href);
|
||||
dest.writeString(this.likeNum);
|
||||
dest.writeString(this.viewNum);
|
||||
dest.writeString(this.commentNum);
|
||||
dest.writeString(this.stepNum);
|
||||
dest.writeString(this.shareNum);
|
||||
dest.writeString(this.addtime);
|
||||
dest.writeString(this.lat);
|
||||
dest.writeString(this.lng);
|
||||
dest.writeString(this.city);
|
||||
dest.writeString(this.datetime);
|
||||
dest.writeInt(this.like);
|
||||
dest.writeInt(this.attent);
|
||||
dest.writeString(this.distance);
|
||||
dest.writeInt(this.step);
|
||||
dest.writeParcelable(this.userBean, flags);
|
||||
dest.writeInt(this.status);
|
||||
dest.writeInt(this.musicId);
|
||||
dest.writeParcelable(this.musicInfo, flags);
|
||||
}
|
||||
|
||||
|
||||
public VideoBean(Parcel in) {
|
||||
this.id = in.readString();
|
||||
this.uid = in.readString();
|
||||
this.title = in.readString();
|
||||
this.thumb = in.readString();
|
||||
this.thumbs = in.readString();
|
||||
this.href = in.readString();
|
||||
this.likeNum = in.readString();
|
||||
this.viewNum = in.readString();
|
||||
this.commentNum = in.readString();
|
||||
this.stepNum = in.readString();
|
||||
this.shareNum = in.readString();
|
||||
this.addtime = in.readString();
|
||||
this.lat = in.readString();
|
||||
this.lng = in.readString();
|
||||
this.city = in.readString();
|
||||
this.datetime = in.readString();
|
||||
this.like = in.readInt();
|
||||
this.attent = in.readInt();
|
||||
this.distance = in.readString();
|
||||
this.step = in.readInt();
|
||||
this.userBean = in.readParcelable(UserBean.class.getClassLoader());
|
||||
this.status = in.readInt();
|
||||
this.musicId = in.readInt();
|
||||
this.musicInfo = in.readParcelable(MusicBean.class.getClassLoader());
|
||||
}
|
||||
|
||||
|
||||
public static final Creator<VideoBean> CREATOR = new Creator<VideoBean>() {
|
||||
@Override
|
||||
public VideoBean[] newArray(int size) {
|
||||
return new VideoBean[size];
|
||||
}
|
||||
|
||||
@Override
|
||||
public VideoBean createFromParcel(Parcel in) {
|
||||
return new VideoBean(in);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VideoBean{" +
|
||||
"title='" + title + '\'' +
|
||||
",href='" + href + '\'' +
|
||||
",id='" + id + '\'' +
|
||||
",uid='" + uid + '\'' +
|
||||
",userNiceName='" + userBean.getUserNiceName() + '\'' +
|
||||
",thumb='" + thumb + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
||||
public String getTag() {
|
||||
return "VideoBean" + this.getId() + this.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.yunbao.video.bean;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/6/20.
|
||||
* 选择视频的实体类
|
||||
*/
|
||||
|
||||
public class VideoChooseBean {
|
||||
|
||||
private String videoPath;
|
||||
private String videoName;
|
||||
private String coverPath;
|
||||
private long duration;
|
||||
private String durationString;
|
||||
|
||||
public VideoChooseBean() {
|
||||
}
|
||||
|
||||
public VideoChooseBean(String videoPath, String videoName, String coverPath, long duration, String durationString) {
|
||||
this.videoPath = videoPath;
|
||||
this.videoName = videoName;
|
||||
this.coverPath = coverPath;
|
||||
this.duration = duration;
|
||||
this.durationString = durationString;
|
||||
}
|
||||
|
||||
public String getVideoPath() {
|
||||
return videoPath;
|
||||
}
|
||||
|
||||
public void setVideoPath(String videoPath) {
|
||||
this.videoPath = videoPath;
|
||||
}
|
||||
|
||||
public String getVideoName() {
|
||||
return videoName;
|
||||
}
|
||||
|
||||
public void setVideoName(String videoName) {
|
||||
this.videoName = videoName;
|
||||
}
|
||||
|
||||
public String getCoverPath() {
|
||||
return coverPath;
|
||||
}
|
||||
|
||||
public void setCoverPath(String coverPath) {
|
||||
this.coverPath = coverPath;
|
||||
}
|
||||
|
||||
public long getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public void setDuration(long duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public String getDurationString() {
|
||||
return durationString;
|
||||
}
|
||||
|
||||
public void setDurationString(String durationString) {
|
||||
this.durationString = durationString;
|
||||
}
|
||||
}
|
||||
360
video/src/main/java/com/yunbao/video/bean/VideoCommentBean.java
Normal file
360
video/src/main/java/com/yunbao/video/bean/VideoCommentBean.java
Normal file
@@ -0,0 +1,360 @@
|
||||
package com.yunbao.video.bean;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.yunbao.common.bean.UserBean;
|
||||
import com.yunbao.common.utils.WordUtil;
|
||||
import com.yunbao.video.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Created by cxf on 2017/7/14.
|
||||
*/
|
||||
|
||||
public class VideoCommentBean implements Parcelable {
|
||||
|
||||
private static final String REPLY = WordUtil.getString(R.string.video_comment_reply) + " ";
|
||||
|
||||
private String mId;
|
||||
private String mUid;
|
||||
private String mToUid;
|
||||
private String mVideoId;
|
||||
private String mCommentId;
|
||||
private String mParentId;
|
||||
private String mContent;
|
||||
private String mLikeNum;
|
||||
private String mAddTime;
|
||||
private String mAtInfo;
|
||||
private int mIsLike;
|
||||
private int mReplyNum;
|
||||
private String mDatetime;
|
||||
private UserBean mUserBean;
|
||||
private UserBean mToUserBean;
|
||||
private List<VideoCommentBean> mChildList;
|
||||
private boolean mParentNode;//是否是父元素
|
||||
private int mPosition;
|
||||
private VideoCommentBean mParentNodeBean;
|
||||
private int mChildPage = 1;
|
||||
|
||||
public VideoCommentBean() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@JSONField(name = "id")
|
||||
public String getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
@JSONField(name = "id")
|
||||
public void setId(String id) {
|
||||
mId = id;
|
||||
}
|
||||
|
||||
@JSONField(name = "uid")
|
||||
public String getUid() {
|
||||
return mUid;
|
||||
}
|
||||
|
||||
@JSONField(name = "uid")
|
||||
public void setUid(String uid) {
|
||||
mUid = uid;
|
||||
}
|
||||
|
||||
@JSONField(name = "touid")
|
||||
public String getToUid() {
|
||||
return mToUid;
|
||||
}
|
||||
|
||||
@JSONField(name = "touid")
|
||||
public void setToUid(String toUid) {
|
||||
mToUid = toUid;
|
||||
}
|
||||
|
||||
@JSONField(name = "videoid")
|
||||
public String getVideoId() {
|
||||
return mVideoId;
|
||||
}
|
||||
|
||||
@JSONField(name = "videoid")
|
||||
public void setVideoId(String videoId) {
|
||||
mVideoId = videoId;
|
||||
}
|
||||
|
||||
@JSONField(name = "commentid")
|
||||
public String getCommentId() {
|
||||
return mCommentId;
|
||||
}
|
||||
|
||||
@JSONField(name = "commentid")
|
||||
public void setCommentId(String commentId) {
|
||||
mCommentId = commentId;
|
||||
}
|
||||
|
||||
@JSONField(name = "parentid")
|
||||
public String getParentId() {
|
||||
return mParentId;
|
||||
}
|
||||
|
||||
@JSONField(name = "parentid")
|
||||
public void setParentId(String parentId) {
|
||||
mParentId = parentId;
|
||||
}
|
||||
|
||||
@JSONField(name = "content")
|
||||
public String getContent() {
|
||||
if (!mParentNode && this.mToUserBean != null && !TextUtils.isEmpty(mToUserBean.getId())) {
|
||||
String userName = mToUserBean.getUserNiceName();
|
||||
if (!TextUtils.isEmpty(userName)) {
|
||||
return REPLY + userName + " : " + mContent;
|
||||
}
|
||||
}
|
||||
return mContent;
|
||||
}
|
||||
|
||||
@JSONField(name = "content")
|
||||
public void setContent(String content) {
|
||||
mContent = content;
|
||||
}
|
||||
|
||||
|
||||
@JSONField(name = "likes")
|
||||
public String getLikeNum() {
|
||||
return mLikeNum;
|
||||
}
|
||||
|
||||
@JSONField(name = "likes")
|
||||
public void setLikeNum(String likeNum) {
|
||||
mLikeNum = likeNum;
|
||||
}
|
||||
|
||||
@JSONField(name = "addtime")
|
||||
public String getAddTime() {
|
||||
return mAddTime;
|
||||
}
|
||||
|
||||
@JSONField(name = "addtime")
|
||||
public void setAddTime(String addTime) {
|
||||
mAddTime = addTime;
|
||||
}
|
||||
|
||||
@JSONField(name = "userinfo")
|
||||
public UserBean getUserBean() {
|
||||
return mUserBean;
|
||||
}
|
||||
|
||||
@JSONField(name = "userinfo")
|
||||
public void setUserBean(UserBean userBean) {
|
||||
mUserBean = userBean;
|
||||
}
|
||||
|
||||
@JSONField(name = "datetime")
|
||||
public String getDatetime() {
|
||||
return mDatetime;
|
||||
}
|
||||
|
||||
@JSONField(name = "datetime")
|
||||
public void setDatetime(String datetime) {
|
||||
mDatetime = datetime;
|
||||
}
|
||||
|
||||
@JSONField(name = "islike")
|
||||
public int getIsLike() {
|
||||
return mIsLike;
|
||||
}
|
||||
|
||||
@JSONField(name = "islike")
|
||||
public void setIsLike(int like) {
|
||||
mIsLike = like;
|
||||
}
|
||||
|
||||
@JSONField(name = "at_info")
|
||||
public String getAtInfo() {
|
||||
return mAtInfo;
|
||||
}
|
||||
|
||||
@JSONField(name = "at_info")
|
||||
public void setAtInfo(String atInfo) {
|
||||
mAtInfo = atInfo;
|
||||
}
|
||||
|
||||
|
||||
@JSONField(name = "touserinfo")
|
||||
public UserBean getToUserBean() {
|
||||
return mToUserBean;
|
||||
}
|
||||
|
||||
@JSONField(name = "touserinfo")
|
||||
public void setToUserBean(UserBean toUserBean) {
|
||||
mToUserBean = toUserBean;
|
||||
}
|
||||
|
||||
@JSONField(name = "replys")
|
||||
public int getReplyNum() {
|
||||
return mReplyNum;
|
||||
}
|
||||
|
||||
@JSONField(name = "replys")
|
||||
public void setReplyNum(int replyNum) {
|
||||
mReplyNum = replyNum;
|
||||
}
|
||||
|
||||
|
||||
@JSONField(name = "replylist")
|
||||
public List<VideoCommentBean> getChildList() {
|
||||
return mChildList;
|
||||
}
|
||||
|
||||
@JSONField(name = "replylist")
|
||||
public void setChildList(List<VideoCommentBean> childList) {
|
||||
mChildList = childList;
|
||||
for (VideoCommentBean bean : childList) {
|
||||
if (bean != null) {
|
||||
bean.setParentNodeBean(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public VideoCommentBean getParentNodeBean() {
|
||||
return mParentNodeBean;
|
||||
}
|
||||
|
||||
public void setParentNodeBean(VideoCommentBean parentNodeBean) {
|
||||
mParentNodeBean = parentNodeBean;
|
||||
}
|
||||
|
||||
public boolean isParentNode() {
|
||||
return mParentNode;
|
||||
}
|
||||
|
||||
public void setParentNode(boolean parentNode) {
|
||||
mParentNode = parentNode;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return mPosition;
|
||||
}
|
||||
|
||||
public void setPosition(int position) {
|
||||
mPosition = position;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public int getChildPage() {
|
||||
return mChildPage;
|
||||
}
|
||||
@JSONField(serialize = false)
|
||||
public void setChildPage(int childPage) {
|
||||
mChildPage = childPage;
|
||||
}
|
||||
|
||||
public boolean isFirstChild(VideoCommentBean parentNodeBean) {
|
||||
if (!mParentNode && parentNodeBean != null) {
|
||||
List<VideoCommentBean> parentChildList = parentNodeBean.getChildList();
|
||||
if (parentChildList != null && parentChildList.size() > 0) {
|
||||
return this == parentChildList.get(0);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public boolean needShowExpand(VideoCommentBean parentNodeBean) {
|
||||
if (!mParentNode && parentNodeBean != null) {
|
||||
List<VideoCommentBean> parentChildList = parentNodeBean.getChildList();
|
||||
if (parentChildList != null) {
|
||||
int size = parentChildList.size();
|
||||
if (parentNodeBean.getReplyNum() > 1 && parentNodeBean.getReplyNum() > size && this == parentChildList.get(size - 1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public boolean needShowCollapsed(VideoCommentBean parentNodeBean) {
|
||||
if (!mParentNode && parentNodeBean != null) {
|
||||
List<VideoCommentBean> parentChildList = parentNodeBean.getChildList();
|
||||
if (parentChildList != null) {
|
||||
int size = parentChildList.size();
|
||||
if (size > 1 && size >= parentNodeBean.getReplyNum() && this == parentChildList.get(size - 1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void removeChild() {
|
||||
if (mChildList != null && mChildList.size() > 1) {
|
||||
mChildList = mChildList.subList(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(mId);
|
||||
dest.writeString(mUid);
|
||||
dest.writeString(mToUid);
|
||||
dest.writeString(mVideoId);
|
||||
dest.writeString(mCommentId);
|
||||
dest.writeString(mParentId);
|
||||
dest.writeString(mContent);
|
||||
dest.writeString(mLikeNum);
|
||||
dest.writeString(mAddTime);
|
||||
dest.writeString(mAtInfo);
|
||||
dest.writeInt(mIsLike);
|
||||
dest.writeInt(mReplyNum);
|
||||
dest.writeString(mDatetime);
|
||||
dest.writeParcelable(mUserBean, flags);
|
||||
dest.writeParcelable(mToUserBean, flags);
|
||||
dest.writeTypedList(mChildList);
|
||||
dest.writeByte((byte) (mParentNode ? 1 : 0));
|
||||
dest.writeInt(mPosition);
|
||||
}
|
||||
|
||||
public VideoCommentBean(Parcel in) {
|
||||
mId = in.readString();
|
||||
mUid = in.readString();
|
||||
mToUid = in.readString();
|
||||
mVideoId = in.readString();
|
||||
mCommentId = in.readString();
|
||||
mParentId = in.readString();
|
||||
mContent = in.readString();
|
||||
mLikeNum = in.readString();
|
||||
mAddTime = in.readString();
|
||||
mAtInfo = in.readString();
|
||||
mIsLike = in.readInt();
|
||||
mReplyNum = in.readInt();
|
||||
mDatetime = in.readString();
|
||||
mUserBean = in.readParcelable(UserBean.class.getClassLoader());
|
||||
mToUserBean = in.readParcelable(UserBean.class.getClassLoader());
|
||||
mChildList = in.createTypedArrayList(VideoCommentBean.CREATOR);
|
||||
mParentNode = in.readByte() != 0;
|
||||
mPosition = in.readInt();
|
||||
}
|
||||
|
||||
public static final Creator<VideoCommentBean> CREATOR = new Creator<VideoCommentBean>() {
|
||||
@Override
|
||||
public VideoCommentBean createFromParcel(Parcel in) {
|
||||
return new VideoCommentBean(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VideoCommentBean[] newArray(int size) {
|
||||
return new VideoCommentBean[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.yunbao.video.bean;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/15.
|
||||
*/
|
||||
|
||||
public class VideoReportBean {
|
||||
|
||||
private String id;
|
||||
private String name;
|
||||
private boolean checked;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public boolean isChecked() {
|
||||
return checked;
|
||||
}
|
||||
|
||||
public void setChecked(boolean checked) {
|
||||
this.checked = checked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VideoReportBean{" +
|
||||
"id='" + id + '\'' +
|
||||
", name='" + name + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package com.yunbao.video.custom;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by vinsonswang on 2017/11/9.
|
||||
*/
|
||||
|
||||
public class ColorfulProgress extends View {
|
||||
|
||||
private Paint mPaint;
|
||||
private Paint mColorPaint;
|
||||
|
||||
private RectF mViewRectf;
|
||||
private RectF mColorRectf;
|
||||
private float mWidth;
|
||||
private float mHeight;
|
||||
|
||||
private List<MarkInfo> mMarkInfoList;
|
||||
private float mCurPositioin;
|
||||
|
||||
private VideoProgressController mVideoProgressController;
|
||||
|
||||
public ColorfulProgress(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
public ColorfulProgress(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public ColorfulProgress(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init(){
|
||||
mPaint = new Paint();
|
||||
mColorPaint = new Paint();
|
||||
mViewRectf = new RectF();
|
||||
mColorRectf = new RectF();
|
||||
|
||||
mPaint.setAntiAlias(true);
|
||||
mColorPaint.setAntiAlias(true);
|
||||
|
||||
mPaint.setColor(0x00000000);
|
||||
|
||||
mMarkInfoList = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void setVideoProgressController(VideoProgressController videoProgressController){
|
||||
mVideoProgressController = videoProgressController;
|
||||
}
|
||||
|
||||
public void setWidthHeight(float width, float height){
|
||||
mViewRectf.left = 0;
|
||||
mViewRectf.top = 0;
|
||||
mViewRectf.right = width;
|
||||
mViewRectf.bottom = height;
|
||||
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param curPosition
|
||||
*/
|
||||
public void setCurPosition(float curPosition) {
|
||||
mCurPositioin = curPosition;
|
||||
// mCurTimeUs = mVideoProgressController.distance2Duration(mCurPositioin);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始标记
|
||||
*
|
||||
* @param color
|
||||
*/
|
||||
public void startMark(int color) {
|
||||
MarkInfo info = new MarkInfo();
|
||||
info.startTimeMs = mVideoProgressController.getCurrentTimeMs();
|
||||
info.left = mCurPositioin;
|
||||
info.color = color;
|
||||
mMarkInfoList.add(info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束标记
|
||||
*/
|
||||
public void endMark() {
|
||||
MarkInfo info = mMarkInfoList.get(mMarkInfoList.size() - 1);
|
||||
info.right = mCurPositioin;
|
||||
}
|
||||
|
||||
public MarkInfo deleteLastMark() {
|
||||
MarkInfo info = null;
|
||||
if (mMarkInfoList != null && mMarkInfoList.size() != 0) {
|
||||
info = mMarkInfoList.remove(mMarkInfoList.size() - 1);
|
||||
invalidate();
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
public int getMarkListSize() {
|
||||
return mMarkInfoList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
drawView(canvas);
|
||||
|
||||
drawMarkInfo(canvas);
|
||||
}
|
||||
|
||||
private void drawMarkInfo(Canvas canvas) {
|
||||
for (MarkInfo info : mMarkInfoList) {
|
||||
mColorPaint.setColor(info.color);
|
||||
mColorRectf.left = info.left;
|
||||
mColorRectf.top = 0;
|
||||
mColorRectf.bottom = mHeight;
|
||||
mColorRectf.right = info.right == -1 ? mCurPositioin : info.right;
|
||||
|
||||
if (mColorRectf.left > mColorRectf.right) {
|
||||
float tmp = mColorRectf.left;
|
||||
mColorRectf.left = mColorRectf.right;
|
||||
mColorRectf.right = tmp;
|
||||
}
|
||||
|
||||
canvas.drawRect(mColorRectf, mColorPaint);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawView(Canvas canvas){
|
||||
canvas.drawRect(mViewRectf, mPaint);
|
||||
}
|
||||
|
||||
public class MarkInfo {
|
||||
public int color;
|
||||
public long startTimeMs;
|
||||
public float left = -1;
|
||||
private float right = -1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,502 @@
|
||||
package com.yunbao.video.custom;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import com.yunbao.video.R;
|
||||
|
||||
|
||||
public class NumberProgressBar extends View {
|
||||
|
||||
private long mMaxProgress = 100;
|
||||
|
||||
/**
|
||||
* Current progress, can not exceed the max progress.
|
||||
*/
|
||||
private long mCurrentProgress = 0;
|
||||
|
||||
/**
|
||||
* The progress area bar color.
|
||||
*/
|
||||
private int mReachedBarColor;
|
||||
|
||||
/**
|
||||
* The bar unreached area color.
|
||||
*/
|
||||
private int mUnreachedBarColor;
|
||||
|
||||
/**
|
||||
* The progress text color.
|
||||
*/
|
||||
private int mTextColor;
|
||||
|
||||
/**
|
||||
* The progress text size.
|
||||
*/
|
||||
private float mTextSize;
|
||||
|
||||
/**
|
||||
* The height of the reached area.
|
||||
*/
|
||||
private float mReachedBarHeight;
|
||||
|
||||
/**
|
||||
* The height of the unreached area.
|
||||
*/
|
||||
private float mUnreachedBarHeight;
|
||||
|
||||
/**
|
||||
* The suffix of the number.
|
||||
*/
|
||||
private String mSuffix = "%";
|
||||
|
||||
/**
|
||||
* The prefix.
|
||||
*/
|
||||
private String mPrefix = "";
|
||||
|
||||
|
||||
private final int default_text_color = Color.rgb(66, 145, 241);
|
||||
private final int default_reached_color = Color.rgb(66, 145, 241);
|
||||
private final int default_unreached_color = Color.rgb(204, 204, 204);
|
||||
private final float default_progress_text_offset;
|
||||
private final float default_text_size;
|
||||
private final float default_reached_bar_height;
|
||||
private final float default_unreached_bar_height;
|
||||
|
||||
/**
|
||||
* For save and restore instance of progressbar.
|
||||
*/
|
||||
private static final String INSTANCE_STATE = "saved_instance";
|
||||
private static final String INSTANCE_TEXT_COLOR = "text_color";
|
||||
private static final String INSTANCE_TEXT_SIZE = "text_size";
|
||||
private static final String INSTANCE_REACHED_BAR_HEIGHT = "reached_bar_height";
|
||||
private static final String INSTANCE_REACHED_BAR_COLOR = "reached_bar_color";
|
||||
private static final String INSTANCE_UNREACHED_BAR_HEIGHT = "unreached_bar_height";
|
||||
private static final String INSTANCE_UNREACHED_BAR_COLOR = "unreached_bar_color";
|
||||
private static final String INSTANCE_MAX = "max";
|
||||
private static final String INSTANCE_PROGRESS = "progress";
|
||||
private static final String INSTANCE_SUFFIX = "suffix";
|
||||
private static final String INSTANCE_PREFIX = "prefix";
|
||||
private static final String INSTANCE_TEXT_VISIBILITY = "text_visibility";
|
||||
|
||||
private static final int PROGRESS_TEXT_VISIBLE = 0;
|
||||
|
||||
|
||||
/**
|
||||
* The width of the text that to be drawn.
|
||||
*/
|
||||
private float mDrawTextWidth;
|
||||
|
||||
/**
|
||||
* The drawn text start.
|
||||
*/
|
||||
private float mDrawTextStart;
|
||||
|
||||
/**
|
||||
* The drawn text end.
|
||||
*/
|
||||
private float mDrawTextEnd;
|
||||
|
||||
/**
|
||||
* The text that to be drawn in onDraw().
|
||||
*/
|
||||
private String mCurrentDrawText;
|
||||
|
||||
/**
|
||||
* The Paint of the reached area.
|
||||
*/
|
||||
private Paint mReachedBarPaint;
|
||||
/**
|
||||
* The Paint of the unreached area.
|
||||
*/
|
||||
private Paint mUnreachedBarPaint;
|
||||
/**
|
||||
* The Paint of the progress text.
|
||||
*/
|
||||
private Paint mTextPaint;
|
||||
|
||||
/**
|
||||
* Unreached bar area to draw rect.
|
||||
*/
|
||||
private RectF mUnreachedRectF = new RectF(0, 0, 0, 0);
|
||||
/**
|
||||
* Reached bar area rect.
|
||||
*/
|
||||
private RectF mReachedRectF = new RectF(0, 0, 0, 0);
|
||||
|
||||
/**
|
||||
* The progress text offset.
|
||||
*/
|
||||
private float mOffset;
|
||||
|
||||
/**
|
||||
* Determine if need to draw unreached area.
|
||||
*/
|
||||
private boolean mDrawUnreachedBar = true;
|
||||
|
||||
private boolean mDrawReachedBar = true;
|
||||
|
||||
private boolean mIfDrawText = true;
|
||||
|
||||
// /**
|
||||
// * Listener
|
||||
// */
|
||||
// private OnProgressBarListener mListener;
|
||||
|
||||
public enum ProgressTextVisibility {
|
||||
Visible, Invisible
|
||||
}
|
||||
|
||||
public NumberProgressBar(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public NumberProgressBar(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public NumberProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
default_reached_bar_height = dp2px(1.5f);
|
||||
default_unreached_bar_height = dp2px(1.0f);
|
||||
default_text_size = sp2px(10);
|
||||
default_progress_text_offset = dp2px(3.0f);
|
||||
|
||||
//load styled attributes.
|
||||
final TypedArray attributes = context.getTheme().obtainStyledAttributes(attrs, R.styleable.NumberProgressBar,
|
||||
defStyleAttr, 0);
|
||||
|
||||
mReachedBarColor = attributes.getColor(R.styleable.NumberProgressBar_progress_reached_color, default_reached_color);
|
||||
mUnreachedBarColor = attributes.getColor(R.styleable.NumberProgressBar_progress_unreached_color, default_unreached_color);
|
||||
mTextColor = attributes.getColor(R.styleable.NumberProgressBar_progress_text_color, default_text_color);
|
||||
mTextSize = attributes.getDimension(R.styleable.NumberProgressBar_progress_text_size, default_text_size);
|
||||
|
||||
mReachedBarHeight = attributes.getDimension(R.styleable.NumberProgressBar_progress_reached_bar_height, default_reached_bar_height);
|
||||
mUnreachedBarHeight = attributes.getDimension(R.styleable.NumberProgressBar_progress_unreached_bar_height, default_unreached_bar_height);
|
||||
mOffset = attributes.getDimension(R.styleable.NumberProgressBar_progress_text_offset, default_progress_text_offset);
|
||||
|
||||
int textVisible = attributes.getInt(R.styleable.NumberProgressBar_progress_text_visibility, PROGRESS_TEXT_VISIBLE);
|
||||
if (textVisible != PROGRESS_TEXT_VISIBLE) {
|
||||
mIfDrawText = false;
|
||||
}
|
||||
|
||||
setProgress(attributes.getInt(R.styleable.NumberProgressBar_progress_current, 0));
|
||||
setMax(attributes.getInt(R.styleable.NumberProgressBar_progress_max, 100));
|
||||
|
||||
attributes.recycle();
|
||||
initializePainters();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSuggestedMinimumWidth() {
|
||||
return (int) mTextSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSuggestedMinimumHeight() {
|
||||
return Math.max((int) mTextSize, Math.max((int) mReachedBarHeight, (int) mUnreachedBarHeight));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
setMeasuredDimension(measure(widthMeasureSpec, true), measure(heightMeasureSpec, false));
|
||||
}
|
||||
|
||||
private int measure(int measureSpec, boolean isWidth) {
|
||||
int result;
|
||||
int mode = MeasureSpec.getMode(measureSpec);
|
||||
int size = MeasureSpec.getSize(measureSpec);
|
||||
int padding = isWidth ? getPaddingLeft() + getPaddingRight() : getPaddingTop() + getPaddingBottom();
|
||||
if (mode == MeasureSpec.EXACTLY) {
|
||||
result = size;
|
||||
} else {
|
||||
result = isWidth ? getSuggestedMinimumWidth() : getSuggestedMinimumHeight();
|
||||
result += padding;
|
||||
if (mode == MeasureSpec.AT_MOST) {
|
||||
if (isWidth) {
|
||||
result = Math.max(result, size);
|
||||
} else {
|
||||
result = Math.min(result, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (mIfDrawText) {
|
||||
calculateDrawRectF();
|
||||
} else {
|
||||
calculateDrawRectFWithoutProgressText();
|
||||
}
|
||||
|
||||
if (mDrawReachedBar) {
|
||||
canvas.drawRect(mReachedRectF, mReachedBarPaint);
|
||||
}
|
||||
|
||||
if (mDrawUnreachedBar) {
|
||||
canvas.drawRect(mUnreachedRectF, mUnreachedBarPaint);
|
||||
}
|
||||
|
||||
if (mIfDrawText)
|
||||
canvas.drawText(mCurrentDrawText, mDrawTextStart, mDrawTextEnd, mTextPaint);
|
||||
}
|
||||
|
||||
private void initializePainters() {
|
||||
mReachedBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mReachedBarPaint.setColor(mReachedBarColor);
|
||||
|
||||
mUnreachedBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mUnreachedBarPaint.setColor(mUnreachedBarColor);
|
||||
|
||||
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mTextPaint.setColor(mTextColor);
|
||||
mTextPaint.setTextSize(mTextSize);
|
||||
}
|
||||
|
||||
|
||||
private void calculateDrawRectFWithoutProgressText() {
|
||||
mReachedRectF.left = getPaddingLeft();
|
||||
mReachedRectF.top = getHeight() / 2.0f - mReachedBarHeight / 2.0f;
|
||||
mReachedRectF.right = (getWidth() - getPaddingLeft() - getPaddingRight()) / (getMax() * 1.0f) * getProgress() + getPaddingLeft();
|
||||
mReachedRectF.bottom = getHeight() / 2.0f + mReachedBarHeight / 2.0f;
|
||||
|
||||
mUnreachedRectF.left = mReachedRectF.right;
|
||||
mUnreachedRectF.right = getWidth() - getPaddingRight();
|
||||
mUnreachedRectF.top = getHeight() / 2.0f + -mUnreachedBarHeight / 2.0f;
|
||||
mUnreachedRectF.bottom = getHeight() / 2.0f + mUnreachedBarHeight / 2.0f;
|
||||
}
|
||||
|
||||
private void calculateDrawRectF() {
|
||||
|
||||
mCurrentDrawText = String.format("%d", getProgress() * 100 / getMax());
|
||||
mCurrentDrawText = mPrefix + mCurrentDrawText + mSuffix;
|
||||
mDrawTextWidth = mTextPaint.measureText(mCurrentDrawText);
|
||||
|
||||
if (getProgress() == 0) {
|
||||
mDrawReachedBar = false;
|
||||
mDrawTextStart = getPaddingLeft();
|
||||
} else {
|
||||
mDrawReachedBar = true;
|
||||
mReachedRectF.left = getPaddingLeft();
|
||||
mReachedRectF.top = getHeight() / 2.0f - mReachedBarHeight / 2.0f;
|
||||
mReachedRectF.right = (getWidth() - getPaddingLeft() - getPaddingRight()) / (getMax() * 1.0f) * getProgress() - mOffset + getPaddingLeft();
|
||||
mReachedRectF.bottom = getHeight() / 2.0f + mReachedBarHeight / 2.0f;
|
||||
mDrawTextStart = (mReachedRectF.right + mOffset);
|
||||
}
|
||||
|
||||
mDrawTextEnd = (int) ((getHeight() / 2.0f) - ((mTextPaint.descent() + mTextPaint.ascent()) / 2.0f));
|
||||
|
||||
if ((mDrawTextStart + mDrawTextWidth) >= getWidth() - getPaddingRight()) {
|
||||
mDrawTextStart = getWidth() - getPaddingRight() - mDrawTextWidth;
|
||||
mReachedRectF.right = mDrawTextStart - mOffset;
|
||||
}
|
||||
|
||||
float unreachedBarStart = mDrawTextStart + mDrawTextWidth + mOffset;
|
||||
if (unreachedBarStart >= getWidth() - getPaddingRight()) {
|
||||
mDrawUnreachedBar = false;
|
||||
} else {
|
||||
mDrawUnreachedBar = true;
|
||||
mUnreachedRectF.left = unreachedBarStart;
|
||||
mUnreachedRectF.right = getWidth() - getPaddingRight();
|
||||
mUnreachedRectF.top = getHeight() / 2.0f + -mUnreachedBarHeight / 2.0f;
|
||||
mUnreachedRectF.bottom = getHeight() / 2.0f + mUnreachedBarHeight / 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get progress text color.
|
||||
*
|
||||
* @return progress text color.
|
||||
*/
|
||||
public int getTextColor() {
|
||||
return mTextColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get progress text size.
|
||||
*
|
||||
* @return progress text size.
|
||||
*/
|
||||
public float getProgressTextSize() {
|
||||
return mTextSize;
|
||||
}
|
||||
|
||||
public int getUnreachedBarColor() {
|
||||
return mUnreachedBarColor;
|
||||
}
|
||||
|
||||
public int getReachedBarColor() {
|
||||
return mReachedBarColor;
|
||||
}
|
||||
|
||||
public long getProgress() {
|
||||
return mCurrentProgress;
|
||||
}
|
||||
|
||||
public long getMax() {
|
||||
return mMaxProgress;
|
||||
}
|
||||
|
||||
public float getReachedBarHeight() {
|
||||
return mReachedBarHeight;
|
||||
}
|
||||
|
||||
public float getUnreachedBarHeight() {
|
||||
return mUnreachedBarHeight;
|
||||
}
|
||||
|
||||
public void setProgressTextSize(float textSize) {
|
||||
this.mTextSize = textSize;
|
||||
mTextPaint.setTextSize(mTextSize);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setProgressTextColor(int textColor) {
|
||||
this.mTextColor = textColor;
|
||||
mTextPaint.setColor(mTextColor);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setUnreachedBarColor(int barColor) {
|
||||
this.mUnreachedBarColor = barColor;
|
||||
mUnreachedBarPaint.setColor(mUnreachedBarColor);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setReachedBarColor(int progressColor) {
|
||||
this.mReachedBarColor = progressColor;
|
||||
mReachedBarPaint.setColor(mReachedBarColor);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setReachedBarHeight(float height) {
|
||||
mReachedBarHeight = height;
|
||||
}
|
||||
|
||||
public void setUnreachedBarHeight(float height) {
|
||||
mUnreachedBarHeight = height;
|
||||
}
|
||||
|
||||
public void setMax(long maxProgress) {
|
||||
if (maxProgress > 0) {
|
||||
this.mMaxProgress = maxProgress;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void setSuffix(String suffix) {
|
||||
if (suffix == null) {
|
||||
mSuffix = "";
|
||||
} else {
|
||||
mSuffix = suffix;
|
||||
}
|
||||
}
|
||||
|
||||
public String getSuffix() {
|
||||
return mSuffix;
|
||||
}
|
||||
|
||||
public void setPrefix(String prefix) {
|
||||
if (prefix == null)
|
||||
mPrefix = "";
|
||||
else {
|
||||
mPrefix = prefix;
|
||||
}
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return mPrefix;
|
||||
}
|
||||
|
||||
public void incrementProgressBy(int by) {
|
||||
if (by > 0) {
|
||||
setProgress(getProgress() + by);
|
||||
}
|
||||
|
||||
// if(mListener != null){
|
||||
// mListener.onProgressChange(getProgress(), getMax());
|
||||
// }
|
||||
}
|
||||
|
||||
public void setProgress(long progress) {
|
||||
if (progress <= getMax() && progress >= 0) {
|
||||
this.mCurrentProgress = progress;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Parcelable onSaveInstanceState() {
|
||||
final Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(INSTANCE_STATE, super.onSaveInstanceState());
|
||||
bundle.putInt(INSTANCE_TEXT_COLOR, getTextColor());
|
||||
bundle.putFloat(INSTANCE_TEXT_SIZE, getProgressTextSize());
|
||||
bundle.putFloat(INSTANCE_REACHED_BAR_HEIGHT, getReachedBarHeight());
|
||||
bundle.putFloat(INSTANCE_UNREACHED_BAR_HEIGHT, getUnreachedBarHeight());
|
||||
bundle.putInt(INSTANCE_REACHED_BAR_COLOR, getReachedBarColor());
|
||||
bundle.putInt(INSTANCE_UNREACHED_BAR_COLOR, getUnreachedBarColor());
|
||||
bundle.putLong(INSTANCE_MAX, getMax());
|
||||
bundle.putLong(INSTANCE_PROGRESS, getProgress());
|
||||
bundle.putString(INSTANCE_SUFFIX, getSuffix());
|
||||
bundle.putString(INSTANCE_PREFIX, getPrefix());
|
||||
bundle.putBoolean(INSTANCE_TEXT_VISIBILITY, getProgressTextVisibility());
|
||||
return bundle;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Parcelable state) {
|
||||
if (state instanceof Bundle) {
|
||||
final Bundle bundle = (Bundle) state;
|
||||
mTextColor = bundle.getInt(INSTANCE_TEXT_COLOR);
|
||||
mTextSize = bundle.getFloat(INSTANCE_TEXT_SIZE);
|
||||
mReachedBarHeight = bundle.getFloat(INSTANCE_REACHED_BAR_HEIGHT);
|
||||
mUnreachedBarHeight = bundle.getFloat(INSTANCE_UNREACHED_BAR_HEIGHT);
|
||||
mReachedBarColor = bundle.getInt(INSTANCE_REACHED_BAR_COLOR);
|
||||
mUnreachedBarColor = bundle.getInt(INSTANCE_UNREACHED_BAR_COLOR);
|
||||
initializePainters();
|
||||
setMax(bundle.getLong(INSTANCE_MAX));
|
||||
setProgress(bundle.getLong(INSTANCE_PROGRESS));
|
||||
setPrefix(bundle.getString(INSTANCE_PREFIX));
|
||||
setSuffix(bundle.getString(INSTANCE_SUFFIX));
|
||||
setProgressTextVisibility(bundle.getBoolean(INSTANCE_TEXT_VISIBILITY) ? ProgressTextVisibility.Visible : ProgressTextVisibility.Invisible);
|
||||
super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATE));
|
||||
return;
|
||||
}
|
||||
super.onRestoreInstanceState(state);
|
||||
}
|
||||
|
||||
public float dp2px(float dp) {
|
||||
final float scale = getResources().getDisplayMetrics().density;
|
||||
return dp * scale + 0.5f;
|
||||
}
|
||||
|
||||
public float sp2px(float sp) {
|
||||
final float scale = getResources().getDisplayMetrics().scaledDensity;
|
||||
return sp * scale;
|
||||
}
|
||||
|
||||
public void setProgressTextVisibility(ProgressTextVisibility visibility) {
|
||||
mIfDrawText = visibility == ProgressTextVisibility.Visible;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public boolean getProgressTextVisibility() {
|
||||
return mIfDrawText;
|
||||
}
|
||||
|
||||
// public void setOnProgressBarListener(OnProgressBarListener listener){
|
||||
// mListener = listener;
|
||||
// }
|
||||
}
|
||||
450
video/src/main/java/com/yunbao/video/custom/RangeSlider.java
Normal file
450
video/src/main/java/com/yunbao/video/custom/RangeSlider.java
Normal file
@@ -0,0 +1,450 @@
|
||||
package com.yunbao.video.custom;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
|
||||
import com.yunbao.video.R;
|
||||
|
||||
|
||||
public class RangeSlider extends ViewGroup {
|
||||
private static final String TAG = "RangeSlider";
|
||||
private static final int DEFAULT_LINE_SIZE = 1;
|
||||
private static final int DEFAULT_THUMB_WIDTH = 7;
|
||||
private static final int DEFAULT_TICK_START = 0;
|
||||
private static final int DEFAULT_TICK_END = 5;
|
||||
private static final int DEFAULT_TICK_INTERVAL = 1;
|
||||
private static final int DEFAULT_MASK_BACKGROUND = 0xA0000000;
|
||||
private static final int DEFAULT_LINE_COLOR = 0xFF000000;
|
||||
public static final int TYPE_LEFT = 1;
|
||||
public static final int TYPE_RIGHT = 2;
|
||||
|
||||
private final Paint mLinePaint, mBgPaint;
|
||||
private final ThumbView mLeftThumb, mRightThumb;
|
||||
|
||||
private int mTouchSlop;
|
||||
private int mOriginalX, mLastX;
|
||||
|
||||
private int mThumbWidth;
|
||||
|
||||
private int mTickStart = DEFAULT_TICK_START;
|
||||
private int mTickEnd = DEFAULT_TICK_END;
|
||||
private int mTickInterval = DEFAULT_TICK_INTERVAL;
|
||||
private int mTickCount = (mTickEnd - mTickStart) / mTickInterval;
|
||||
|
||||
private float mLineSize;
|
||||
|
||||
private boolean mIsDragging;
|
||||
|
||||
private OnRangeChangeListener mRangeChangeListener;
|
||||
|
||||
public RangeSlider(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public RangeSlider(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public RangeSlider(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RangeSlider);
|
||||
mThumbWidth = array.getDimensionPixelOffset(R.styleable.RangeSlider_thumbWidth, DEFAULT_THUMB_WIDTH);
|
||||
mLineSize = array.getDimensionPixelOffset(R.styleable.RangeSlider_lineHeight, DEFAULT_LINE_SIZE);
|
||||
mBgPaint = new Paint();
|
||||
mBgPaint.setColor(array.getColor(R.styleable.RangeSlider_maskColor, DEFAULT_MASK_BACKGROUND));
|
||||
|
||||
mLinePaint = new Paint();
|
||||
mLinePaint.setColor(array.getColor(R.styleable.RangeSlider_lineColor, DEFAULT_LINE_COLOR));
|
||||
|
||||
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
|
||||
|
||||
Drawable lDrawable = array.getDrawable(R.styleable.RangeSlider_leftThumbDrawable);
|
||||
Drawable rDrawable = array.getDrawable(R.styleable.RangeSlider_rightThumbDrawable);
|
||||
mLeftThumb = new ThumbView(context, mThumbWidth, lDrawable == null ? new ColorDrawable(DEFAULT_LINE_COLOR) : lDrawable);
|
||||
mRightThumb = new ThumbView(context, mThumbWidth, rDrawable == null ? new ColorDrawable(DEFAULT_LINE_COLOR) : rDrawable);
|
||||
setTickCount(array.getInteger(R.styleable.RangeSlider_tickCount, DEFAULT_TICK_END));
|
||||
setRangeIndex(array.getInteger(R.styleable.RangeSlider_leftThumbIndex, DEFAULT_TICK_START),
|
||||
array.getInteger(R.styleable.RangeSlider_rightThumbIndex, mTickCount));
|
||||
array.recycle();
|
||||
|
||||
addView(mLeftThumb);
|
||||
addView(mRightThumb);
|
||||
|
||||
setWillNotDraw(false);
|
||||
}
|
||||
|
||||
public void setThumbWidth(int thumbWidth) {
|
||||
mThumbWidth = thumbWidth;
|
||||
mLeftThumb.setThumbWidth(thumbWidth);
|
||||
mRightThumb.setThumbWidth(thumbWidth);
|
||||
}
|
||||
|
||||
public void setLeftThumbDrawable(Drawable drawable) {
|
||||
mLeftThumb.setThumbDrawable(drawable);
|
||||
}
|
||||
|
||||
public void setRightThumbDrawable(Drawable drawable) {
|
||||
mRightThumb.setThumbDrawable(drawable);
|
||||
}
|
||||
|
||||
public void setLineColor(int color) {
|
||||
mLinePaint.setColor(color);
|
||||
}
|
||||
|
||||
public void setLineSize(float lineSize) {
|
||||
mLineSize = lineSize;
|
||||
}
|
||||
|
||||
public void setMaskColor(int color) {
|
||||
mBgPaint.setColor(color);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
widthMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY);
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
mLeftThumb.measure(widthMeasureSpec, heightMeasureSpec);
|
||||
mRightThumb.measure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
final int lThumbWidth = mLeftThumb.getMeasuredWidth();
|
||||
final int lThumbHeight = mLeftThumb.getMeasuredHeight();
|
||||
mLeftThumb.layout(0, 0, lThumbWidth, lThumbHeight);
|
||||
mRightThumb.layout(0, 0, lThumbWidth, lThumbHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
moveThumbByIndex(mLeftThumb, mLeftThumb.getRangeIndex());
|
||||
moveThumbByIndex(mRightThumb, mRightThumb.getRangeIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
final int width = getMeasuredWidth();
|
||||
final int height = getMeasuredHeight();
|
||||
|
||||
final int lThumbWidth = mLeftThumb.getMeasuredWidth();
|
||||
final float lThumbOffset = mLeftThumb.getX();
|
||||
final float rThumbOffset = mRightThumb.getX();
|
||||
|
||||
final float lineTop = mLineSize;
|
||||
final float lineBottom = height - mLineSize;
|
||||
|
||||
|
||||
// top line
|
||||
canvas.drawRect(lThumbWidth + lThumbOffset, 0, rThumbOffset, lineTop, mLinePaint);
|
||||
|
||||
// bottom line
|
||||
canvas.drawRect(lThumbWidth + lThumbOffset, lineBottom, rThumbOffset, height, mLinePaint);
|
||||
|
||||
if (lThumbOffset > mThumbWidth) {
|
||||
canvas.drawRect(0, 0, lThumbOffset + mThumbWidth, height, mBgPaint);
|
||||
}
|
||||
if (rThumbOffset < width - mThumbWidth) {
|
||||
canvas.drawRect(rThumbOffset, 0, width, height, mBgPaint);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 对游标进行复位
|
||||
*/
|
||||
public void resetRangePos() {
|
||||
ValueAnimator leftValueAnimator = ValueAnimator.ofFloat(mLeftThumb.getX(), 0f);
|
||||
leftValueAnimator.setDuration(200);
|
||||
leftValueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
|
||||
ValueAnimator rightValueAnimator = ValueAnimator.ofFloat(mRightThumb.getX(), this.getMeasuredWidth());
|
||||
|
||||
rightValueAnimator.setDuration(200);
|
||||
rightValueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
|
||||
|
||||
leftValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
int moveX = (int) ((float) animation.getAnimatedValue() - mLeftThumb.getX());
|
||||
if (moveX != 0) {
|
||||
moveLeftThumbByPixel(moveX);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
});
|
||||
rightValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
Log.i(TAG, "right onAnimationUpdate: " + animation.getAnimatedValue());
|
||||
int moveX = (int) ((float) animation.getAnimatedValue() - mRightThumb.getX());
|
||||
Log.i(TAG, "move x = " + moveX);
|
||||
if (moveX != 0) {
|
||||
moveRightThumbByPixel(moveX);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
leftValueAnimator.start();
|
||||
rightValueAnimator.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (!isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean handle = false;
|
||||
|
||||
switch (event.getAction()) {
|
||||
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
int x = (int) event.getX();
|
||||
int y = (int) event.getY();
|
||||
|
||||
mLastX = mOriginalX = x;
|
||||
mIsDragging = false;
|
||||
|
||||
if (!mLeftThumb.isPressed() && mLeftThumb.inInTarget(x, y)) {
|
||||
mLeftThumb.setPressed(true);
|
||||
handle = true;
|
||||
if (mRangeChangeListener != null) {
|
||||
mRangeChangeListener.onKeyDown(TYPE_LEFT);
|
||||
}
|
||||
} else if (!mRightThumb.isPressed() && mRightThumb.inInTarget(x, y)) {
|
||||
mRightThumb.setPressed(true);
|
||||
handle = true;
|
||||
if (mRangeChangeListener != null) {
|
||||
mRangeChangeListener.onKeyDown(TYPE_RIGHT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
case MotionEvent.ACTION_UP:
|
||||
mIsDragging = false;
|
||||
mOriginalX = mLastX = 0;
|
||||
getParent().requestDisallowInterceptTouchEvent(false);
|
||||
if (mLeftThumb.isPressed()) {
|
||||
releaseLeftThumb();
|
||||
invalidate();
|
||||
handle = true;
|
||||
if (mRangeChangeListener != null) {
|
||||
mRangeChangeListener.onKeyUp(TYPE_LEFT, mLeftThumb.getRangeIndex(), mRightThumb.getRangeIndex());
|
||||
}
|
||||
} else if (mRightThumb.isPressed()) {
|
||||
releaseRightThumb();
|
||||
invalidate();
|
||||
handle = true;
|
||||
if (mRangeChangeListener != null) {
|
||||
mRangeChangeListener.onKeyUp(TYPE_RIGHT, mLeftThumb.getRangeIndex(), mRightThumb.getRangeIndex());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
x = (int) event.getX();
|
||||
|
||||
if (!mIsDragging && Math.abs(x - mOriginalX) > mTouchSlop) {
|
||||
mIsDragging = true;
|
||||
}
|
||||
if (mIsDragging) {
|
||||
int moveX = x - mLastX;
|
||||
if (mLeftThumb.isPressed()) {
|
||||
getParent().requestDisallowInterceptTouchEvent(true);
|
||||
moveLeftThumbByPixel(moveX);
|
||||
handle = true;
|
||||
invalidate();
|
||||
} else if (mRightThumb.isPressed()) {
|
||||
getParent().requestDisallowInterceptTouchEvent(true);
|
||||
moveRightThumbByPixel(moveX);
|
||||
handle = true;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
mLastX = x;
|
||||
break;
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
private boolean isValidTickCount(int tickCount) {
|
||||
return (tickCount > 1);
|
||||
}
|
||||
|
||||
private boolean indexOutOfRange(int leftThumbIndex, int rightThumbIndex) {
|
||||
return (leftThumbIndex < 0 || leftThumbIndex > mTickCount
|
||||
|| rightThumbIndex < 0
|
||||
|| rightThumbIndex > mTickCount);
|
||||
}
|
||||
|
||||
private float getRangeLength() {
|
||||
int width = getMeasuredWidth();
|
||||
if (width < mThumbWidth) {
|
||||
return 0;
|
||||
}
|
||||
return width - mThumbWidth;
|
||||
}
|
||||
|
||||
private float getIntervalLength() {
|
||||
return getRangeLength() / mTickCount;
|
||||
}
|
||||
|
||||
public int getNearestIndex(float x) {
|
||||
return Math.round(x / getIntervalLength());
|
||||
}
|
||||
|
||||
public int getLeftIndex() {
|
||||
return mLeftThumb.getRangeIndex();
|
||||
}
|
||||
|
||||
public int getRightIndex() {
|
||||
return mRightThumb.getRangeIndex();
|
||||
}
|
||||
|
||||
private void notifyRangeChange(int type) {
|
||||
if (mRangeChangeListener != null) {
|
||||
// mRangeChangeListener.onRangeChange(this, type, mLeftThumb.getRangeIndex(), mRightThumb.getRangeIndex());
|
||||
}
|
||||
}
|
||||
|
||||
public void setRangeChangeListener(OnRangeChangeListener rangeChangeListener) {
|
||||
mRangeChangeListener = rangeChangeListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tick count in the RangeSlider.
|
||||
*
|
||||
* @param count Integer specifying the number of ticks.
|
||||
*/
|
||||
public void setTickCount(int count) {
|
||||
int tickCount = (count - mTickStart) / mTickInterval;
|
||||
if (isValidTickCount(tickCount)) {
|
||||
mTickEnd = count;
|
||||
mTickCount = tickCount;
|
||||
mRightThumb.setTickIndex(mTickCount);
|
||||
} else {
|
||||
throw new IllegalArgumentException("tickCount less than 2; invalid tickCount.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The location of the thumbs according by the supplied index.
|
||||
* Numbered from 0 to mTickCount - 1 from the left.
|
||||
*
|
||||
* @param leftIndex Integer specifying the index of the left thumb
|
||||
* @param rightIndex Integer specifying the index of the right thumb
|
||||
*/
|
||||
public void setRangeIndex(int leftIndex, int rightIndex) {
|
||||
if (indexOutOfRange(leftIndex, rightIndex)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Thumb index left " + leftIndex + ", or right " + rightIndex
|
||||
+ " is out of bounds. Check that it is greater than the minimum ("
|
||||
+ mTickStart + ") and less than the maximum value ("
|
||||
+ mTickEnd + ")");
|
||||
} else {
|
||||
if (mLeftThumb.getRangeIndex() != leftIndex) {
|
||||
mLeftThumb.setTickIndex(leftIndex);
|
||||
}
|
||||
if (mRightThumb.getRangeIndex() != rightIndex) {
|
||||
mRightThumb.setTickIndex(rightIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean moveThumbByIndex(ThumbView view, int index) {
|
||||
view.setX(index * getIntervalLength());
|
||||
if (view.getRangeIndex() != index) {
|
||||
view.setTickIndex(index);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void moveLeftThumbByPixel(int pixel) {
|
||||
float x = mLeftThumb.getX() + pixel;
|
||||
float interval = getIntervalLength();
|
||||
float start = mTickStart / mTickInterval * interval;
|
||||
float end = mTickEnd / mTickInterval * interval;
|
||||
|
||||
if (x > start && x < end && x < mRightThumb.getX() - mThumbWidth) {
|
||||
mLeftThumb.setX(x);
|
||||
int index = getNearestIndex(x);
|
||||
if (mLeftThumb.getRangeIndex() != index) {
|
||||
mLeftThumb.setTickIndex(index);
|
||||
notifyRangeChange(TYPE_LEFT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void moveRightThumbByPixel(int pixel) {
|
||||
float x = mRightThumb.getX() + pixel;
|
||||
float interval = getIntervalLength();
|
||||
float start = mTickStart / mTickInterval * interval;
|
||||
float end = mTickEnd / mTickInterval * interval;
|
||||
|
||||
if (x > start && x < end && x > mLeftThumb.getX() + mThumbWidth) {
|
||||
mRightThumb.setX(x);
|
||||
int index = getNearestIndex(x);
|
||||
if (mRightThumb.getRangeIndex() != index) {
|
||||
mRightThumb.setTickIndex(index);
|
||||
notifyRangeChange(TYPE_RIGHT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void releaseLeftThumb() {
|
||||
int index = getNearestIndex(mLeftThumb.getX());
|
||||
int endIndex = mRightThumb.getRangeIndex();
|
||||
if (index >= endIndex) {
|
||||
index = endIndex - 1;
|
||||
}
|
||||
if (moveThumbByIndex(mLeftThumb, index)) {
|
||||
notifyRangeChange(TYPE_LEFT);
|
||||
}
|
||||
mLeftThumb.setPressed(false);
|
||||
}
|
||||
|
||||
private void releaseRightThumb() {
|
||||
int index = getNearestIndex(mRightThumb.getX());
|
||||
int endIndex = mLeftThumb.getRangeIndex();
|
||||
if (index <= endIndex) {
|
||||
index = endIndex + 1;
|
||||
}
|
||||
if (moveThumbByIndex(mRightThumb, index)) {
|
||||
notifyRangeChange(TYPE_RIGHT);
|
||||
}
|
||||
mRightThumb.setPressed(false);
|
||||
}
|
||||
|
||||
public void setCutRange(int leftTick, int rightTick) {
|
||||
if (mLeftThumb.getRangeIndex() != leftTick) {
|
||||
moveThumbByIndex(mLeftThumb, leftTick);
|
||||
}
|
||||
if (mRightThumb.getRangeIndex() != rightTick) {
|
||||
moveThumbByIndex(mRightThumb, rightTick);
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public interface OnRangeChangeListener {
|
||||
void onKeyDown(int type);
|
||||
|
||||
void onKeyUp(int type, int leftPinIndex, int rightPinIndex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
package com.yunbao.video.custom;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.yunbao.video.R;
|
||||
|
||||
/**
|
||||
* Created by vinsonswang on 2017/11/7.
|
||||
*/
|
||||
|
||||
public class RangeSliderViewContainer extends LinearLayout {
|
||||
private final String TAG = "RangeSliderView";
|
||||
|
||||
private Context mContext;
|
||||
private View mRootView;
|
||||
private View mStartView; // 左边拖动控件
|
||||
private View mEndView; // 右边拖动控件
|
||||
private View mMiddleView; // 中间裁剪区域
|
||||
private long mStartTimeMs; // 起始时间us
|
||||
private long mDurationMs; // 最终的时长us
|
||||
private long mEndTimeMs; // 结束时间us
|
||||
private long mMaxDuration; // 允许设置的最大时长
|
||||
private int mDistance; // 中间裁剪区域距离
|
||||
|
||||
private ViewTouchProcess mStartViewTouchProcess;
|
||||
private ViewTouchProcess mEndViewTouchProcess;
|
||||
|
||||
private VideoProgressController mVideoProgressController;
|
||||
|
||||
private OnDurationChangeListener mOnDurationChangeListener;
|
||||
|
||||
public interface OnDurationChangeListener{
|
||||
void onDurationChange(long startTimeMs, long endTimeMs);
|
||||
}
|
||||
|
||||
public void setDurationChangeListener(OnDurationChangeListener onDurationChangeListener){
|
||||
mOnDurationChangeListener = onDurationChangeListener;
|
||||
}
|
||||
|
||||
public RangeSliderViewContainer(Context context) {
|
||||
super(context);
|
||||
initView(context);
|
||||
}
|
||||
|
||||
public RangeSliderViewContainer(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
initView(context);
|
||||
}
|
||||
|
||||
public RangeSliderViewContainer(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
initView(context);
|
||||
}
|
||||
|
||||
private void initView(Context context){
|
||||
mContext = context;
|
||||
mRootView = LayoutInflater.from(context).inflate(R.layout.layout_range_slider, this);
|
||||
mStartView = mRootView.findViewById(R.id.iv_start_view);
|
||||
mEndView = mRootView.findViewById(R.id.iv_end_view);
|
||||
mMiddleView = mRootView.findViewById(R.id.middle_view);
|
||||
|
||||
mStartViewTouchProcess = new ViewTouchProcess(mStartView);
|
||||
mEndViewTouchProcess = new ViewTouchProcess(mEndView);
|
||||
}
|
||||
|
||||
public void init(VideoProgressController videoProgressController, long startTimeMs, long durationMs, long maxDurationMs){
|
||||
mVideoProgressController = videoProgressController;
|
||||
mStartTimeMs = startTimeMs;
|
||||
mDurationMs = durationMs;
|
||||
mMaxDuration = maxDurationMs;
|
||||
mEndTimeMs = mStartTimeMs + mDurationMs;
|
||||
|
||||
mDistance = videoProgressController.duration2Distance(mDurationMs);
|
||||
|
||||
ViewGroup.LayoutParams layoutParams = mMiddleView.getLayoutParams();
|
||||
layoutParams.width = mDistance;
|
||||
mMiddleView.setLayoutParams(layoutParams);
|
||||
setMiddleRangeColor(0x4d0accac);
|
||||
|
||||
setTouchProcessListener();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置中间范围颜色
|
||||
* @param color
|
||||
*/
|
||||
public void setMiddleRangeColor(int color){
|
||||
mMiddleView.setBackgroundColor(color);
|
||||
}
|
||||
|
||||
private void setTouchProcessListener(){
|
||||
mStartViewTouchProcess.setOnPositionChangedListener(new ViewTouchProcess.OnPositionChangedListener() {
|
||||
@Override
|
||||
public void onPostionChanged(float distance) {
|
||||
long dtime = mVideoProgressController.distance2Duration(distance);
|
||||
if(dtime > 0 && mDurationMs - dtime < 0){
|
||||
dtime = mDurationMs;
|
||||
}else if(dtime < 0 && (mStartTimeMs + dtime < 0) ){
|
||||
dtime = -mStartTimeMs;
|
||||
}
|
||||
if(dtime == 0){
|
||||
return;
|
||||
}
|
||||
|
||||
mDurationMs -= dtime;
|
||||
mStartTimeMs = mStartTimeMs + dtime;
|
||||
MarginLayoutParams layoutParams = (MarginLayoutParams) mStartView.getLayoutParams();
|
||||
int dx = layoutParams.leftMargin;
|
||||
changeStartViewLayoutParams();
|
||||
dx = layoutParams.leftMargin - dx;
|
||||
layoutParams = (MarginLayoutParams) mMiddleView.getLayoutParams();
|
||||
layoutParams.width -= dx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeComplete() {
|
||||
mVideoProgressController.setIsRangeSliderChanged(true);
|
||||
mVideoProgressController.setCurrentTimeMs(mStartTimeMs);
|
||||
if(mOnDurationChangeListener != null){
|
||||
mOnDurationChangeListener.onDurationChange(mStartTimeMs, mEndTimeMs);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
mEndViewTouchProcess.setOnPositionChangedListener(new ViewTouchProcess.OnPositionChangedListener() {
|
||||
@Override
|
||||
public void onPostionChanged(float distance) {
|
||||
long dtime = mVideoProgressController.distance2Duration(distance);
|
||||
// TXCLog.i(TAG, String.format(Locale.getDefault(), "onPostionChanged, mEndView distance = %f, dtime = %d", distance, dtime));
|
||||
|
||||
if(dtime < 0 && (mEndTimeMs + dtime - mStartTimeMs) < 0){
|
||||
dtime = mStartTimeMs - mEndTimeMs;
|
||||
}else if(dtime > 0 && mEndTimeMs + dtime > mMaxDuration){
|
||||
dtime = mMaxDuration - mEndTimeMs;
|
||||
}
|
||||
if(dtime == 0){
|
||||
return;
|
||||
}
|
||||
mDurationMs += dtime;
|
||||
|
||||
ViewGroup.LayoutParams layoutParams = mMiddleView.getLayoutParams();
|
||||
layoutParams.width = mVideoProgressController.duration2Distance(mDurationMs);
|
||||
|
||||
// TXCLog.i(TAG, String.format(Locale.getDefault(), "onPostionChanged, mEndView dtime = %d, layoutParams.width = %d", dtime, layoutParams.width));
|
||||
|
||||
mEndTimeMs = mEndTimeMs + dtime;
|
||||
mMiddleView.setLayoutParams(layoutParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeComplete() {
|
||||
mVideoProgressController.setIsRangeSliderChanged(true);
|
||||
mVideoProgressController.setCurrentTimeMs(mEndTimeMs);
|
||||
if(mOnDurationChangeListener != null){
|
||||
mOnDurationChangeListener.onDurationChange(mStartTimeMs, mEndTimeMs);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void changeStartViewLayoutParams(){
|
||||
MarginLayoutParams layoutParams = (MarginLayoutParams) mStartView.getLayoutParams();
|
||||
layoutParams.leftMargin = mVideoProgressController.calculateStartViewPosition(this);
|
||||
|
||||
|
||||
mStartView.setLayoutParams(layoutParams);
|
||||
}
|
||||
|
||||
public void setEditComplete(){
|
||||
mStartView.setVisibility(View.INVISIBLE);
|
||||
mEndView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
public void showEdit(){
|
||||
mStartView.setVisibility(View.VISIBLE);
|
||||
mEndView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
public ViewGroup getContainer(){
|
||||
return (ViewGroup)mRootView;
|
||||
}
|
||||
|
||||
public View getStartView(){
|
||||
return mStartView;
|
||||
}
|
||||
|
||||
public View getEndView(){
|
||||
return mEndView;
|
||||
}
|
||||
|
||||
public long getStartTimeUs() {
|
||||
return mStartTimeMs;
|
||||
}
|
||||
|
||||
public long getDuration() {
|
||||
return mDurationMs;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
package com.yunbao.video.custom;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.os.Handler;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Created by vinsonswang on 2017/8/24.
|
||||
*/
|
||||
|
||||
public class RecordProgressView extends View {
|
||||
private final String TAG = "RecordProgressView";
|
||||
|
||||
private float mScale;
|
||||
private Paint mRecordPaint;
|
||||
private Paint mPendingPaint;
|
||||
private Paint mSpacePaint;
|
||||
private int mBackgroundColor;
|
||||
private int mRecordColor;
|
||||
private int mPendingColor;
|
||||
private int mSpaceColor;
|
||||
|
||||
private boolean isCursorShow = false;
|
||||
private boolean isInProgress = false;
|
||||
private Handler mHandler;
|
||||
|
||||
private ArrayList<ClipInfo> mClipInfoList;
|
||||
private ClipInfo mCurClipInfo;
|
||||
private boolean isPending;
|
||||
|
||||
private int mMaxDuration;
|
||||
private int mMinDuration;
|
||||
private int mLastTotalDuration;
|
||||
|
||||
public RecordProgressView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public RecordProgressView(Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public RecordProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mScale = context.getResources().getDisplayMetrics().density;
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
mRecordPaint = new Paint();
|
||||
mPendingPaint = new Paint();
|
||||
mSpacePaint = new Paint();
|
||||
|
||||
mRecordPaint.setAntiAlias(true);
|
||||
mPendingPaint.setAntiAlias(true);
|
||||
mSpacePaint.setAntiAlias(true);
|
||||
|
||||
mBackgroundColor = 0x66000000;
|
||||
mRecordColor = 0xffff6131;
|
||||
mPendingColor = 0xffff6131;
|
||||
mSpaceColor = 0xffffffff;
|
||||
|
||||
mRecordPaint.setColor(mRecordColor);
|
||||
mPendingPaint.setColor(mPendingColor);
|
||||
mSpacePaint.setColor(mSpaceColor);
|
||||
|
||||
mClipInfoList = new ArrayList<ClipInfo>();
|
||||
mCurClipInfo = new ClipInfo();
|
||||
isPending = false;
|
||||
|
||||
mHandler = new Handler();
|
||||
startCursorBling();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
canvas.drawColor(mBackgroundColor);
|
||||
|
||||
int lastTotalProgress = 0;
|
||||
float totalWidth = 0;
|
||||
for (ClipInfo clipInfo : mClipInfoList) {
|
||||
float newWidth = (lastTotalProgress + clipInfo.progress) / (float) mMaxDuration * getWidth();
|
||||
switch (clipInfo.clipType) {
|
||||
case ClipInfo.CLIP_TYPE_SPACE:
|
||||
canvas.drawRect(totalWidth - dp2px(1), 0f, newWidth, getHeight(), mSpacePaint);
|
||||
break;
|
||||
case ClipInfo.CLIP_TYPE_PROGRESS:
|
||||
canvas.drawRect(totalWidth, 0f, newWidth, getHeight(), mRecordPaint);
|
||||
break;
|
||||
case ClipInfo.CLIP_TYPE_PENDING:
|
||||
canvas.drawRect(totalWidth, 0f, newWidth, getHeight(), mPendingPaint);
|
||||
break;
|
||||
}
|
||||
lastTotalProgress += clipInfo.progress;
|
||||
totalWidth = newWidth;
|
||||
}
|
||||
if (mCurClipInfo != null && mCurClipInfo.progress != 0) {
|
||||
canvas.drawRect(totalWidth, 0f, totalWidth + mCurClipInfo.progress / (float) mMaxDuration * getWidth(), getHeight(), mRecordPaint);
|
||||
totalWidth = totalWidth + mCurClipInfo.progress / (float) mMaxDuration * getWidth();
|
||||
}
|
||||
if (lastTotalProgress + mCurClipInfo.progress < mMinDuration) {
|
||||
canvas.drawRect(mMinDuration / (float) mMaxDuration * getWidth(), 0f,
|
||||
mMinDuration / (float) mMaxDuration * getWidth() + dp2px(2), getHeight(), mSpacePaint);
|
||||
}
|
||||
if (isCursorShow || isInProgress) {
|
||||
canvas.drawRect(totalWidth, 0f, totalWidth + dp2px(2), getHeight(), mSpacePaint);
|
||||
}
|
||||
}
|
||||
|
||||
private class ClipInfo {
|
||||
public static final int CLIP_TYPE_PROGRESS = 1;
|
||||
public static final int CLIP_TYPE_PENDING = 2;
|
||||
public static final int CLIP_TYPE_SPACE = 3;
|
||||
|
||||
public int progress;
|
||||
public int clipType;
|
||||
}
|
||||
|
||||
public void setMaxDuration(int maxDuration) {
|
||||
this.mMaxDuration = maxDuration;
|
||||
}
|
||||
|
||||
public void setMinDuration(int minDuration) {
|
||||
this.mMinDuration = minDuration;
|
||||
}
|
||||
|
||||
public void setProgress(int progress) {
|
||||
isInProgress = true;
|
||||
stopCursorBling();
|
||||
if (isPending) {
|
||||
for (ClipInfo clipInfo : mClipInfoList) {
|
||||
if (clipInfo.clipType == ClipInfo.CLIP_TYPE_PENDING) {
|
||||
clipInfo.clipType = ClipInfo.CLIP_TYPE_PROGRESS;
|
||||
isPending = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.mCurClipInfo.clipType = ClipInfo.CLIP_TYPE_PROGRESS;
|
||||
this.mCurClipInfo.progress = progress - mLastTotalDuration;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void clipComplete() {
|
||||
isInProgress = false;
|
||||
|
||||
mLastTotalDuration = mLastTotalDuration + mCurClipInfo.progress;
|
||||
|
||||
mClipInfoList.add(mCurClipInfo);
|
||||
ClipInfo clipInfo = new ClipInfo();
|
||||
clipInfo.clipType = ClipInfo.CLIP_TYPE_SPACE;
|
||||
clipInfo.progress = 0;
|
||||
mClipInfoList.add(clipInfo);
|
||||
mCurClipInfo = new ClipInfo();
|
||||
|
||||
startCursorBling();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void selectLast() {
|
||||
if (mClipInfoList.size() >= 2) {
|
||||
ClipInfo clipInfo = mClipInfoList.get(mClipInfoList.size() - 2);
|
||||
clipInfo.clipType = ClipInfo.CLIP_TYPE_PENDING;
|
||||
isPending = true;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteLast() {
|
||||
if (mClipInfoList.size() >= 2) {
|
||||
mClipInfoList.remove(mClipInfoList.size() - 1);
|
||||
ClipInfo clipInfo = mClipInfoList.remove(mClipInfoList.size() - 1);
|
||||
mLastTotalDuration = mLastTotalDuration - clipInfo.progress;
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void deleteAll() {
|
||||
if (mClipInfoList != null) {
|
||||
mClipInfoList.clear();
|
||||
}
|
||||
isPending = false;
|
||||
mLastTotalDuration = 0;
|
||||
stopCursorBling();
|
||||
startCursorBling();
|
||||
}
|
||||
|
||||
private Runnable cursorRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
isCursorShow = !isCursorShow;
|
||||
mHandler.postDelayed(cursorRunnable, 500);
|
||||
invalidate();
|
||||
}
|
||||
};
|
||||
|
||||
private void startCursorBling() {
|
||||
if (mHandler != null) {
|
||||
mHandler.postDelayed(cursorRunnable, 500);
|
||||
}
|
||||
}
|
||||
|
||||
private void stopCursorBling() {
|
||||
if (mHandler != null) {
|
||||
mHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void release() {
|
||||
if (mHandler != null) {
|
||||
mHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
mHandler = null;
|
||||
}
|
||||
|
||||
private int dp2px(int dpVal) {
|
||||
return (int) (mScale * dpVal + 0.5f);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package com.yunbao.video.custom;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.yunbao.video.R;
|
||||
|
||||
|
||||
/**
|
||||
* Created by vinsonswang on 2017/11/10.
|
||||
*/
|
||||
public class SliderViewContainer extends LinearLayout {
|
||||
private static final String TAG = "RepeatSliderView";
|
||||
private Context mContext;
|
||||
private View mRootView;
|
||||
private View mSliderView;
|
||||
|
||||
private long mStartTimeMs;
|
||||
|
||||
private VideoProgressController mVideoProgressController;
|
||||
private ViewTouchProcess mViewTouchProcess;
|
||||
|
||||
private OnStartTimeChangedListener mOnStartTimeChangedListener;
|
||||
|
||||
public interface OnStartTimeChangedListener {
|
||||
void onStartTimeMsChanged(long timeMs);
|
||||
}
|
||||
|
||||
public SliderViewContainer(Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public SliderViewContainer(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public SliderViewContainer(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public void setOnStartTimeChangedListener(OnStartTimeChangedListener onStartTimeChangedListener) {
|
||||
mOnStartTimeChangedListener = onStartTimeChangedListener;
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
mContext = context;
|
||||
mRootView = LayoutInflater.from(context).inflate(R.layout.layout_repeat_slider, this);
|
||||
mSliderView = mRootView.findViewById(R.id.iv_slider);
|
||||
mViewTouchProcess = new ViewTouchProcess(mSliderView);
|
||||
setTouchProcessListener();
|
||||
}
|
||||
|
||||
private void setTouchProcessListener() {
|
||||
mViewTouchProcess.setOnPositionChangedListener(new ViewTouchProcess.OnPositionChangedListener() {
|
||||
@Override
|
||||
public void onPostionChanged(float distance) {
|
||||
long dtime = mVideoProgressController.distance2Duration(distance);
|
||||
|
||||
// TXCLog.i(TAG, String.format(Locale.getDefault(), "onPostionChanged, mSliderView distance = %f, dtime = %d", distance, dtime));
|
||||
|
||||
if (dtime > 0 && (mVideoProgressController.getTotalDurationMs() - mStartTimeMs) - dtime < 0) {
|
||||
dtime = mVideoProgressController.getTotalDurationMs() - mStartTimeMs;
|
||||
} else if (dtime < 0 && (mStartTimeMs + dtime < 0)) {
|
||||
dtime = -mStartTimeMs;
|
||||
}
|
||||
if (dtime == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
mStartTimeMs = mStartTimeMs + dtime;
|
||||
changeLayoutParams();
|
||||
|
||||
// TXCLog.i(TAG, String.format(Locale.getDefault(), "onPostionChanged, mSliderView layoutParams.leftMargin = %d", layoutParams.leftMargin));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeComplete() {
|
||||
// mVideoProgressController.setIsRangeSliderChanged(true);
|
||||
// mVideoProgressController.setCurrentTimeMs(mStartTimeMs);
|
||||
if (mOnStartTimeChangedListener != null) {
|
||||
mOnStartTimeChangedListener.onStartTimeMsChanged(mStartTimeMs);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public void changeLayoutParams() {
|
||||
if(mVideoProgressController != null){
|
||||
MarginLayoutParams layoutParams = (MarginLayoutParams) mSliderView.getLayoutParams();
|
||||
layoutParams.leftMargin = mVideoProgressController.calculateSliderViewPosition(SliderViewContainer.this);
|
||||
mSliderView.setLayoutParams(layoutParams);
|
||||
}
|
||||
}
|
||||
|
||||
public View getSliderView() {
|
||||
return mSliderView;
|
||||
}
|
||||
|
||||
public void setVideoProgressControlloer(VideoProgressController videoProgressControlloer) {
|
||||
mVideoProgressController = videoProgressControlloer;
|
||||
}
|
||||
|
||||
public void setStartTimeMs(long timeMs) {
|
||||
mStartTimeMs = timeMs;
|
||||
changeLayoutParams();
|
||||
}
|
||||
|
||||
public long getStartTimeMs() {
|
||||
return mStartTimeMs;
|
||||
}
|
||||
}
|
||||
74
video/src/main/java/com/yunbao/video/custom/ThumbView.java
Normal file
74
video/src/main/java/com/yunbao/video/custom/ThumbView.java
Normal file
@@ -0,0 +1,74 @@
|
||||
package com.yunbao.video.custom;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
|
||||
public class ThumbView extends View {
|
||||
|
||||
private static final int EXTEND_TOUCH_SLOP = 15;
|
||||
|
||||
private final int mExtendTouchSlop;
|
||||
|
||||
private Drawable mThumbDrawable;
|
||||
|
||||
private boolean mPressed;
|
||||
|
||||
private int mThumbWidth;
|
||||
private int mTickIndex;
|
||||
|
||||
public ThumbView(Context context, int thumbWidth, Drawable drawable) {
|
||||
super(context);
|
||||
mThumbWidth = thumbWidth;
|
||||
mThumbDrawable = drawable;
|
||||
mExtendTouchSlop = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
|
||||
EXTEND_TOUCH_SLOP, context.getResources().getDisplayMetrics());
|
||||
setBackgroundDrawable(mThumbDrawable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(MeasureSpec.makeMeasureSpec(mThumbWidth, MeasureSpec.EXACTLY),
|
||||
MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY));
|
||||
|
||||
mThumbDrawable.setBounds(0, 0, mThumbWidth, getMeasuredHeight());
|
||||
}
|
||||
|
||||
public void setThumbWidth(int thumbWidth) {
|
||||
mThumbWidth = thumbWidth;
|
||||
}
|
||||
|
||||
public void setThumbDrawable(Drawable thumbDrawable) {
|
||||
mThumbDrawable = thumbDrawable;
|
||||
}
|
||||
|
||||
public boolean inInTarget(int x, int y) {
|
||||
Rect rect = new Rect();
|
||||
getHitRect(rect);
|
||||
rect.left -= mExtendTouchSlop;
|
||||
rect.right += mExtendTouchSlop;
|
||||
rect.top -= mExtendTouchSlop;
|
||||
rect.bottom += mExtendTouchSlop;
|
||||
return rect.contains(x, y);
|
||||
}
|
||||
|
||||
public int getRangeIndex() {
|
||||
return mTickIndex;
|
||||
}
|
||||
|
||||
public void setTickIndex(int tickIndex) {
|
||||
mTickIndex = tickIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPressed() {
|
||||
return mPressed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPressed(boolean pressed) {
|
||||
mPressed = pressed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package com.yunbao.video.custom;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.yunbao.video.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class ThumbnailAdapter extends RecyclerView.Adapter {
|
||||
|
||||
private static final int TYPE_HEADER = 0;
|
||||
private static final int TYPE_NORMAL = 1;
|
||||
|
||||
private Context mContext;
|
||||
private List<Bitmap> mList;
|
||||
private LayoutInflater mInflater;
|
||||
private int mScreenWdith;
|
||||
|
||||
public ThumbnailAdapter(Context context) {
|
||||
mContext = context;
|
||||
mList = new ArrayList<>();
|
||||
DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
|
||||
mScreenWdith = dm.widthPixels;
|
||||
mInflater = LayoutInflater.from(mContext);
|
||||
}
|
||||
|
||||
public void addBitmapList(List<Bitmap> list){
|
||||
mList.addAll(list);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void reverse() {
|
||||
if (mList.size() > 0) {
|
||||
Collections.reverse(mList);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
if (position == 0 || position == mList.size() + 1) {
|
||||
return TYPE_HEADER;
|
||||
} else {
|
||||
return TYPE_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View itemView;
|
||||
if (viewType == TYPE_HEADER) {
|
||||
itemView = new View(mContext);
|
||||
itemView.setLayoutParams(new ViewGroup.LayoutParams(mScreenWdith / 2, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
return new HeadVh(itemView);
|
||||
|
||||
} else {
|
||||
return new Vh(mInflater.inflate(R.layout.item_video_progress_thumbnail, parent, false));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(RecyclerView.ViewHolder vh, int position) {
|
||||
if (vh instanceof Vh) {
|
||||
((Vh) vh).setData(mList.get(position - 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mList.size() + 2;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onViewRecycled(RecyclerView.ViewHolder vh) {
|
||||
if (vh != null && vh instanceof Vh) {
|
||||
((Vh) vh).recycle();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class HeadVh extends RecyclerView.ViewHolder {
|
||||
public HeadVh(View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
}
|
||||
|
||||
class Vh extends RecyclerView.ViewHolder {
|
||||
|
||||
ImageView img;
|
||||
|
||||
public Vh(View itemView) {
|
||||
super(itemView);
|
||||
img = (ImageView) itemView;
|
||||
}
|
||||
|
||||
void setData(Bitmap bitmap) {
|
||||
img.setImageBitmap(bitmap);
|
||||
}
|
||||
|
||||
void recycle() {
|
||||
if (img != null) {
|
||||
img.setImageBitmap(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
109
video/src/main/java/com/yunbao/video/custom/VideoLoadingBar.java
Normal file
109
video/src/main/java/com/yunbao/video/custom/VideoLoadingBar.java
Normal file
@@ -0,0 +1,109 @@
|
||||
package com.yunbao.video.custom;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import com.yunbao.video.R;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/6/30.
|
||||
*/
|
||||
|
||||
public class VideoLoadingBar extends View {
|
||||
|
||||
private int mWidth;
|
||||
private RectF mBgRectF;
|
||||
private Paint mBgPaint;
|
||||
private Paint mFgPaint;
|
||||
private RectF mFgRectF;
|
||||
private float mRate;
|
||||
private boolean mLoading;
|
||||
private int mBgColor;//背景色
|
||||
private int mFgColor;//前景色
|
||||
|
||||
public VideoLoadingBar(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public VideoLoadingBar(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public VideoLoadingBar(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LoadingBar);
|
||||
mBgColor = ta.getColor(R.styleable.LoadingBar_lb_bg_color, 0xff000000);
|
||||
mFgColor = ta.getColor(R.styleable.LoadingBar_lb_fg_color, 0xffffffff);
|
||||
ta.recycle();
|
||||
initPaint();
|
||||
}
|
||||
|
||||
private void initPaint() {
|
||||
mBgPaint = new Paint();
|
||||
mBgPaint.setAntiAlias(true);
|
||||
mBgPaint.setDither(true);
|
||||
mBgPaint.setColor(mBgColor);
|
||||
mBgPaint.setStyle(Paint.Style.FILL);
|
||||
mBgRectF = new RectF();
|
||||
|
||||
mFgPaint = new Paint();
|
||||
mFgPaint.setAntiAlias(true);
|
||||
mFgPaint.setDither(true);
|
||||
mFgPaint.setColor(mFgColor);
|
||||
mFgPaint.setStyle(Paint.Style.FILL);
|
||||
mFgRectF = new RectF();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
mWidth = getMeasuredWidth();
|
||||
int height = getMeasuredHeight();
|
||||
mBgRectF.top = 0;
|
||||
mBgRectF.bottom = height;
|
||||
mFgRectF.top = 0;
|
||||
mFgRectF.bottom = height;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
mBgRectF.left = 0;
|
||||
mBgRectF.right = mWidth;
|
||||
canvas.drawRect(mBgRectF, mBgPaint);
|
||||
if (mLoading) {
|
||||
if (mRate > 1) {
|
||||
mRate = 1;
|
||||
}
|
||||
float barWidth = mRate * mWidth;
|
||||
float left = (mWidth - barWidth) / 2;
|
||||
mFgRectF.left = left;
|
||||
mFgRectF.right = left + barWidth;
|
||||
canvas.drawRect(mFgRectF, mFgPaint);
|
||||
if (mRate < 1) {
|
||||
mRate += 0.1f;
|
||||
postInvalidateDelayed(20);
|
||||
} else {
|
||||
mRate = 0;
|
||||
postInvalidateDelayed(150);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setLoading(boolean loading) {
|
||||
if (mLoading != loading) {
|
||||
mLoading = loading;
|
||||
mRate = 0;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void endLoading() {
|
||||
mLoading = false;
|
||||
mRate = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
package com.yunbao.video.custom;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by vinsonswang on 2017/11/6.
|
||||
*/
|
||||
|
||||
public class VideoProgressController {
|
||||
|
||||
private Context mContext;
|
||||
private VideoProgressView mVideoProgressView;
|
||||
private RecyclerView mRecyclerView;
|
||||
private boolean mIsTouching;
|
||||
private int mScrollState;
|
||||
private float mCurrentScroll;
|
||||
private long mCurrentTimeMs;
|
||||
private long mTotalDurationMs; // us
|
||||
private float mThumbnailPicListDisplayWidth; // 视频缩略图列表的宽度
|
||||
private float mVideoProgressDisplayWidth; // 视频进度条可显示宽度
|
||||
private int mThumbnailNum;
|
||||
private VideoProgressSeekListener mVideoProgressSeekListener;
|
||||
private float mScale;
|
||||
private int mFrameWidth;
|
||||
private List<RangeSliderViewContainer> mRangeSliderViewContainerList;
|
||||
private boolean mIsRangeSliderChanged;
|
||||
private ColorfulProgress mColorfulProgress;
|
||||
private List<SliderViewContainer> mSliderViewContainerList;
|
||||
|
||||
|
||||
public VideoProgressController(Context context, long durationMs) {
|
||||
mContext = context;
|
||||
DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
|
||||
mVideoProgressDisplayWidth = dm.widthPixels;
|
||||
mScale = dm.density;
|
||||
mFrameWidth = dp2px(30);
|
||||
mTotalDurationMs = durationMs;
|
||||
}
|
||||
|
||||
public void addRangeSliderView(final RangeSliderViewContainer rangeSliderView) {
|
||||
if (rangeSliderView == null) {
|
||||
return;
|
||||
}
|
||||
if (mRangeSliderViewContainerList == null) {
|
||||
mRangeSliderViewContainerList = new ArrayList<>();
|
||||
}
|
||||
mRangeSliderViewContainerList.add(rangeSliderView);
|
||||
mVideoProgressView.getParentView().addView(rangeSliderView);
|
||||
rangeSliderView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
rangeSliderView.changeStartViewLayoutParams();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean removeRangeSliderView(RangeSliderViewContainer rangeSliderView) {
|
||||
if (mVideoProgressView == null) {
|
||||
return false;
|
||||
}
|
||||
mVideoProgressView.getParentView().removeView(rangeSliderView);
|
||||
if (mRangeSliderViewContainerList == null || mRangeSliderViewContainerList.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
return mRangeSliderViewContainerList.remove(rangeSliderView);
|
||||
}
|
||||
|
||||
public View removeRangeSliderView(int index) {
|
||||
if (mVideoProgressView == null) {
|
||||
return null;
|
||||
}
|
||||
if (mRangeSliderViewContainerList == null || mRangeSliderViewContainerList.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
if (index > mRangeSliderViewContainerList.size() - 1) {
|
||||
return null;
|
||||
}
|
||||
RangeSliderViewContainer view = mRangeSliderViewContainerList.remove(index);
|
||||
mVideoProgressView.getParentView().removeView(view);
|
||||
return view;
|
||||
}
|
||||
|
||||
public RangeSliderViewContainer getRangeSliderView(int index) {
|
||||
if (mRangeSliderViewContainerList != null && index < mRangeSliderViewContainerList.size() && index >= 0) {
|
||||
return mRangeSliderViewContainerList.get(index);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addColorfulProgress(ColorfulProgress colorfulProgress) {
|
||||
if (colorfulProgress == null) {
|
||||
return;
|
||||
}
|
||||
colorfulProgress.setVideoProgressController(this);
|
||||
mColorfulProgress = colorfulProgress;
|
||||
mVideoProgressView.getParentView().addView(colorfulProgress);
|
||||
mColorfulProgress.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
changeColorfulProgressOffset();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void changeColorfulProgressOffset() {
|
||||
if (mColorfulProgress == null) {
|
||||
return;
|
||||
}
|
||||
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) mColorfulProgress.getLayoutParams();
|
||||
layoutParams.leftMargin = calculateColorfulProgressOffset();
|
||||
mColorfulProgress.requestLayout();
|
||||
}
|
||||
|
||||
public void removeColorfulProgress() {
|
||||
if (mColorfulProgress != null) {
|
||||
mVideoProgressView.getParentView().removeView(mColorfulProgress);
|
||||
}
|
||||
}
|
||||
|
||||
public void addSliderView(final SliderViewContainer sliderViewContainer) {
|
||||
if (sliderViewContainer == null) {
|
||||
return;
|
||||
}
|
||||
if (mSliderViewContainerList == null) {
|
||||
mSliderViewContainerList = new ArrayList<>();
|
||||
}
|
||||
mSliderViewContainerList.add(sliderViewContainer);
|
||||
sliderViewContainer.setVideoProgressControlloer(this);
|
||||
mVideoProgressView.getParentView().addView(sliderViewContainer);
|
||||
sliderViewContainer.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
sliderViewContainer.changeLayoutParams();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean removeSliderView(SliderViewContainer sliderViewContainer) {
|
||||
if (mVideoProgressView == null) {
|
||||
return false;
|
||||
}
|
||||
mVideoProgressView.getParentView().removeView(sliderViewContainer);
|
||||
if (mSliderViewContainerList == null || mSliderViewContainerList.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
return mSliderViewContainerList.remove(sliderViewContainer);
|
||||
}
|
||||
|
||||
public View removeSliderView(int index) {
|
||||
if (mVideoProgressView == null) {
|
||||
return null;
|
||||
}
|
||||
if (mSliderViewContainerList == null || mSliderViewContainerList.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
if (index > mSliderViewContainerList.size() - 1) {
|
||||
return null;
|
||||
}
|
||||
SliderViewContainer sliderViewContainer = mSliderViewContainerList.get(index);
|
||||
mVideoProgressView.getParentView().removeView(sliderViewContainer);
|
||||
return sliderViewContainer;
|
||||
}
|
||||
|
||||
|
||||
int calculateStartViewPosition(RangeSliderViewContainer rangeSliderView) {
|
||||
return (int) (mVideoProgressDisplayWidth / 2 - rangeSliderView.getStartView().getMeasuredWidth()
|
||||
+ duration2Distance(rangeSliderView.getStartTimeUs()) - mCurrentScroll);
|
||||
}
|
||||
|
||||
int calculateSliderViewPosition(SliderViewContainer sliderViewContainer) {
|
||||
return (int) (mVideoProgressDisplayWidth / 2 + duration2Distance(sliderViewContainer.getStartTimeMs()) - mCurrentScroll);
|
||||
}
|
||||
|
||||
int calculateColorfulProgressOffset() {
|
||||
return (int) (mVideoProgressDisplayWidth / 2 - mCurrentScroll);
|
||||
}
|
||||
|
||||
public int duration2Distance(long durationMs) {
|
||||
float rate = durationMs * 1.0f / mTotalDurationMs;
|
||||
return (int) (getThumbnailPicListDisplayWidth() * rate);
|
||||
}
|
||||
|
||||
long distance2Duration(float distance) {
|
||||
float rate = distance / getThumbnailPicListDisplayWidth();
|
||||
return (long) (mTotalDurationMs * rate);
|
||||
}
|
||||
|
||||
public void setVideoProgressSeekListener(VideoProgressSeekListener videoProgressSeekListener) {
|
||||
mVideoProgressSeekListener = videoProgressSeekListener;
|
||||
}
|
||||
|
||||
public void setVideoProgressView(VideoProgressView videoProgressView) {
|
||||
mVideoProgressView = videoProgressView;
|
||||
mRecyclerView = mVideoProgressView.getRecyclerView();
|
||||
mRecyclerView.setOnTouchListener(new View.OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(View view, MotionEvent motionEvent) {
|
||||
int eventId = motionEvent.getAction();
|
||||
switch (eventId) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mIsTouching = true;
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
mIsTouching = false;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
|
||||
super.onScrollStateChanged(recyclerView, newState);
|
||||
|
||||
switch (newState) {
|
||||
case RecyclerView.SCROLL_STATE_IDLE:
|
||||
|
||||
if (mVideoProgressSeekListener != null) {
|
||||
mVideoProgressSeekListener.onVideoProgressSeekFinish(mCurrentTimeMs);
|
||||
}
|
||||
if (mRangeSliderViewContainerList != null && mRangeSliderViewContainerList.size() > 0) {
|
||||
for (RangeSliderViewContainer rangeSliderView : mRangeSliderViewContainerList) {
|
||||
rangeSliderView.changeStartViewLayoutParams();
|
||||
}
|
||||
}
|
||||
|
||||
if (mColorfulProgress != null) {
|
||||
mColorfulProgress.setCurPosition(mCurrentScroll);
|
||||
changeColorfulProgressOffset();
|
||||
}
|
||||
|
||||
if (mSliderViewContainerList != null && mSliderViewContainerList.size() > 0) {
|
||||
for (SliderViewContainer sliderViewContainer : mSliderViewContainerList) {
|
||||
sliderViewContainer.changeLayoutParams();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case RecyclerView.SCROLL_STATE_DRAGGING:
|
||||
|
||||
break;
|
||||
case RecyclerView.SCROLL_STATE_SETTLING:
|
||||
|
||||
break;
|
||||
}
|
||||
mScrollState = newState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
||||
super.onScrolled(recyclerView, dx, dy);
|
||||
|
||||
mCurrentScroll = mCurrentScroll + dx;
|
||||
float rate = mCurrentScroll / getThumbnailPicListDisplayWidth();
|
||||
long currentTimeUs = (long) (rate * mTotalDurationMs);
|
||||
|
||||
|
||||
if (mIsTouching || mIsRangeSliderChanged || mScrollState == RecyclerView.SCROLL_STATE_SETTLING) {
|
||||
mIsRangeSliderChanged = false; // 由于范围改变引起的,回调给界面后保证能单帧预览,之后马上重置
|
||||
if (mVideoProgressSeekListener != null) {
|
||||
mVideoProgressSeekListener.onVideoProgressSeek(currentTimeUs);
|
||||
}
|
||||
}
|
||||
mCurrentTimeMs = currentTimeUs;
|
||||
if (mRangeSliderViewContainerList != null && mRangeSliderViewContainerList.size() > 0) {
|
||||
for (RangeSliderViewContainer rangeSliderView : mRangeSliderViewContainerList) {
|
||||
rangeSliderView.changeStartViewLayoutParams();
|
||||
}
|
||||
}
|
||||
|
||||
if (mColorfulProgress != null) {
|
||||
mColorfulProgress.setCurPosition(mCurrentScroll);
|
||||
changeColorfulProgressOffset();
|
||||
}
|
||||
if (mSliderViewContainerList != null && mSliderViewContainerList.size() > 0) {
|
||||
for (SliderViewContainer sliderViewContainer : mSliderViewContainerList) {
|
||||
sliderViewContainer.changeLayoutParams();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前时间ms
|
||||
*
|
||||
* @param currentTimeMs
|
||||
*/
|
||||
public void setCurrentTimeMs(long currentTimeMs) {
|
||||
mCurrentTimeMs = currentTimeMs;
|
||||
float rate = (float) mCurrentTimeMs / mTotalDurationMs;
|
||||
float scrollBy = rate * getThumbnailPicListDisplayWidth() - mCurrentScroll;
|
||||
mRecyclerView.scrollBy((int) scrollBy, 0);
|
||||
}
|
||||
|
||||
public long getCurrentTimeMs() {
|
||||
return mCurrentTimeMs;
|
||||
}
|
||||
|
||||
public long getTotalDurationMs() {
|
||||
return mTotalDurationMs;
|
||||
}
|
||||
|
||||
public void setIsRangeSliderChanged(boolean isRangeSliderChanged) {
|
||||
mIsRangeSliderChanged = isRangeSliderChanged;
|
||||
}
|
||||
|
||||
private void scroll(float rate) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缩略图列表的长度,需要在设置完数据之后调用,否则返回0
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public float getThumbnailPicListDisplayWidth() {
|
||||
if (mThumbnailPicListDisplayWidth == 0) {
|
||||
mThumbnailNum = mVideoProgressView.getThumbnailCount();
|
||||
mThumbnailPicListDisplayWidth = mThumbnailNum * mFrameWidth;
|
||||
}
|
||||
return mThumbnailPicListDisplayWidth;
|
||||
}
|
||||
|
||||
public interface VideoProgressSeekListener {
|
||||
void onVideoProgressSeek(long currentTimeMs);
|
||||
|
||||
void onVideoProgressSeekFinish(long currentTimeMs);
|
||||
}
|
||||
|
||||
private int dp2px(int dpVal) {
|
||||
return (int) (mScale * dpVal + 0.5f);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.yunbao.video.custom;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import androidx.annotation.AttrRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.yunbao.video.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by vinsonswang on 2017/11/6.
|
||||
*/
|
||||
|
||||
public class VideoProgressView extends FrameLayout {
|
||||
|
||||
private Context mContext;
|
||||
private View mRootView;
|
||||
private RecyclerView mRecyclerView;
|
||||
private ThumbnailAdapter mThumbnailAdapter;
|
||||
|
||||
public VideoProgressView(@NonNull Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public VideoProgressView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public VideoProgressView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mRootView = LayoutInflater.from(mContext).inflate(R.layout.layout_video_progress, this, false);
|
||||
mRecyclerView = (RecyclerView) mRootView.findViewById(R.id.rv_video_thumbnail);
|
||||
mRecyclerView.setHasFixedSize(true);
|
||||
mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false));
|
||||
mThumbnailAdapter = new ThumbnailAdapter(mContext);
|
||||
mRecyclerView.setAdapter(mThumbnailAdapter);
|
||||
addView(mRootView);
|
||||
}
|
||||
|
||||
public void addBitmapList(List<Bitmap> list){
|
||||
if(mThumbnailAdapter!=null){
|
||||
mThumbnailAdapter.addBitmapList(list);
|
||||
}
|
||||
}
|
||||
|
||||
public void reverse() {
|
||||
if (mThumbnailAdapter != null) {
|
||||
mThumbnailAdapter.reverse();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public RecyclerView getRecyclerView() {
|
||||
return mRecyclerView;
|
||||
}
|
||||
|
||||
public int getThumbnailCount() {
|
||||
if (mThumbnailAdapter != null) {
|
||||
return mThumbnailAdapter.getItemCount() - 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public ViewGroup getParentView() {
|
||||
return (ViewGroup) mRootView;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.yunbao.video.custom;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import com.yunbao.video.R;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/5.
|
||||
*/
|
||||
|
||||
public class VideoRecordBtnView extends View {
|
||||
|
||||
private static final int RATE_MAX = 100;
|
||||
private int mMaxWidth;
|
||||
private int mMinWidth;
|
||||
private int mStartWidth;
|
||||
private int mRate;
|
||||
private int mStrokeWidth;
|
||||
private Paint mPaint;
|
||||
private int mRadius;
|
||||
private Path mBgPath;
|
||||
private Path mFgPath;
|
||||
|
||||
public VideoRecordBtnView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public VideoRecordBtnView(Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public VideoRecordBtnView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.VideoRecordBtnView);
|
||||
mMaxWidth = (int) ta.getDimension(R.styleable.VideoRecordBtnView_vrb_max_width, 0);
|
||||
mMinWidth = (int) ta.getDimension(R.styleable.VideoRecordBtnView_vrb_min_width, 0);
|
||||
mStartWidth = (int) ta.getDimension(R.styleable.VideoRecordBtnView_vrb_start_width, 0);
|
||||
int color = ta.getColor(R.styleable.VideoRecordBtnView_vrb_color, 0);
|
||||
ta.recycle();
|
||||
mRate = RATE_MAX;
|
||||
mStrokeWidth = mStartWidth;
|
||||
mPaint = new Paint();
|
||||
mPaint.setAntiAlias(true);
|
||||
mPaint.setDither(true);
|
||||
mPaint.setColor(color);
|
||||
mPaint.setStyle(Paint.Style.FILL);
|
||||
mBgPath = new Path();
|
||||
mFgPath = new Path();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
mRadius = w / 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
|
||||
heightMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
mBgPath.reset();
|
||||
mBgPath.addCircle(mRadius, mRadius, mRadius, Path.Direction.CW);
|
||||
mFgPath.reset();
|
||||
mFgPath.addCircle(mRadius, mRadius, mRadius - mStrokeWidth, Path.Direction.CW);
|
||||
mBgPath.op(mFgPath, Path.Op.DIFFERENCE);
|
||||
canvas.drawPath(mBgPath, mPaint);
|
||||
}
|
||||
|
||||
public void setRate(int rate) {
|
||||
if (rate < 0) {
|
||||
rate = 0;
|
||||
}
|
||||
if (rate > RATE_MAX) {
|
||||
rate = RATE_MAX;
|
||||
}
|
||||
if (mRate == rate) {
|
||||
return;
|
||||
}
|
||||
mRate = rate;
|
||||
int strokeWidth = calculateStrokeWidth();
|
||||
if (mStrokeWidth == strokeWidth) {
|
||||
return;
|
||||
}
|
||||
mStrokeWidth = strokeWidth;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
mStrokeWidth = mStartWidth;
|
||||
mRate = RATE_MAX;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private int calculateStrokeWidth() {
|
||||
return (int) (mMinWidth + (mMaxWidth - mMinWidth) * mRate / 100f);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.yunbao.video.custom;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* Created by vinsonswang on 2017/11/7.
|
||||
*/
|
||||
|
||||
public class ViewTouchProcess implements View.OnTouchListener{
|
||||
private final String TAG = "RangeSliderChildViewTouchProcess";
|
||||
private View mView;
|
||||
private float mStartX;
|
||||
private OnPositionChangedListener mOnPositionChangedListener;
|
||||
|
||||
public interface OnPositionChangedListener{
|
||||
void onPostionChanged(float distance);
|
||||
void onChangeComplete();
|
||||
}
|
||||
|
||||
public ViewTouchProcess(View view){
|
||||
mView = view;
|
||||
mView.setOnTouchListener(this);
|
||||
}
|
||||
|
||||
public void setOnPositionChangedListener(OnPositionChangedListener onPositionChangedListener){
|
||||
mOnPositionChangedListener = onPositionChangedListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View view, MotionEvent motionEvent) {
|
||||
int eventId = motionEvent.getAction();
|
||||
switch (eventId){
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mStartX = motionEvent.getRawX();
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
float dx = motionEvent.getRawX() - mStartX;
|
||||
mStartX = motionEvent.getRawX();
|
||||
if(mOnPositionChangedListener != null){
|
||||
mOnPositionChangedListener.onPostionChanged(dx);
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
if(mOnPositionChangedListener != null){
|
||||
mOnPositionChangedListener.onChangeComplete();
|
||||
}
|
||||
mStartX = 0;
|
||||
break;
|
||||
default:
|
||||
mStartX = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
package com.yunbao.video.dialog;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.yunbao.common.Constants;
|
||||
import com.yunbao.common.bean.UserBean;
|
||||
import com.yunbao.common.dialog.AbsDialogFragment;
|
||||
import com.yunbao.common.dialog.ChatFaceDialog;
|
||||
import com.yunbao.common.http.HttpCallback;
|
||||
import com.yunbao.common.utils.DpUtil;
|
||||
import com.yunbao.common.utils.ToastUtil;
|
||||
import com.yunbao.common.utils.WordUtil;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.activity.AbsVideoPlayActivity;
|
||||
import com.yunbao.video.bean.VideoCommentBean;
|
||||
import com.yunbao.video.event.VideoCommentEvent;
|
||||
import com.yunbao.video.http.VideoHttpConsts;
|
||||
import com.yunbao.video.http.VideoHttpUtil;
|
||||
import com.yunbao.video.utils.VideoTextRender;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/3.
|
||||
* 视频评论输入框
|
||||
*/
|
||||
|
||||
public class VideoInputDialogFragment extends AbsDialogFragment implements View.OnClickListener, ChatFaceDialog.ActionListener {
|
||||
|
||||
private InputMethodManager imm;
|
||||
private EditText mInput;
|
||||
private boolean mOpenFace;
|
||||
private int mOriginHeight;
|
||||
private int mFaceHeight;
|
||||
private CheckBox mCheckBox;
|
||||
private ChatFaceDialog mChatFaceDialog;
|
||||
private Handler mHandler;
|
||||
private String mVideoId;
|
||||
private String mVideoUid;
|
||||
private VideoCommentBean mVideoCommentBean;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.dialog_video_input;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDialogStyle() {
|
||||
return R.style.dialog2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canCancel() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setWindowAttributes(Window window) {
|
||||
window.setWindowAnimations(R.style.bottomToTopAnim);
|
||||
WindowManager.LayoutParams params = window.getAttributes();
|
||||
params.width = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
mOriginHeight = DpUtil.dp2px(48);
|
||||
params.height = mOriginHeight;
|
||||
params.gravity = Gravity.BOTTOM;
|
||||
window.setAttributes(params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
mHandler = new Handler();
|
||||
mInput = (EditText) mRootView.findViewById(R.id.input);
|
||||
mInput.setOnClickListener(this);
|
||||
mCheckBox = mRootView.findViewById(R.id.btn_face);
|
||||
mCheckBox.setOnClickListener(this);
|
||||
mInput.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if (actionId == EditorInfo.IME_ACTION_SEND) {
|
||||
sendComment();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
Bundle bundle = getArguments();
|
||||
if (bundle != null) {
|
||||
mOpenFace = bundle.getBoolean(Constants.VIDEO_FACE_OPEN, false);
|
||||
mFaceHeight = bundle.getInt(Constants.VIDEO_FACE_HEIGHT, 0);
|
||||
mVideoCommentBean = bundle.getParcelable(Constants.VIDEO_COMMENT_BEAN);
|
||||
if (mVideoCommentBean != null) {
|
||||
UserBean replyUserBean = mVideoCommentBean.getUserBean();//要回复的人
|
||||
if (replyUserBean != null) {
|
||||
mInput.setHint(WordUtil.getString(R.string.video_comment_reply) + replyUserBean.getUserNiceName());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mOpenFace) {
|
||||
if (mCheckBox != null) {
|
||||
mCheckBox.setChecked(true);
|
||||
}
|
||||
if (mFaceHeight > 0) {
|
||||
changeHeight(mFaceHeight);
|
||||
if (mHandler != null) {
|
||||
mHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showFace();
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mHandler != null) {
|
||||
mHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showSoftInput();
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setVideoInfo(String videoId, String videoUid) {
|
||||
mVideoId = videoId;
|
||||
mVideoUid = videoUid;
|
||||
}
|
||||
|
||||
private void showSoftInput() {
|
||||
//软键盘弹出
|
||||
if (imm != null) {
|
||||
imm.showSoftInput(mInput, InputMethodManager.SHOW_FORCED);
|
||||
}
|
||||
if (mInput != null) {
|
||||
mInput.requestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
private void hideSoftInput() {
|
||||
if (imm != null) {
|
||||
imm.hideSoftInputFromWindow(mInput.getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.SET_COMMENT);
|
||||
if (mHandler != null) {
|
||||
mHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
mHandler = null;
|
||||
if (mChatFaceDialog != null) {
|
||||
mChatFaceDialog.dismiss();
|
||||
}
|
||||
mChatFaceDialog = null;
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (!canClick()) {
|
||||
return;
|
||||
}
|
||||
int i = v.getId();
|
||||
if (i == R.id.btn_face) {
|
||||
clickFace();
|
||||
|
||||
} else if (i == R.id.input) {
|
||||
clickInput();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void clickInput() {
|
||||
hideFace();
|
||||
if (mCheckBox != null) {
|
||||
mCheckBox.setChecked(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void clickFace() {
|
||||
if (mCheckBox.isChecked()) {
|
||||
hideSoftInput();
|
||||
if (mHandler != null) {
|
||||
mHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showFace();
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
} else {
|
||||
hideFace();
|
||||
showSoftInput();
|
||||
}
|
||||
}
|
||||
|
||||
private void showFace() {
|
||||
if (mFaceHeight > 0) {
|
||||
changeHeight(mFaceHeight);
|
||||
View faceView = ((AbsVideoPlayActivity) mContext).getFaceView();
|
||||
if (faceView != null) {
|
||||
mChatFaceDialog = new ChatFaceDialog(mRootView, faceView, false, VideoInputDialogFragment.this);
|
||||
mChatFaceDialog.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void hideFace() {
|
||||
if (mChatFaceDialog != null) {
|
||||
mChatFaceDialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 改变高度
|
||||
*/
|
||||
private void changeHeight(int deltaHeight) {
|
||||
Dialog dialog = getDialog();
|
||||
if (dialog == null) {
|
||||
return;
|
||||
}
|
||||
Window window = dialog.getWindow();
|
||||
if (window == null) {
|
||||
return;
|
||||
}
|
||||
WindowManager.LayoutParams params = window.getAttributes();
|
||||
params.height = mOriginHeight + deltaHeight;
|
||||
window.setAttributes(params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFaceDialogDismiss() {
|
||||
changeHeight(0);
|
||||
mChatFaceDialog = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发表评论
|
||||
*/
|
||||
public void sendComment() {
|
||||
if (TextUtils.isEmpty(mVideoId) || TextUtils.isEmpty(mVideoUid) || mInput == null || !canClick()) {
|
||||
return;
|
||||
}
|
||||
String content = mInput.getText().toString().trim();
|
||||
if (TextUtils.isEmpty(content)) {
|
||||
ToastUtil.show(R.string.content_empty);
|
||||
return;
|
||||
}
|
||||
String toUid = mVideoUid;
|
||||
String commentId = "0";
|
||||
String parentId = "0";
|
||||
if (mVideoCommentBean != null) {
|
||||
toUid = mVideoCommentBean.getUid();
|
||||
commentId = mVideoCommentBean.getCommentId();
|
||||
parentId = mVideoCommentBean.getId();
|
||||
}
|
||||
VideoHttpUtil.setComment(toUid, mVideoId, content, commentId, parentId, new HttpCallback() {
|
||||
@Override
|
||||
public void onSuccess(int code, String msg, String[] info) {
|
||||
if (code == 0 && info.length > 0) {
|
||||
if (mInput != null) {
|
||||
mInput.setText("");
|
||||
}
|
||||
JSONObject obj = JSON.parseObject(info[0]);
|
||||
String commentNum = obj.getString("comments");
|
||||
EventBus.getDefault().post(new VideoCommentEvent(mVideoId, commentNum));
|
||||
ToastUtil.show(msg);
|
||||
dismiss();
|
||||
((AbsVideoPlayActivity) mContext).hideCommentWindow(true);
|
||||
} else if (code == 500) {
|
||||
ToastUtil.show(msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击表情上面的删除按钮
|
||||
*/
|
||||
public void onFaceDeleteClick() {
|
||||
if (mInput != null) {
|
||||
int selection = mInput.getSelectionStart();
|
||||
String text = mInput.getText().toString();
|
||||
if (selection > 0) {
|
||||
String text2 = text.substring(selection - 1, selection);
|
||||
if ("]".equals(text2)) {
|
||||
int start = text.lastIndexOf("[", selection);
|
||||
if (start >= 0) {
|
||||
mInput.getText().delete(start, selection);
|
||||
} else {
|
||||
mInput.getText().delete(selection - 1, selection);
|
||||
}
|
||||
} else {
|
||||
mInput.getText().delete(selection - 1, selection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击表情
|
||||
*/
|
||||
public void onFaceClick(String str, int faceImageRes) {
|
||||
if (mInput != null) {
|
||||
Editable editable = mInput.getText();
|
||||
editable.insert(mInput.getSelectionStart(), VideoTextRender.getFaceImageSpan(str, faceImageRes));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package com.yunbao.video.dialog;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.PopupWindow;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.yunbao.common.adapter.RefreshAdapter;
|
||||
import com.yunbao.common.custom.CommonRefreshView;
|
||||
import com.yunbao.common.http.HttpCallback;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.adapter.MusicAdapter;
|
||||
import com.yunbao.video.bean.MusicBean;
|
||||
import com.yunbao.video.http.VideoHttpConsts;
|
||||
import com.yunbao.video.http.VideoHttpUtil;
|
||||
import com.yunbao.video.interfaces.VideoMusicActionListener;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/7.
|
||||
*/
|
||||
|
||||
public class VideoMusicClassDialog extends PopupWindow implements View.OnClickListener {
|
||||
|
||||
private Context mContext;
|
||||
private View mParent;
|
||||
private String mTitle;
|
||||
private String mClassId;
|
||||
private CommonRefreshView mRefreshView;
|
||||
private MusicAdapter mAdapter;
|
||||
private VideoMusicActionListener mActionListener;
|
||||
|
||||
public VideoMusicClassDialog(Context context, View parent, String title, String classId, VideoMusicActionListener actionListener) {
|
||||
mContext = context;
|
||||
mParent = parent;
|
||||
mTitle = title;
|
||||
mClassId = classId;
|
||||
mActionListener = actionListener;
|
||||
setContentView(initView());
|
||||
setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
setBackgroundDrawable(new ColorDrawable());
|
||||
setOutsideTouchable(true);
|
||||
setClippingEnabled(false);
|
||||
setFocusable(true);
|
||||
setAnimationStyle(R.style.leftToRightAnim);
|
||||
setOnDismissListener(new OnDismissListener() {
|
||||
@Override
|
||||
public void onDismiss() {
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.GET_MUSIC_LIST);
|
||||
if (mAdapter != null) {
|
||||
mAdapter.setActionListener(null);
|
||||
}
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onStopMusic();
|
||||
}
|
||||
mActionListener = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private View initView() {
|
||||
View v = LayoutInflater.from(mContext).inflate(R.layout.view_video_music_class, null);
|
||||
TextView title = v.findViewById(R.id.title);
|
||||
if (!TextUtils.isEmpty(mTitle)) {
|
||||
title.setText(mTitle);
|
||||
}
|
||||
mRefreshView = v.findViewById(R.id.refreshView);
|
||||
mRefreshView.setEmptyLayoutId(R.layout.view_no_data_music_class);
|
||||
mRefreshView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false));
|
||||
|
||||
mRefreshView.setDataHelper(new CommonRefreshView.DataHelper<MusicBean>() {
|
||||
@Override
|
||||
public RefreshAdapter<MusicBean> getAdapter() {
|
||||
if (mAdapter == null) {
|
||||
mAdapter = new MusicAdapter(mContext);
|
||||
mAdapter.setActionListener(mActionListener);
|
||||
}
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadData(int p, HttpCallback callback) {
|
||||
if (!TextUtils.isEmpty(mClassId)) {
|
||||
VideoHttpUtil.getMusicList(mClassId, p, callback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MusicBean> processData(String[] info) {
|
||||
return JSON.parseArray(Arrays.toString(info), MusicBean.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefreshSuccess(List<MusicBean> list, int listCount) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefreshFailure() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMoreSuccess(List<MusicBean> loadItemList, int loadItemCount) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMoreFailure() {
|
||||
|
||||
}
|
||||
});
|
||||
v.findViewById(R.id.btn_close).setOnClickListener(this);
|
||||
return v;
|
||||
}
|
||||
|
||||
public void show() {
|
||||
showAtLocation(mParent, Gravity.BOTTOM, 0, 0);
|
||||
if (mRefreshView != null) {
|
||||
mRefreshView.initData();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dismiss();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.yunbao.video.dialog;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.Gravity;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.yunbao.common.CommonAppConfig;
|
||||
import com.yunbao.common.Constants;
|
||||
import com.yunbao.common.bean.ConfigBean;
|
||||
import com.yunbao.common.dialog.AbsDialogFragment;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.bean.VideoBean;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/10/19.
|
||||
* 视频分享弹窗
|
||||
*/
|
||||
|
||||
public class VideoShareDialogFragment extends AbsDialogFragment {
|
||||
|
||||
private RecyclerView mRecyclerView;
|
||||
private RecyclerView mRecyclerView2;
|
||||
private VideoBean mVideoBean;
|
||||
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.dialog_video_share;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDialogStyle() {
|
||||
return R.style.dialog2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canCancel() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setWindowAttributes(Window window) {
|
||||
window.setWindowAnimations(R.style.bottomToTopAnim);
|
||||
WindowManager.LayoutParams params = window.getAttributes();
|
||||
params.width = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
||||
params.gravity = Gravity.BOTTOM;
|
||||
window.setAttributes(params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
Bundle bundle = getArguments();
|
||||
if (bundle == null) {
|
||||
return;
|
||||
}
|
||||
mVideoBean = bundle.getParcelable(Constants.VIDEO_BEAN);
|
||||
if (mVideoBean == null) {
|
||||
return;
|
||||
}
|
||||
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
|
||||
mRecyclerView.setHasFixedSize(true);
|
||||
mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false));
|
||||
mRecyclerView2 = (RecyclerView) findViewById(R.id.recyclerView_2);
|
||||
mRecyclerView2.setHasFixedSize(true);
|
||||
mRecyclerView2.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false));
|
||||
// List<MobBean> list = null;
|
||||
ConfigBean configBean = CommonAppConfig.getInstance().getConfig();
|
||||
if (configBean != null) {
|
||||
// list = MobBean.getVideoShareTypeList(configBean.getVideoShareTypes());
|
||||
}
|
||||
// if (list != null) {
|
||||
// VideoShareAdapter adapter = new VideoShareAdapter(mContext, list);
|
||||
// adapter.setOnItemClickListener(this);
|
||||
// mRecyclerView.setAdapter(adapter);
|
||||
// }
|
||||
// List<MobBean> list2 = new ArrayList<>();
|
||||
// MobBean linkBean = new MobBean();
|
||||
// linkBean.setType(Constants.LINK);
|
||||
// linkBean.setName(R.string.copy_link);
|
||||
// linkBean.setIcon1(R.mipmap.icon_share_video_link);
|
||||
// list2.add(linkBean);
|
||||
// MobBean reportBean = new MobBean();
|
||||
// if (mVideoBean.getUid().equals(CommonAppConfig.getInstance().getUid())) {//自己的视频
|
||||
// reportBean.setType(Constants.DELETE);
|
||||
// reportBean.setName(R.string.delete);
|
||||
// reportBean.setIcon1(R.mipmap.icon_share_video_delete);
|
||||
// } else {
|
||||
// reportBean.setType(Constants.REPORT);
|
||||
// reportBean.setName(R.string.report);
|
||||
// reportBean.setIcon1(R.mipmap.icon_share_video_report);
|
||||
// }
|
||||
// list2.add(reportBean);
|
||||
// MobBean saveBean = new MobBean();
|
||||
// saveBean.setType(Constants.SAVE);
|
||||
// saveBean.setName(R.string.save);
|
||||
// saveBean.setIcon1(R.mipmap.icon_share_video_save);
|
||||
// list2.add(saveBean);
|
||||
// VideoShareAdapter adapter2 = new VideoShareAdapter(mContext, list2);
|
||||
// adapter2.setOnItemClickListener(this);
|
||||
// mRecyclerView2.setAdapter(adapter2);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.yunbao.video.event;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/17.
|
||||
*/
|
||||
|
||||
public class VideoCommentEvent {
|
||||
private String mVideoId;
|
||||
private String mCommentNum;
|
||||
|
||||
public VideoCommentEvent(String videoId, String commentNum) {
|
||||
mVideoId = videoId;
|
||||
mCommentNum = commentNum;
|
||||
}
|
||||
|
||||
public String getVideoId() {
|
||||
return mVideoId;
|
||||
}
|
||||
|
||||
public void setVideoId(String videoId) {
|
||||
mVideoId = videoId;
|
||||
}
|
||||
|
||||
public String getCommentNum() {
|
||||
return mCommentNum;
|
||||
}
|
||||
|
||||
public void setCommentNum(String commentNum) {
|
||||
mCommentNum = commentNum;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.yunbao.video.event;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/15.
|
||||
*/
|
||||
|
||||
public class VideoDeleteEvent {
|
||||
|
||||
private String mVideoId;
|
||||
|
||||
public VideoDeleteEvent(String videoId) {
|
||||
mVideoId = videoId;
|
||||
}
|
||||
|
||||
public String getVideoId() {
|
||||
return mVideoId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.yunbao.video.event;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/17.
|
||||
*/
|
||||
|
||||
public class VideoLikeEvent {
|
||||
private String videoId;
|
||||
private int isLike;
|
||||
private String likeNum;
|
||||
|
||||
public VideoLikeEvent(String videoId, int isLike, String likeNum) {
|
||||
this.videoId = videoId;
|
||||
this.isLike = isLike;
|
||||
this.likeNum = likeNum;
|
||||
}
|
||||
|
||||
public String getVideoId() {
|
||||
return videoId;
|
||||
}
|
||||
|
||||
public void setVideoId(String videoId) {
|
||||
this.videoId = videoId;
|
||||
}
|
||||
|
||||
public int getIsLike() {
|
||||
return isLike;
|
||||
}
|
||||
|
||||
public void setIsLike(int isLike) {
|
||||
this.isLike = isLike;
|
||||
}
|
||||
|
||||
public String getLikeNum() {
|
||||
return likeNum;
|
||||
}
|
||||
|
||||
public void setLikeNum(String likeNum) {
|
||||
this.likeNum = likeNum;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.yunbao.video.event;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/15.
|
||||
*/
|
||||
|
||||
public class VideoScrollPageEvent {
|
||||
|
||||
private String mKey;
|
||||
private int mPage;
|
||||
|
||||
public VideoScrollPageEvent(String key, int page) {
|
||||
mKey = key;
|
||||
mPage = page;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return mKey;
|
||||
}
|
||||
|
||||
public int getPage() {
|
||||
return mPage;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.yunbao.video.event;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/17.
|
||||
*/
|
||||
|
||||
public class VideoShareEvent {
|
||||
private String videoId;
|
||||
private String shareNum;
|
||||
|
||||
public VideoShareEvent(String videoId, String shareNum) {
|
||||
this.videoId = videoId;
|
||||
this.shareNum = shareNum;
|
||||
}
|
||||
|
||||
public String getVideoId() {
|
||||
return videoId;
|
||||
}
|
||||
|
||||
public void setVideoId(String videoId) {
|
||||
this.videoId = videoId;
|
||||
}
|
||||
|
||||
public String getShareNum() {
|
||||
return shareNum;
|
||||
}
|
||||
|
||||
public void setShareNum(String shareNum) {
|
||||
this.shareNum = shareNum;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.yunbao.video.http;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2019/2/16.
|
||||
*/
|
||||
|
||||
public class VideoHttpConsts {
|
||||
public static final String GET_HOME_VIDEO_LIST = "getHomeVideoList";
|
||||
public static final String GET_VIDEO_COMMENT_LIST = "getVideoCommentList";
|
||||
public static final String SET_COMMENT_LIKE = "setCommentLike";
|
||||
public static final String SET_COMMENT = "setComment";
|
||||
public static final String GET_COMMENT_REPLY = "getCommentReply";
|
||||
public static final String GET_MUSIC_CLASS_LIST = "getMusicClassList";
|
||||
public static final String GET_HOT_MUSIC_LIST = "getHotMusicList";
|
||||
public static final String SET_MUSIC_COLLECT = "setMusicCollect";
|
||||
public static final String GET_MUSIC_COLLECT_LIST = "getMusicCollectList";
|
||||
public static final String GET_MUSIC_LIST = "getMusicList";
|
||||
public static final String VIDEO_SEARCH_MUSIC = "videoSearchMusic";
|
||||
public static final String GET_QI_NIU_TOKEN = "getQiNiuToken";
|
||||
public static final String SAVE_UPLOAD_VIDEO_INFO = "saveUploadVideoInfo";
|
||||
public static final String GET_HOME_VIDEO = "getHomeVideo";
|
||||
public static final String GET_VIDEO_REPORT_LIST = "getVideoReportList";
|
||||
public static final String VIDEO_REPORT = "videoReport";
|
||||
public static final String VIDEO_DELETE = "videoDelete";
|
||||
public static final String SET_VIDEO_SHARE = "setVideoShare";
|
||||
public static final String VIDEO_WATCH_START = "videoWatchStart";
|
||||
public static final String VIDEO_WATCH_END = "videoWatchEnd";
|
||||
}
|
||||
309
video/src/main/java/com/yunbao/video/http/VideoHttpUtil.java
Normal file
309
video/src/main/java/com/yunbao/video/http/VideoHttpUtil.java
Normal file
@@ -0,0 +1,309 @@
|
||||
package com.yunbao.video.http;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.lzy.okgo.OkGo;
|
||||
import com.lzy.okgo.callback.StringCallback;
|
||||
import com.yunbao.common.CommonAppConfig;
|
||||
import com.yunbao.common.http.CommonHttpUtil;
|
||||
import com.yunbao.common.http.HttpCallback;
|
||||
import com.yunbao.common.http.HttpClient;
|
||||
import com.yunbao.common.utils.MD5Util;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/9/17.
|
||||
*/
|
||||
|
||||
public class VideoHttpUtil {
|
||||
|
||||
private static final String VIDEO_SALT = "#2hgfk85cm23mk58vncsark";
|
||||
|
||||
/**
|
||||
* 取消网络请求
|
||||
*/
|
||||
public static void cancel(String tag) {
|
||||
HttpClient.getInstance().cancel(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取首页视频列表
|
||||
*/
|
||||
public static void getHomeVideoList(int p, HttpCallback callback) {
|
||||
HttpClient.getInstance().get("Video.getVideoList", VideoHttpConsts.GET_HOME_VIDEO_LIST)
|
||||
.params("uid", CommonAppConfig.getInstance().getUid())
|
||||
.params("token", CommonAppConfig.getInstance().getToken())
|
||||
.params("p", p)
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 视频点赞
|
||||
*/
|
||||
public static void setVideoLike(String tag, String videoid, HttpCallback callback) {
|
||||
HttpClient.getInstance().get("Video.addLike", tag)
|
||||
.params("uid", CommonAppConfig.getInstance().getUid())
|
||||
.params("token", CommonAppConfig.getInstance().getToken())
|
||||
.params("videoid", videoid)
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取视频评论
|
||||
*/
|
||||
public static void getVideoCommentList(String videoid, int p, HttpCallback callback) {
|
||||
HttpClient.getInstance().get("Video.getComments", VideoHttpConsts.GET_VIDEO_COMMENT_LIST)
|
||||
.params("uid", CommonAppConfig.getInstance().getUid())
|
||||
.params("token", CommonAppConfig.getInstance().getToken())
|
||||
.params("videoid", videoid)
|
||||
.params("p", p)
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 评论点赞
|
||||
*/
|
||||
public static void setCommentLike(String commentid, HttpCallback callback) {
|
||||
HttpClient.getInstance().get("Video.addCommentLike", VideoHttpConsts.SET_COMMENT_LIKE)
|
||||
.params("commentid", commentid)
|
||||
.params("uid", CommonAppConfig.getInstance().getUid())
|
||||
.params("token", CommonAppConfig.getInstance().getToken())
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发表评论
|
||||
*/
|
||||
public static void setComment(String toUid, String videoId, String content, String commentId, String parentId, HttpCallback callback) {
|
||||
HttpClient.getInstance().get("Video.setComment", VideoHttpConsts.SET_COMMENT)
|
||||
.params("uid", CommonAppConfig.getInstance().getUid())
|
||||
.params("token", CommonAppConfig.getInstance().getToken())
|
||||
.params("touid", toUid)
|
||||
.params("videoid", videoId)
|
||||
.params("commentid", commentId)
|
||||
.params("parentid", parentId)
|
||||
.params("content", content)
|
||||
.params("at_info", "")
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取评论回复
|
||||
*/
|
||||
public static void getCommentReply(String commentid, int p, HttpCallback callback) {
|
||||
HttpClient.getInstance().get("Video.getReplys", VideoHttpConsts.GET_COMMENT_REPLY)
|
||||
.params("commentid", commentid)
|
||||
.params("uid", CommonAppConfig.getInstance().getUid())
|
||||
.params("token", CommonAppConfig.getInstance().getToken())
|
||||
.params("p", p)
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取视频音乐分类列表
|
||||
*/
|
||||
public static void getMusicClassList(HttpCallback callback) {
|
||||
HttpClient.getInstance().get("Music.classify_list", VideoHttpConsts.GET_MUSIC_CLASS_LIST)
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取热门视频音乐列表
|
||||
*/
|
||||
public static void getHotMusicList(int p, HttpCallback callback) {
|
||||
HttpClient.getInstance().get("Music.hotLists", VideoHttpConsts.GET_HOT_MUSIC_LIST)
|
||||
.params("uid", CommonAppConfig.getInstance().getUid())
|
||||
.params("token", CommonAppConfig.getInstance().getToken())
|
||||
.params("p", p)
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 音乐收藏
|
||||
*/
|
||||
public static void setMusicCollect(int muiscId, HttpCallback callback) {
|
||||
HttpClient.getInstance().get("Music.collectMusic", VideoHttpConsts.SET_MUSIC_COLLECT)
|
||||
.params("uid", CommonAppConfig.getInstance().getUid())
|
||||
.params("token", CommonAppConfig.getInstance().getToken())
|
||||
.params("musicid", muiscId)
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 音乐收藏列表
|
||||
*/
|
||||
public static void getMusicCollectList(int p, HttpCallback callback) {
|
||||
HttpClient.getInstance().get("Music.getCollectMusicLists", VideoHttpConsts.GET_MUSIC_COLLECT_LIST)
|
||||
.params("uid", CommonAppConfig.getInstance().getUid())
|
||||
.params("token", CommonAppConfig.getInstance().getToken())
|
||||
.params("p", p)
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取具体分类下的音乐列表
|
||||
*/
|
||||
public static void getMusicList(String classId, int p, HttpCallback callback) {
|
||||
HttpClient.getInstance().get("Music.music_list", VideoHttpConsts.GET_MUSIC_LIST)
|
||||
.params("uid", CommonAppConfig.getInstance().getUid())
|
||||
.params("token", CommonAppConfig.getInstance().getToken())
|
||||
.params("classify", classId)
|
||||
.params("p", p)
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 搜索音乐
|
||||
*/
|
||||
public static void videoSearchMusic(String key, int p, HttpCallback callback) {
|
||||
HttpClient.getInstance().get("Music.searchMusic", VideoHttpConsts.VIDEO_SEARCH_MUSIC)
|
||||
.params("uid", CommonAppConfig.getInstance().getUid())
|
||||
.params("token", CommonAppConfig.getInstance().getToken())
|
||||
.params("key", key)
|
||||
.params("p", p)
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 上传视频,获取七牛云token的接口
|
||||
*/
|
||||
public static void getQiNiuToken(HttpCallback callback) {
|
||||
HttpClient.getInstance().get("Video.getQiniuToken", VideoHttpConsts.GET_QI_NIU_TOKEN)
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 短视频上传信息
|
||||
*
|
||||
* @param title 短视频标题
|
||||
* @param thumb 短视频封面图url
|
||||
* @param href 短视频视频url
|
||||
* @param musicId 背景音乐Id
|
||||
*/
|
||||
public static void saveUploadVideoInfo(String title, String thumb, String href, int musicId, boolean openLocation, HttpCallback callback) {
|
||||
HttpClient.getInstance().get("Video.setVideo", VideoHttpConsts.SAVE_UPLOAD_VIDEO_INFO)
|
||||
.params("uid", CommonAppConfig.getInstance().getUid())
|
||||
.params("token", CommonAppConfig.getInstance().getToken())
|
||||
.params("lat", openLocation ? String.valueOf(CommonAppConfig.getInstance().getLat()) : "")
|
||||
.params("lng", openLocation ? String.valueOf(CommonAppConfig.getInstance().getLng()) : "")
|
||||
.params("city", openLocation ? CommonAppConfig.getInstance().getCity() : "")
|
||||
.params("title", title)
|
||||
.params("thumb", thumb)
|
||||
.params("href", href)
|
||||
.params("music_id", musicId)
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取腾讯云储存上传签名
|
||||
*/
|
||||
public static void getTxUploadCredential(StringCallback callback) {
|
||||
OkGo.<String>get("http://upload.qq163.iego.cn:8088/cam")
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某人发布的视频
|
||||
*/
|
||||
public static void getHomeVideo(String toUid, int p, HttpCallback callback) {
|
||||
HttpClient.getInstance().get("Video.getHomeVideo", VideoHttpConsts.GET_HOME_VIDEO)
|
||||
.params("uid", CommonAppConfig.getInstance().getUid())
|
||||
.params("token", CommonAppConfig.getInstance().getToken())
|
||||
.params("touid", toUid)
|
||||
.params("p", p)
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取举报内容列表
|
||||
*/
|
||||
public static void getVideoReportList(HttpCallback callback) {
|
||||
HttpClient.getInstance().get("Video.getReportContentlist", VideoHttpConsts.GET_VIDEO_REPORT_LIST)
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 举报视频接口
|
||||
*/
|
||||
public static void videoReport(String videoId, String reportId, String content, HttpCallback callback) {
|
||||
HttpClient.getInstance().get("Video.report", VideoHttpConsts.VIDEO_REPORT)
|
||||
.params("uid", CommonAppConfig.getInstance().getUid())
|
||||
.params("token", CommonAppConfig.getInstance().getToken())
|
||||
.params("videoid", videoId)
|
||||
.params("type", reportId)
|
||||
.params("content", content)
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除自己的视频
|
||||
*/
|
||||
public static void videoDelete(String videoid, HttpCallback callback) {
|
||||
HttpClient.getInstance().get("Video.del", VideoHttpConsts.VIDEO_DELETE)
|
||||
.params("uid", CommonAppConfig.getInstance().getUid())
|
||||
.params("token", CommonAppConfig.getInstance().getToken())
|
||||
.params("videoid", videoid)
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分享视频
|
||||
*/
|
||||
public static void setVideoShare(String videoid, HttpCallback callback) {
|
||||
String uid = CommonAppConfig.getInstance().getUid();
|
||||
String s = MD5Util.getMD5(uid + "-" + videoid + "-" + VIDEO_SALT);
|
||||
HttpClient.getInstance().get("Video.addShare", VideoHttpConsts.SET_VIDEO_SHARE)
|
||||
.params("uid", uid)
|
||||
.params("token", CommonAppConfig.getInstance().getToken())
|
||||
.params("videoid", videoid)
|
||||
.params("random_str", s)
|
||||
.execute(callback);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 开始观看视频的时候请求这个接口
|
||||
*/
|
||||
public static void videoWatchStart(String videoUid, String videoId) {
|
||||
String uid = CommonAppConfig.getInstance().getUid();
|
||||
if (TextUtils.isEmpty(uid) || uid.equals(videoUid)) {
|
||||
return;
|
||||
}
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.VIDEO_WATCH_START);
|
||||
String s = MD5Util.getMD5(uid + "-" + videoId + "-" + VIDEO_SALT);
|
||||
HttpClient.getInstance().get("Video.addView", VideoHttpConsts.VIDEO_WATCH_START)
|
||||
.params("uid", uid)
|
||||
.params("token", CommonAppConfig.getInstance().getToken())
|
||||
.params("videoid", videoId)
|
||||
.params("random_str", s)
|
||||
.execute(CommonHttpUtil.NO_CALLBACK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 完整观看完视频后请求这个接口
|
||||
*/
|
||||
public static void videoWatchEnd(String videoUid, String videoId) {
|
||||
String uid = CommonAppConfig.getInstance().getUid();
|
||||
if (TextUtils.isEmpty(uid) || uid.equals(videoUid)) {
|
||||
return;
|
||||
}
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.VIDEO_WATCH_END);
|
||||
String s = MD5Util.getMD5(uid + "-" + videoId + "-" + VIDEO_SALT);
|
||||
HttpClient.getInstance().get("Video.setConversion", VideoHttpConsts.VIDEO_WATCH_END)
|
||||
.params("uid", uid)
|
||||
.params("token", CommonAppConfig.getInstance().getToken())
|
||||
.params("videoid", videoId)
|
||||
.params("random_str", s)
|
||||
.execute(CommonHttpUtil.NO_CALLBACK);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.yunbao.video.interfaces;
|
||||
|
||||
import com.yunbao.video.adapter.MusicAdapter;
|
||||
import com.yunbao.video.bean.MusicBean;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/7.
|
||||
*/
|
||||
|
||||
public interface VideoMusicActionListener {
|
||||
void onPlayMusic(MusicAdapter adapter, MusicBean bean, int position);
|
||||
|
||||
void onStopMusic();
|
||||
|
||||
void onUseClick(MusicBean bean);
|
||||
|
||||
void onCollect(MusicAdapter adapter, int musicId, int isCollect);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.yunbao.video.interfaces;
|
||||
|
||||
import com.yunbao.common.http.HttpCallback;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/15.
|
||||
*/
|
||||
|
||||
public interface VideoScrollDataHelper {
|
||||
void loadData(int p, HttpCallback callback);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.yunbao.video.upload;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/5/21.
|
||||
*/
|
||||
|
||||
public class VideoUploadBean {
|
||||
private File mVideoFile;
|
||||
private File mImageFile;
|
||||
private String mResultVideoUrl;//视频上传结果的url
|
||||
private String mResultImageUrl;//图片上传结果的url
|
||||
|
||||
|
||||
public VideoUploadBean(File videoFile, File imageFile) {
|
||||
mVideoFile = videoFile;
|
||||
mImageFile = imageFile;
|
||||
}
|
||||
|
||||
public File getVideoFile() {
|
||||
return mVideoFile;
|
||||
}
|
||||
|
||||
public void setVideoFile(File videoFile) {
|
||||
mVideoFile = videoFile;
|
||||
}
|
||||
|
||||
public File getImageFile() {
|
||||
return mImageFile;
|
||||
}
|
||||
|
||||
public void setImageFile(File imageFile) {
|
||||
mImageFile = imageFile;
|
||||
}
|
||||
|
||||
public String getResultVideoUrl() {
|
||||
return mResultVideoUrl;
|
||||
}
|
||||
|
||||
public void setResultVideoUrl(String resultVideoUrl) {
|
||||
mResultVideoUrl = resultVideoUrl;
|
||||
}
|
||||
|
||||
public String getResultImageUrl() {
|
||||
return mResultImageUrl;
|
||||
}
|
||||
|
||||
public void setResultImageUrl(String resultImageUrl) {
|
||||
mResultImageUrl = resultImageUrl;
|
||||
}
|
||||
|
||||
public void deleteFile() {
|
||||
if (mVideoFile != null && mVideoFile.exists()) {
|
||||
mVideoFile.delete();
|
||||
}
|
||||
if (mImageFile != null && mImageFile.exists()) {
|
||||
mImageFile.delete();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.yunbao.video.upload;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/5/21.
|
||||
*/
|
||||
|
||||
public interface VideoUploadCallback {
|
||||
void onSuccess(VideoUploadBean bean);
|
||||
|
||||
void onFailure();
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package com.yunbao.video.upload;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.lzy.okgo.OkGo;
|
||||
import com.lzy.okgo.convert.StringConvert;
|
||||
import com.lzy.okgo.model.Progress;
|
||||
import com.lzy.okgo.request.PostRequest;
|
||||
import com.lzy.okserver.OkUpload;
|
||||
import com.lzy.okserver.upload.UploadListener;
|
||||
import com.lzy.okserver.upload.UploadTask;
|
||||
import com.yunbao.common.http.Data;
|
||||
import com.yunbao.common.http.JsonBean;
|
||||
import com.yunbao.common.utils.L;
|
||||
import com.yunbao.common.utils.RouteUtil;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/21.
|
||||
* 上传视频,不使用云存储,使用自建存储,比如ftp服务器等
|
||||
*/
|
||||
|
||||
public class VideoUploadFtpImpl implements VideoUploadStrategy {
|
||||
|
||||
private static final String TAG = "VideoUploadFtpImpl";
|
||||
private UploadTask<String> mTask;
|
||||
|
||||
|
||||
@Override
|
||||
public void upload(final VideoUploadBean videoUploadBean, final VideoUploadCallback callback) {
|
||||
if (videoUploadBean == null || callback == null) {
|
||||
return;
|
||||
}
|
||||
PostRequest<String> postRequest = OkGo.<String>post("http://www.mytoday.net/api/public/?service=Video.uploadvideo")
|
||||
.params("uid", "13640")
|
||||
.params("token", "0e6371c5a642e8b48748a4d994303473")
|
||||
.params("file", videoUploadBean.getVideoFile())
|
||||
.params("file1", videoUploadBean.getImageFile())
|
||||
.converter(new StringConvert());
|
||||
mTask = OkUpload.request(TAG, postRequest)
|
||||
.save()
|
||||
.register(new UploadListener<String>(TAG) {
|
||||
@Override
|
||||
public void onStart(Progress progress) {
|
||||
L.e(TAG, "onStart------progress----->" + progress.fraction * 100);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgress(Progress progress) {
|
||||
L.e(TAG, "onProgress------progress----->" + progress.fraction * 100);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Progress progress) {
|
||||
L.e(TAG, "onProgress------progress----->" + progress.fraction * 100);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish(String s, Progress progress) {
|
||||
L.e(TAG, "onFinish------progress----->" + progress.fraction * 100);
|
||||
L.e(TAG, "onFinish------s----->" + s);
|
||||
if (!TextUtils.isEmpty(s)) {
|
||||
try {
|
||||
JsonBean bean = JSON.parseObject(s, JsonBean.class);
|
||||
if (bean != null) {
|
||||
if (200 == bean.getRet()) {
|
||||
Data data = bean.getData();
|
||||
if (data != null) {
|
||||
if (700 == data.getCode()) {
|
||||
//token过期,重新登录
|
||||
RouteUtil.forwardLoginInvalid(data.getMsg());
|
||||
if (callback != null) {
|
||||
callback.onFailure();
|
||||
}
|
||||
} else {
|
||||
String[] info = data.getInfo();
|
||||
if (data.getCode() == 0 && info.length > 0) {
|
||||
JSONObject obj = JSON.parseObject(info[0]);
|
||||
if (videoUploadBean != null) {
|
||||
videoUploadBean.setResultVideoUrl(obj.getString("video"));
|
||||
videoUploadBean.setResultImageUrl(obj.getString("img"));
|
||||
if (callback != null) {
|
||||
callback.onSuccess(videoUploadBean);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
L.e("服务器返回值异常--->ret: " + bean.getRet() + " msg: " + bean.getMsg());
|
||||
if (callback != null) {
|
||||
callback.onFailure();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
L.e("服务器返回值异常--->ret: " + bean.getRet() + " msg: " + bean.getMsg());
|
||||
if (callback != null) {
|
||||
callback.onFailure();
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
L.e("服务器返回值异常--->bean = null");
|
||||
if (callback != null) {
|
||||
callback.onFailure();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (callback != null) {
|
||||
callback.onFailure();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove(Progress progress) {
|
||||
L.e(TAG, "onRemove------progress----->" + progress);
|
||||
if (callback != null) {
|
||||
callback.onFailure();
|
||||
}
|
||||
}
|
||||
});
|
||||
mTask.start();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
if (mTask != null) {
|
||||
mTask.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.yunbao.video.upload;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.qiniu.android.http.ResponseInfo;
|
||||
import com.qiniu.android.storage.UpCompletionHandler;
|
||||
import com.qiniu.android.storage.UploadManager;
|
||||
import com.yunbao.common.bean.ConfigBean;
|
||||
import com.yunbao.common.http.HttpCallback;
|
||||
import com.yunbao.common.utils.L;
|
||||
import com.yunbao.video.http.VideoHttpConsts;
|
||||
import com.yunbao.video.http.VideoHttpUtil;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/5/21.
|
||||
* 视频上传 七牛云实现类
|
||||
*/
|
||||
|
||||
public class VideoUploadQnImpl implements VideoUploadStrategy {
|
||||
|
||||
private static final String TAG = "VideoUploadQnImpl";
|
||||
private VideoUploadBean mVideoUploadBean;
|
||||
private VideoUploadCallback mVideoUploadCallback;
|
||||
private String mToken;
|
||||
private UploadManager mUploadManager;
|
||||
private UpCompletionHandler mVideoUpCompletionHandler;//视频上传回调
|
||||
private UpCompletionHandler mImageUpCompletionHandler;//封面图片上传回调
|
||||
private String mQiNiuHost;
|
||||
|
||||
|
||||
public VideoUploadQnImpl(ConfigBean configBean) {
|
||||
mQiNiuHost = configBean.getVideoQiNiuHost();
|
||||
mVideoUpCompletionHandler = new UpCompletionHandler() {
|
||||
@Override
|
||||
public void complete(String key, ResponseInfo info, JSONObject response) {
|
||||
L.e(TAG, "视频上传结果-------->key: " + key);
|
||||
L.e(TAG, "视频上传结果-------->ResponseInfo: " + (info == null ? "" : info.toString()));
|
||||
L.e(TAG, "视频上传结果-------->response: " + (response == null ? "" : response.toString()));
|
||||
if (mVideoUploadBean == null) {
|
||||
return;
|
||||
}
|
||||
String videoResultUrl = mQiNiuHost + mVideoUploadBean.getVideoFile().getName();
|
||||
L.e(TAG, "视频上传结果-------->" + videoResultUrl);
|
||||
mVideoUploadBean.setResultVideoUrl(videoResultUrl);
|
||||
uploadFile(mVideoUploadBean.getImageFile(), mImageUpCompletionHandler);
|
||||
}
|
||||
};
|
||||
mImageUpCompletionHandler = new UpCompletionHandler() {
|
||||
@Override
|
||||
public void complete(String key, ResponseInfo info, JSONObject response) {
|
||||
if (mVideoUploadBean == null) {
|
||||
return;
|
||||
}
|
||||
String imageResultUrl = mQiNiuHost + mVideoUploadBean.getImageFile().getName();
|
||||
L.e(TAG, "图片上传结果-------->" + imageResultUrl);
|
||||
mVideoUploadBean.setResultImageUrl(imageResultUrl);
|
||||
if (mVideoUploadCallback != null) {
|
||||
mVideoUploadCallback.onSuccess(mVideoUploadBean);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void upload(VideoUploadBean bean, VideoUploadCallback callback) {
|
||||
if (bean == null || callback == null) {
|
||||
return;
|
||||
}
|
||||
mVideoUploadBean = bean;
|
||||
mVideoUploadCallback = callback;
|
||||
VideoHttpUtil.getQiNiuToken(new HttpCallback() {
|
||||
@Override
|
||||
public void onSuccess(int code, String msg, String[] info) {
|
||||
if (code == 0) {
|
||||
if (info.length > 0) {
|
||||
mToken = JSON.parseObject(info[0]).getString("token");
|
||||
L.e(TAG, "-------上传的token------>" + mToken);
|
||||
uploadFile(mVideoUploadBean.getVideoFile(), mVideoUpCompletionHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*/
|
||||
private void uploadFile(File file, UpCompletionHandler handler) {
|
||||
if (TextUtils.isEmpty(mToken)) {
|
||||
return;
|
||||
}
|
||||
if (mUploadManager == null) {
|
||||
mUploadManager = new UploadManager();
|
||||
}
|
||||
mUploadManager.put(file, file.getName(), mToken, handler, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.GET_QI_NIU_TOKEN);
|
||||
mVideoUploadCallback = null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.yunbao.video.upload;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/5/21.
|
||||
*/
|
||||
|
||||
public interface VideoUploadStrategy {
|
||||
void upload(VideoUploadBean bean, VideoUploadCallback callback);
|
||||
|
||||
void cancel();
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
package com.yunbao.video.upload;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.lzy.okgo.callback.StringCallback;
|
||||
import com.lzy.okgo.model.Response;
|
||||
import com.yunbao.common.CommonAppContext;
|
||||
import com.yunbao.common.bean.ConfigBean;
|
||||
import com.yunbao.common.utils.L;
|
||||
import com.yunbao.video.http.VideoHttpUtil;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/5/21.
|
||||
*/
|
||||
|
||||
public class VideoUploadTxImpl implements VideoUploadStrategy {
|
||||
|
||||
private static final String TAG = "VideoUploadTxImpl";
|
||||
|
||||
private VideoUploadBean mVideoUploadBean;
|
||||
private VideoUploadCallback mVideoUploadCallback;
|
||||
private OnSuccessCallback mVideoOnSuccessCallback;//视频上传成功回调
|
||||
private OnSuccessCallback mImageOnSuccessCallback;//封面图片上传成功回调
|
||||
// private CosXmlService mCosXmlService;
|
||||
private String mAppId;//appId
|
||||
private String mRegion;//区域
|
||||
private String mBucketName;//桶的名字
|
||||
private String mCosVideoPath;//腾讯云存储上面的 视频文件夹
|
||||
private String mCosImagePath;//腾讯云存储上面的 图片文件夹
|
||||
|
||||
public VideoUploadTxImpl(ConfigBean configBean) {
|
||||
mAppId = configBean.getTxCosAppId();
|
||||
mRegion = configBean.getTxCosRegion();
|
||||
mBucketName = configBean.getTxCosBucketName();
|
||||
mCosVideoPath = configBean.getTxCosVideoPath();
|
||||
mCosImagePath = configBean.getTxCosImagePath();
|
||||
if (mCosVideoPath == null) {
|
||||
mCosVideoPath = "";
|
||||
}
|
||||
if (!mCosVideoPath.endsWith("/")) {
|
||||
mCosVideoPath += "/";
|
||||
}
|
||||
if (mCosImagePath == null) {
|
||||
mCosImagePath = "";
|
||||
}
|
||||
if (!mCosImagePath.endsWith("/")) {
|
||||
mCosImagePath += "/";
|
||||
}
|
||||
mVideoOnSuccessCallback = new OnSuccessCallback() {
|
||||
@Override
|
||||
public void onUploadSuccess(String url) {
|
||||
if (mVideoUploadBean == null) {
|
||||
return;
|
||||
}
|
||||
L.e(TAG, "视频上传结果-------->" + url);
|
||||
mVideoUploadBean.setResultVideoUrl(url);
|
||||
//上传封面图片
|
||||
uploadFile(mCosImagePath, mVideoUploadBean.getImageFile(), mImageOnSuccessCallback);
|
||||
}
|
||||
};
|
||||
mImageOnSuccessCallback = new OnSuccessCallback() {
|
||||
@Override
|
||||
public void onUploadSuccess(String url) {
|
||||
if (mVideoUploadBean == null) {
|
||||
return;
|
||||
}
|
||||
L.e(TAG, "图片上传结果-------->" + url);
|
||||
mVideoUploadBean.setResultImageUrl(url);
|
||||
if (mVideoUploadCallback != null) {
|
||||
mVideoUploadCallback.onSuccess(mVideoUploadBean);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upload(final VideoUploadBean bean, final VideoUploadCallback callback) {
|
||||
if (bean == null || callback == null) {
|
||||
return;
|
||||
}
|
||||
mVideoUploadBean = bean;
|
||||
mVideoUploadCallback = callback;
|
||||
|
||||
VideoHttpUtil.getTxUploadCredential(new StringCallback() {
|
||||
@Override
|
||||
public void onSuccess(Response<String> response) {
|
||||
String result = response.body();
|
||||
if (!TextUtils.isEmpty(result)) {
|
||||
JSONObject obj = JSON.parseObject(result);
|
||||
if (obj.getIntValue("code") == 0) {
|
||||
JSONObject data = obj.getJSONObject("data");
|
||||
JSONObject credentials = data.getJSONObject("credentials");
|
||||
startUpload(credentials.getString("tmpSecretId"),
|
||||
credentials.getString("tmpSecretKey"),
|
||||
credentials.getString("sessionToken"),
|
||||
data.getLongValue("expiredTime"));
|
||||
} else {
|
||||
if (mVideoUploadCallback != null) {
|
||||
mVideoUploadCallback.onFailure();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Response<String> response) {
|
||||
super.onError(response);
|
||||
if (mVideoUploadCallback != null) {
|
||||
mVideoUploadCallback.onFailure();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void startUpload(String secretId, String secretKey, String token, long expiredTime) {
|
||||
try {
|
||||
// SessionQCloudCredentials credentials = new SessionQCloudCredentials(secretId, secretKey, token, expiredTime);
|
||||
// QCloudCredentialProvider qCloudCredentialProvider = new StaticCredentialProvider(credentials);
|
||||
// CosXmlServiceConfig serviceConfig = new CosXmlServiceConfig.Builder()
|
||||
// .setAppidAndRegion(mAppId, mRegion)
|
||||
// .builder();
|
||||
// mCosXmlService = new CosXmlService(CommonAppContext.sInstance, serviceConfig, qCloudCredentialProvider);
|
||||
} catch (Exception e) {
|
||||
if (mVideoUploadCallback != null) {
|
||||
mVideoUploadCallback.onFailure();
|
||||
}
|
||||
}
|
||||
//上传视频
|
||||
uploadFile(mCosVideoPath, mVideoUploadBean.getVideoFile(), mVideoOnSuccessCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*/
|
||||
private void uploadFile(String cosPath, File file, final OnSuccessCallback callback) {
|
||||
// if (mCosXmlService == null) {
|
||||
// return;
|
||||
// }
|
||||
// PutObjectRequest putObjectRequest = new PutObjectRequest(mBucketName, cosPath + file.getName(), file.getAbsolutePath());
|
||||
// putObjectRequest.setProgressListener(new CosXmlProgressListener() {
|
||||
// @Override
|
||||
// public void onProgress(long progress, long max) {
|
||||
// L.e(TAG, "---上传进度--->" + progress * 100 / max);
|
||||
// }
|
||||
// });
|
||||
// 使用异步回调上传
|
||||
// mCosXmlService.putObjectAsync(putObjectRequest, new CosXmlResultListener() {
|
||||
// @Override
|
||||
// public void onSuccess(CosXmlRequest cosXmlRequest, CosXmlResult cosXmlResult) {
|
||||
// if (cosXmlResult != null) {
|
||||
// String resultUrl = "http://" + cosXmlResult.accessUrl;
|
||||
// L.e(TAG, "---上传结果----> " + resultUrl);
|
||||
// if (callback != null) {
|
||||
// callback.onUploadSuccess(resultUrl);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFail(CosXmlRequest cosXmlRequest, CosXmlClientException clientException, CosXmlServiceException serviceException) {
|
||||
//
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
mVideoUploadCallback = null;
|
||||
// if (mCosXmlService != null) {
|
||||
// mCosXmlService.release();
|
||||
// }
|
||||
// mCosXmlService = null;
|
||||
}
|
||||
|
||||
public interface OnSuccessCallback {
|
||||
void onUploadSuccess(String url);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.yunbao.video.utils;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.binioter.guideview.Component;
|
||||
import com.yunbao.video.R;
|
||||
|
||||
|
||||
/**
|
||||
* Created by binIoter on 16/6/17.
|
||||
*/
|
||||
public class LottieComponent implements Component {
|
||||
|
||||
@Override public View getView(LayoutInflater inflater) {
|
||||
|
||||
LinearLayout ll = (LinearLayout) inflater.inflate(R.layout.layer_lottie, null);
|
||||
ll.setOnClickListener(new View.OnClickListener() {
|
||||
@Override public void onClick(View view) {
|
||||
// Toast.makeText(view.getContext(), "引导层被点击了", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
return ll;
|
||||
}
|
||||
|
||||
@Override public int getAnchor() {
|
||||
return Component.ANCHOR_TOP;
|
||||
}
|
||||
|
||||
@Override public int getFitPosition() {
|
||||
return Component.FIT_CENTER;
|
||||
}
|
||||
|
||||
@Override public int getXOffset() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override public int getYOffset() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package com.yunbao.video.utils;
|
||||
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.text.TextUtils;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/7/19.
|
||||
*/
|
||||
|
||||
public class MusicMediaPlayerUtil {
|
||||
|
||||
private MediaPlayer mPlayer;
|
||||
private boolean mStarted;
|
||||
private boolean mPaused;
|
||||
private boolean mDestroy;
|
||||
private String mCurPath;
|
||||
|
||||
private MediaPlayer.OnPreparedListener mOnPreparedListener = new MediaPlayer.OnPreparedListener() {
|
||||
@Override
|
||||
public void onPrepared(MediaPlayer mp) {
|
||||
if (mDestroy) {
|
||||
destroy();
|
||||
} else {
|
||||
mPlayer.start();
|
||||
mStarted = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private MediaPlayer.OnCompletionListener mOnCompletionListener = new MediaPlayer.OnCompletionListener() {
|
||||
@Override
|
||||
public void onCompletion(MediaPlayer mp) {
|
||||
mStarted = false;
|
||||
mCurPath = null;
|
||||
}
|
||||
};
|
||||
|
||||
private MediaPlayer.OnErrorListener mOnErrorListener = new MediaPlayer.OnErrorListener() {
|
||||
@Override
|
||||
public boolean onError(MediaPlayer mp, int what, int extra) {
|
||||
mStarted = false;
|
||||
mCurPath = null;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public MusicMediaPlayerUtil() {
|
||||
mPlayer = new MediaPlayer();
|
||||
mPlayer.setOnPreparedListener(mOnPreparedListener);
|
||||
mPlayer.setOnErrorListener(mOnErrorListener);
|
||||
mPlayer.setOnCompletionListener(mOnCompletionListener);
|
||||
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||
}
|
||||
|
||||
public void startPlay(String path) {
|
||||
if (TextUtils.isEmpty(path)) {
|
||||
return;
|
||||
}
|
||||
if (!mStarted) {
|
||||
mCurPath = path;
|
||||
try {
|
||||
mPlayer.reset();
|
||||
mPlayer.setDataSource(path);
|
||||
mPlayer.setLooping(true);
|
||||
mPlayer.setVolume(1f, 1f);
|
||||
mPlayer.prepare();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
if (!path.equals(mCurPath)) {
|
||||
mCurPath = path;
|
||||
mStarted = false;
|
||||
try {
|
||||
mPlayer.stop();
|
||||
mPlayer.reset();
|
||||
mPlayer.setDataSource(path);
|
||||
mPlayer.setLooping(true);
|
||||
mPlayer.setVolume(1f, 1f);
|
||||
mPlayer.prepare();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void pausePlay() {
|
||||
if (mStarted && !mDestroy) {
|
||||
if (mPlayer != null) {
|
||||
mPlayer.pause();
|
||||
}
|
||||
}
|
||||
mPaused = true;
|
||||
}
|
||||
|
||||
public void resumePlay() {
|
||||
if (mStarted && !mDestroy && mPaused) {
|
||||
if (mPlayer != null) {
|
||||
mPlayer.start();
|
||||
}
|
||||
}
|
||||
mPaused = false;
|
||||
}
|
||||
|
||||
public void stopPlay() {
|
||||
if (mStarted && !mDestroy) {
|
||||
if (mPlayer != null) {
|
||||
mPlayer.stop();
|
||||
}
|
||||
mCurPath = null;
|
||||
}
|
||||
mStarted = false;
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
if (mStarted) {
|
||||
mPlayer.stop();
|
||||
}
|
||||
if (mPlayer != null) {
|
||||
mPlayer.release();
|
||||
}
|
||||
mStarted = false;
|
||||
mCurPath = null;
|
||||
mDestroy = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.yunbao.video.utils;
|
||||
|
||||
import com.yunbao.video.R;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/10/11.
|
||||
*/
|
||||
|
||||
public class VideoIconUtil {
|
||||
private static List<Integer> sVideoLikeAnim;//视频点赞动画
|
||||
|
||||
static {
|
||||
sVideoLikeAnim = Arrays.asList(
|
||||
R.mipmap.icon_video_zan_02,
|
||||
R.mipmap.icon_video_zan_03,
|
||||
R.mipmap.icon_video_zan_04,
|
||||
R.mipmap.icon_video_zan_05,
|
||||
R.mipmap.icon_video_zan_06,
|
||||
R.mipmap.icon_video_zan_07,
|
||||
R.mipmap.icon_video_zan_08,
|
||||
R.mipmap.icon_video_zan_09,
|
||||
R.mipmap.icon_video_zan_10,
|
||||
R.mipmap.icon_video_zan_11,
|
||||
R.mipmap.icon_video_zan_12,
|
||||
R.mipmap.icon_video_zan_13,
|
||||
R.mipmap.icon_video_zan_14,
|
||||
R.mipmap.icon_video_zan_15
|
||||
);
|
||||
}
|
||||
|
||||
public static List<Integer> getVideoLikeAnim() {
|
||||
return sVideoLikeAnim;
|
||||
}
|
||||
|
||||
}
|
||||
144
video/src/main/java/com/yunbao/video/utils/VideoLocalUtil.java
Normal file
144
video/src/main/java/com/yunbao/video/utils/VideoLocalUtil.java
Normal file
@@ -0,0 +1,144 @@
|
||||
package com.yunbao.video.utils;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.provider.MediaStore;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.yunbao.common.CommonAppContext;
|
||||
import com.yunbao.common.interfaces.CommonCallback;
|
||||
import com.yunbao.common.utils.StringUtil;
|
||||
import com.yunbao.video.bean.VideoChooseBean;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/6/20.
|
||||
*/
|
||||
|
||||
public class VideoLocalUtil {
|
||||
|
||||
private ContentResolver mContentResolver;
|
||||
private Handler mHandler;
|
||||
private CommonCallback<List<VideoChooseBean>> mCallback;
|
||||
private boolean mStop;
|
||||
|
||||
public VideoLocalUtil() {
|
||||
mContentResolver = CommonAppContext.sInstance.getContentResolver();
|
||||
mHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (mCallback != null && msg != null) {
|
||||
mCallback.callback((List<VideoChooseBean>) msg.obj);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void getLocalVideoList(CommonCallback<List<VideoChooseBean>> callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
mCallback = callback;
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mHandler != null) {
|
||||
List<VideoChooseBean> videoList = getAllVideo();
|
||||
Message msg = Message.obtain();
|
||||
msg.obj = videoList;
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private List<VideoChooseBean> getAllVideo() {
|
||||
List<VideoChooseBean> videoList = new ArrayList<>();
|
||||
String[] mediaColumns = new String[]{
|
||||
MediaStore.Video.VideoColumns._ID,
|
||||
MediaStore.Video.VideoColumns.DATA,
|
||||
MediaStore.Video.VideoColumns.DISPLAY_NAME,
|
||||
MediaStore.Video.VideoColumns.DURATION
|
||||
};
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
cursor = mContentResolver.query(
|
||||
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
|
||||
mediaColumns, null, null, null);
|
||||
if (cursor != null) {
|
||||
while (!mStop && cursor.moveToNext()) {
|
||||
String videoPath = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA));
|
||||
File file = new File(videoPath);
|
||||
boolean canRead = file.canRead();
|
||||
long length = file.length();
|
||||
if (!canRead || length == 0) {
|
||||
continue;
|
||||
}
|
||||
long duration = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION));
|
||||
if (duration <= 0) {
|
||||
continue;
|
||||
}
|
||||
String videoName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME));
|
||||
if (TextUtils.isEmpty(videoName) || !videoName.endsWith(".mp4")) {
|
||||
continue;
|
||||
}
|
||||
VideoChooseBean bean = new VideoChooseBean();
|
||||
bean.setVideoPath(videoPath);
|
||||
bean.setDuration(duration);
|
||||
bean.setVideoName(videoName);
|
||||
bean.setDurationString(StringUtil.getDurationText(duration));
|
||||
videoList.add(bean);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
return videoList;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
mStop = true;
|
||||
mCallback = null;
|
||||
if (mHandler != null) {
|
||||
mHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
mHandler = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 把视频保存到ContentProvider,在选择上传的时候能找到
|
||||
*/
|
||||
public static void saveVideoInfo(Context context, String videoPath, long duration) {
|
||||
try {
|
||||
File videoFile = new File(videoPath);
|
||||
String fileName = videoFile.getName();
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(MediaStore.MediaColumns.TITLE, fileName);
|
||||
values.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);
|
||||
values.put(MediaStore.MediaColumns.DATE_MODIFIED, currentTimeMillis);
|
||||
values.put(MediaStore.MediaColumns.DATE_ADDED, currentTimeMillis);
|
||||
values.put(MediaStore.MediaColumns.DATA, videoPath);
|
||||
values.put(MediaStore.MediaColumns.SIZE, videoFile.length());
|
||||
values.put(MediaStore.Video.VideoColumns.DATE_TAKEN, currentTimeMillis);
|
||||
values.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4");
|
||||
values.put(MediaStore.Video.VideoColumns.DURATION, duration);
|
||||
context.getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
85
video/src/main/java/com/yunbao/video/utils/VideoStorge.java
Normal file
85
video/src/main/java/com/yunbao/video/utils/VideoStorge.java
Normal file
@@ -0,0 +1,85 @@
|
||||
package com.yunbao.video.utils;
|
||||
|
||||
import com.yunbao.video.bean.VideoBean;
|
||||
import com.yunbao.video.interfaces.VideoScrollDataHelper;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/6/9.
|
||||
*/
|
||||
|
||||
public class VideoStorge {
|
||||
|
||||
private static VideoStorge sInstance;
|
||||
private Map<String, List<VideoBean>> mMap;
|
||||
private Map<String, VideoScrollDataHelper> mHelperMap;
|
||||
|
||||
private VideoStorge() {
|
||||
mMap = new HashMap<>();
|
||||
mHelperMap = new HashMap<>();
|
||||
}
|
||||
|
||||
public static VideoStorge getInstance() {
|
||||
if (sInstance == null) {
|
||||
synchronized (VideoStorge.class) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new VideoStorge();
|
||||
}
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public void put(String key, List<VideoBean> list) {
|
||||
if (mMap != null) {
|
||||
mMap.put(key, list);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<VideoBean> get(String key) {
|
||||
if (mMap != null) {
|
||||
return mMap.get(key);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void remove(String key) {
|
||||
if (mMap != null) {
|
||||
mMap.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void clear() {
|
||||
if (mMap != null) {
|
||||
mMap.clear();
|
||||
}
|
||||
if (mHelperMap != null) {
|
||||
mHelperMap.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void putDataHelper(String key, VideoScrollDataHelper helper) {
|
||||
if (mHelperMap != null) {
|
||||
mHelperMap.put(key, helper);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public VideoScrollDataHelper getDataHelper(String key) {
|
||||
if (mHelperMap != null) {
|
||||
return mHelperMap.get(key);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void removeDataHelper(String key) {
|
||||
if (mHelperMap != null) {
|
||||
mHelperMap.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.yunbao.video.utils;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.style.AbsoluteSizeSpan;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.text.style.ImageSpan;
|
||||
|
||||
import com.yunbao.common.CommonAppContext;
|
||||
import com.yunbao.common.utils.DpUtil;
|
||||
import com.yunbao.common.utils.FaceUtil;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/10/11.
|
||||
*/
|
||||
|
||||
public class VideoTextRender {
|
||||
|
||||
private static ForegroundColorSpan sColorSpan1;
|
||||
private static AbsoluteSizeSpan sFontSizeSpan1;
|
||||
private static final int FACE_WIDTH;
|
||||
private static final int VIDEO_FACE_WIDTH;
|
||||
private static final String REGEX = "\\[([\u4e00-\u9fa5\\w])+\\]";
|
||||
private static final Pattern PATTERN;
|
||||
|
||||
static {
|
||||
sColorSpan1 = new ForegroundColorSpan(0xffc8c8c8);
|
||||
sFontSizeSpan1 = new AbsoluteSizeSpan(12, true);
|
||||
FACE_WIDTH = DpUtil.dp2px(20);
|
||||
VIDEO_FACE_WIDTH = DpUtil.dp2px(16);
|
||||
PATTERN = Pattern.compile(REGEX);
|
||||
}
|
||||
|
||||
/**
|
||||
* 聊天表情
|
||||
*/
|
||||
public static CharSequence getFaceImageSpan(String content, int imgRes) {
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder(content);
|
||||
Drawable faceDrawable = ContextCompat.getDrawable(CommonAppContext.sInstance, imgRes);
|
||||
faceDrawable.setBounds(0, 0, FACE_WIDTH, FACE_WIDTH);
|
||||
ImageSpan imageSpan = new ImageSpan(faceDrawable, ImageSpan.ALIGN_BOTTOM);
|
||||
builder.setSpan(imageSpan, 0, content.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 评论内容,解析里面的表情
|
||||
*/
|
||||
public static CharSequence renderVideoComment(String content, String addTime) {
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder(content);
|
||||
Matcher matcher = PATTERN.matcher(content);
|
||||
while (matcher.find()) {
|
||||
// 获取匹配到的具体字符
|
||||
String key = matcher.group();
|
||||
Integer imgRes = FaceUtil.getFaceImageRes(key);
|
||||
if (imgRes != null && imgRes != 0) {
|
||||
Drawable faceDrawable = ContextCompat.getDrawable(CommonAppContext.sInstance, imgRes);
|
||||
if (faceDrawable != null) {
|
||||
faceDrawable.setBounds(0, 0, VIDEO_FACE_WIDTH, VIDEO_FACE_WIDTH);
|
||||
ImageSpan imageSpan = new ImageSpan(faceDrawable, ImageSpan.ALIGN_BOTTOM);
|
||||
// 匹配字符串的开始位置
|
||||
int startIndex = matcher.start();
|
||||
builder.setSpan(imageSpan, startIndex, startIndex + key.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
int startIndex = builder.length();
|
||||
builder.append(addTime);
|
||||
int endIndex = startIndex + addTime.length();
|
||||
builder.setSpan(sColorSpan1, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
builder.setSpan(sFontSizeSpan1, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
return builder;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,365 @@
|
||||
package com.yunbao.video.views;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.widget.PopupWindow;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.yunbao.common.Constants;
|
||||
import com.yunbao.common.adapter.RefreshAdapter;
|
||||
import com.yunbao.common.custom.CommonRefreshView;
|
||||
import com.yunbao.common.custom.MyLinearLayout3;
|
||||
import com.yunbao.common.http.HttpCallback;
|
||||
import com.yunbao.common.interfaces.OnItemClickListener;
|
||||
import com.yunbao.common.interfaces.OnItemLongClickListener;
|
||||
import com.yunbao.common.utils.L;
|
||||
import com.yunbao.common.utils.WordUtil;
|
||||
import com.yunbao.common.views.AbsViewHolder;
|
||||
import com.yunbao.live.activity.LiveReportActivity;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.activity.AbsVideoCommentActivity;
|
||||
import com.yunbao.video.adapter.VideoCommentAdapter;
|
||||
import com.yunbao.video.bean.VideoCommentBean;
|
||||
import com.yunbao.video.event.VideoCommentEvent;
|
||||
import com.yunbao.video.http.VideoHttpConsts;
|
||||
import com.yunbao.video.http.VideoHttpUtil;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/3.
|
||||
* 视频评论相关
|
||||
*/
|
||||
|
||||
public class VideoCommentViewHolder extends AbsViewHolder implements View.OnClickListener, OnItemClickListener<VideoCommentBean>, OnItemLongClickListener<VideoCommentBean>, VideoCommentAdapter.ActionListener {
|
||||
|
||||
private View mRoot;
|
||||
private MyLinearLayout3 mBottom;
|
||||
private CommonRefreshView mRefreshView;
|
||||
private TextView mCommentNum;
|
||||
private VideoCommentAdapter mVideoCommentAdapter;
|
||||
private String mVideoId;
|
||||
private String mVideoUid;
|
||||
private String mCommentString;
|
||||
private ObjectAnimator mShowAnimator;
|
||||
private ObjectAnimator mHideAnimator;
|
||||
private boolean mAnimating;
|
||||
private boolean mNeedRefresh;//是否需要刷新
|
||||
|
||||
public VideoCommentViewHolder(Context context, ViewGroup parentView) {
|
||||
super(context, parentView);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.view_video_comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
mRoot = findViewById(R.id.root);
|
||||
mBottom = (MyLinearLayout3) findViewById(R.id.bottom);
|
||||
int height = mBottom.getHeight2();
|
||||
mBottom.setTranslationY(height);
|
||||
mShowAnimator = ObjectAnimator.ofFloat(mBottom, "translationY", 0);
|
||||
mHideAnimator = ObjectAnimator.ofFloat(mBottom, "translationY", height);
|
||||
mShowAnimator.setDuration(200);
|
||||
mHideAnimator.setDuration(200);
|
||||
TimeInterpolator interpolator = new AccelerateDecelerateInterpolator();
|
||||
mShowAnimator.setInterpolator(interpolator);
|
||||
mHideAnimator.setInterpolator(interpolator);
|
||||
AnimatorListenerAdapter animatorListener = new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mAnimating = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mAnimating = false;
|
||||
if (animation == mHideAnimator) {
|
||||
if (mRoot != null && mRoot.getVisibility() == View.VISIBLE) {
|
||||
mRoot.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
} else if (animation == mShowAnimator) {
|
||||
if (mNeedRefresh) {
|
||||
mNeedRefresh = false;
|
||||
if (mRefreshView != null) {
|
||||
mRefreshView.initData();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
mShowAnimator.addListener(animatorListener);
|
||||
mHideAnimator.addListener(animatorListener);
|
||||
|
||||
findViewById(R.id.root).setOnClickListener(this);
|
||||
findViewById(R.id.btn_close).setOnClickListener(this);
|
||||
findViewById(R.id.input).setOnClickListener(this);
|
||||
findViewById(R.id.btn_face).setOnClickListener(this);
|
||||
mCommentString = WordUtil.getString(R.string.video_comment);
|
||||
mCommentNum = (TextView) findViewById(R.id.comment_num);
|
||||
mRefreshView = (CommonRefreshView) findViewById(R.id.refreshView);
|
||||
mRefreshView.setEmptyLayoutId(R.layout.view_no_data_comment);
|
||||
mRefreshView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false) {
|
||||
@Override
|
||||
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||
try {
|
||||
super.onLayoutChildren(recycler, state);
|
||||
} catch (Exception e) {
|
||||
L.e("onLayoutChildren------>" + e.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mRefreshView.setDataHelper(new CommonRefreshView.DataHelper<VideoCommentBean>() {
|
||||
@Override
|
||||
public RefreshAdapter<VideoCommentBean> getAdapter() {
|
||||
if (mVideoCommentAdapter == null) {
|
||||
mVideoCommentAdapter = new VideoCommentAdapter(mContext);
|
||||
mVideoCommentAdapter.setOnItemClickListener(VideoCommentViewHolder.this);
|
||||
mVideoCommentAdapter.setOnItemLongClickListener(VideoCommentViewHolder.this);
|
||||
mVideoCommentAdapter.setActionListener(VideoCommentViewHolder.this);
|
||||
}
|
||||
return mVideoCommentAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadData(int p, HttpCallback callback) {
|
||||
if (!TextUtils.isEmpty(mVideoId)) {
|
||||
VideoHttpUtil.getVideoCommentList(mVideoId, p, callback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VideoCommentBean> processData(String[] info) {
|
||||
JSONObject obj = JSON.parseObject(info[0]);
|
||||
String commentNum = obj.getString("comments");
|
||||
EventBus.getDefault().post(new VideoCommentEvent(mVideoId, commentNum));
|
||||
if (mCommentNum != null) {
|
||||
mCommentNum.setText(mCommentString + " " + commentNum);
|
||||
}
|
||||
List<VideoCommentBean> list = JSON.parseArray(obj.getString("commentlist"), VideoCommentBean.class);
|
||||
for (VideoCommentBean bean : list) {
|
||||
if (bean != null) {
|
||||
bean.setParentNode(true);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefreshSuccess(List<VideoCommentBean> list, int listCount) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefreshFailure() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMoreSuccess(List<VideoCommentBean> loadItemList, int loadItemCount) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMoreFailure() {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setVideoInfo(String videoId, String videoUid) {
|
||||
if (!TextUtils.isEmpty(videoId) && !TextUtils.isEmpty(videoUid)) {
|
||||
if (!TextUtils.isEmpty(mVideoId) && !mVideoId.equals(videoId)) {
|
||||
if (mVideoCommentAdapter != null) {
|
||||
mVideoCommentAdapter.clearData();
|
||||
}
|
||||
}
|
||||
if (!videoId.equals(mVideoId)) {
|
||||
mNeedRefresh = true;
|
||||
}
|
||||
mVideoId = videoId;
|
||||
mVideoUid = videoUid;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void showBottom() {
|
||||
if (mAnimating) {
|
||||
return;
|
||||
}
|
||||
if (mRoot != null && mRoot.getVisibility() != View.VISIBLE) {
|
||||
mRoot.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (mShowAnimator != null) {
|
||||
mShowAnimator.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void hideBottom() {
|
||||
if (mAnimating) {
|
||||
return;
|
||||
}
|
||||
if (mHideAnimator != null) {
|
||||
mHideAnimator.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void needRefresh() {
|
||||
mNeedRefresh = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int i = v.getId();
|
||||
if (i == R.id.root || i == R.id.btn_close) {
|
||||
hideBottom();
|
||||
} else if (i == R.id.input) {
|
||||
if (!TextUtils.isEmpty(mVideoId) && !TextUtils.isEmpty(mVideoUid)) {
|
||||
((AbsVideoCommentActivity) mContext).openCommentInputWindow(false, mVideoId, mVideoUid, null);
|
||||
}
|
||||
} else if (i == R.id.btn_face) {
|
||||
if (!TextUtils.isEmpty(mVideoId) && !TextUtils.isEmpty(mVideoUid)) {
|
||||
((AbsVideoCommentActivity) mContext).openCommentInputWindow(true, mVideoId, mVideoUid, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void release() {
|
||||
if (mShowAnimator != null) {
|
||||
mShowAnimator.cancel();
|
||||
}
|
||||
mShowAnimator = null;
|
||||
if (mHideAnimator != null) {
|
||||
mHideAnimator.cancel();
|
||||
}
|
||||
mHideAnimator = null;
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.GET_VIDEO_COMMENT_LIST);
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.SET_COMMENT_LIKE);
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.GET_COMMENT_REPLY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(VideoCommentBean bean, int position) {
|
||||
if (position != -1) {
|
||||
if (!TextUtils.isEmpty(mVideoId) && !TextUtils.isEmpty(mVideoUid)) {
|
||||
((AbsVideoCommentActivity) mContext).openCommentInputWindow(false, mVideoId, mVideoUid, bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemLongClick(VideoCommentBean bean, int position, View view) {
|
||||
if (position == -1) {
|
||||
showMoreDialog(bean, view);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExpandClicked(final VideoCommentBean commentBean) {
|
||||
final VideoCommentBean parentNodeBean = commentBean.getParentNodeBean();
|
||||
if (parentNodeBean == null) {
|
||||
return;
|
||||
}
|
||||
VideoHttpUtil.getCommentReply(parentNodeBean.getId(), parentNodeBean.getChildPage(), new HttpCallback() {
|
||||
@Override
|
||||
public void onSuccess(int code, String msg, String[] info) {
|
||||
if (code == 0) {
|
||||
List<VideoCommentBean> list = JSON.parseArray(Arrays.toString(info), VideoCommentBean.class);
|
||||
if (list == null || list.size() == 0) {
|
||||
return;
|
||||
}
|
||||
if (parentNodeBean.getChildPage() == 1) {
|
||||
if (list.size() > 1) {
|
||||
list = list.subList(1, list.size());
|
||||
}
|
||||
}
|
||||
for (VideoCommentBean bean : list) {
|
||||
bean.setParentNodeBean(parentNodeBean);
|
||||
}
|
||||
List<VideoCommentBean> childList = parentNodeBean.getChildList();
|
||||
if (childList != null) {
|
||||
childList.addAll(list);
|
||||
if (childList.size() < parentNodeBean.getReplyNum()) {
|
||||
parentNodeBean.setChildPage(parentNodeBean.getChildPage() + 1);
|
||||
}
|
||||
if (mVideoCommentAdapter != null) {
|
||||
mVideoCommentAdapter.insertReplyList(commentBean, list.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCollapsedClicked(VideoCommentBean commentBean) {
|
||||
VideoCommentBean parentNodeBean = commentBean.getParentNodeBean();
|
||||
if (parentNodeBean == null) {
|
||||
return;
|
||||
}
|
||||
List<VideoCommentBean> childList = parentNodeBean.getChildList();
|
||||
VideoCommentBean node0 = childList.get(0);
|
||||
int orignSize = childList.size();
|
||||
parentNodeBean.removeChild();
|
||||
parentNodeBean.setChildPage(1);
|
||||
if (mVideoCommentAdapter != null) {
|
||||
mVideoCommentAdapter.removeReplyList(node0, orignSize - childList.size());
|
||||
}
|
||||
}
|
||||
|
||||
//view当前点击的控件,手指长按任意位置弹窗
|
||||
private void showMoreDialog(final VideoCommentBean bean, View view) {
|
||||
View pop_layout = LayoutInflater.from(mContext).inflate(R.layout.popwindow_video_report, null);
|
||||
final PopupWindow mPopupWindow = new PopupWindow(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
mPopupWindow.setContentView(pop_layout);
|
||||
mPopupWindow.setFocusable(true);
|
||||
mPopupWindow.setOutsideTouchable(true);
|
||||
mPopupWindow.setBackgroundDrawable(new BitmapDrawable());
|
||||
mPopupWindow.update();
|
||||
|
||||
int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
|
||||
int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
|
||||
pop_layout.measure(w, h);
|
||||
//获取PopWindow宽和高,Constants.xIndex手势X轴Constants.xIndey手势Y轴
|
||||
int mHeight = pop_layout.getMeasuredHeight();
|
||||
int mWidth = pop_layout.getMeasuredWidth();
|
||||
//偏移量
|
||||
int xoff = Constants.xIndex - mWidth / 2;
|
||||
int yoff = 0 - (pop_layout.getHeight() - Constants.yindex);
|
||||
mPopupWindow.showAsDropDown(pop_layout, xoff, yoff);
|
||||
|
||||
TextView report;
|
||||
report = (TextView) pop_layout.findViewById(R.id.report);
|
||||
|
||||
report.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
//举报
|
||||
LiveReportActivity.forward(mContext, bean.getId());
|
||||
mPopupWindow.dismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,325 @@
|
||||
package com.yunbao.video.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.tencent.ugc.TXVideoEditConstants;
|
||||
import com.yunbao.common.utils.DpUtil;
|
||||
import com.yunbao.common.utils.StringUtil;
|
||||
import com.yunbao.common.views.AbsViewHolder;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.activity.VideoEditActivity;
|
||||
import com.yunbao.video.custom.ColorfulProgress;
|
||||
import com.yunbao.video.custom.RangeSliderViewContainer;
|
||||
import com.yunbao.video.custom.VideoProgressController;
|
||||
import com.yunbao.video.custom.VideoProgressView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/8.
|
||||
* 视频编辑 裁剪 特效
|
||||
*/
|
||||
|
||||
public class VideoEditCutViewHolder extends AbsViewHolder implements View.OnClickListener {
|
||||
|
||||
private ActionListener mActionListener;
|
||||
private boolean mShowed;
|
||||
private VideoProgressView mVideoProgressView;
|
||||
private VideoProgressController mVideoProgressController;
|
||||
private ColorfulProgress mColorfulProgress;
|
||||
private long mVideoDuration;
|
||||
private TextView mStartTime;
|
||||
private TextView mEndTime;
|
||||
private TextView mTip;
|
||||
private View mSpecialGroup;
|
||||
private View mBtnSpecialCancel;
|
||||
private boolean mTouching;
|
||||
private long mCurTime;
|
||||
private boolean mSpecialStartMark;
|
||||
|
||||
public VideoEditCutViewHolder(Context context, ViewGroup parentView, long videoDuration) {
|
||||
super(context, parentView, videoDuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processArguments(Object... args) {
|
||||
mVideoDuration = (long) args[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.view_video_edit_cut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
findViewById(R.id.root).setOnClickListener(this);
|
||||
mTip = (TextView) findViewById(R.id.tip);
|
||||
mStartTime = (TextView) findViewById(R.id.start_time);
|
||||
mEndTime = (TextView) findViewById(R.id.end_time);
|
||||
mSpecialGroup = findViewById(R.id.group_special);
|
||||
mBtnSpecialCancel = findViewById(R.id.btn_special_cancel);
|
||||
mBtnSpecialCancel.setOnClickListener(this);
|
||||
//长按添加特效
|
||||
View.OnTouchListener onTouchListener = new View.OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent e) {
|
||||
int action = e.getAction();
|
||||
if (action == MotionEvent.ACTION_DOWN) {
|
||||
if (mTouching) {//防止多个个其他特效同时按下
|
||||
return false;
|
||||
}
|
||||
mTouching = true;
|
||||
specialDown(v);
|
||||
} else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
|
||||
mTouching = false;
|
||||
otherSpecialUp(v);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
findViewById(R.id.btn_special_1).setOnTouchListener(onTouchListener);
|
||||
findViewById(R.id.btn_special_2).setOnTouchListener(onTouchListener);
|
||||
findViewById(R.id.btn_special_3).setOnTouchListener(onTouchListener);
|
||||
findViewById(R.id.btn_special_4).setOnTouchListener(onTouchListener);
|
||||
|
||||
mVideoProgressView = (VideoProgressView) findViewById(R.id.progress_view);
|
||||
List<Bitmap> list = ((VideoEditActivity)mContext).getBitmapList();
|
||||
if (list != null) {
|
||||
mVideoProgressView.addBitmapList(list);
|
||||
}
|
||||
mVideoProgressController = new VideoProgressController(mContext, mVideoDuration);
|
||||
mVideoProgressController.setVideoProgressView(mVideoProgressView);
|
||||
mVideoProgressController.setVideoProgressSeekListener(new VideoProgressController.VideoProgressSeekListener() {
|
||||
@Override
|
||||
public void onVideoProgressSeek(long currentTimeMs) {
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onSeekChanged(currentTimeMs);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVideoProgressSeekFinish(long currentTimeMs) {
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onSeekChanged(currentTimeMs);
|
||||
}
|
||||
}
|
||||
});
|
||||
RangeSliderViewContainer sliderViewContainer = new RangeSliderViewContainer(mContext);
|
||||
sliderViewContainer.init(mVideoProgressController, 0, mVideoDuration, mVideoDuration);
|
||||
sliderViewContainer.setDurationChangeListener(new RangeSliderViewContainer.OnDurationChangeListener() {
|
||||
@Override
|
||||
public void onDurationChange(long startTime, long endTime) {
|
||||
if (mStartTime != null) {
|
||||
mStartTime.setText(StringUtil.getDurationText(startTime));
|
||||
}
|
||||
if (mEndTime != null) {
|
||||
mEndTime.setText(StringUtil.getDurationText(endTime));
|
||||
}
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onCutTimeChanged(startTime, endTime);
|
||||
}
|
||||
}
|
||||
});
|
||||
mVideoProgressController.addRangeSliderView(sliderViewContainer);
|
||||
mColorfulProgress = new ColorfulProgress(mContext);
|
||||
mColorfulProgress.setWidthHeight(mVideoProgressController.getThumbnailPicListDisplayWidth(), DpUtil.dp2px(50));
|
||||
mVideoProgressController.addColorfulProgress(mColorfulProgress);
|
||||
if (mEndTime != null) {
|
||||
mEndTime.setText(StringUtil.getDurationText(mVideoDuration));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int i = v.getId();
|
||||
if (i == R.id.root) {
|
||||
hide();
|
||||
|
||||
} else if (i == R.id.btn_special_cancel) {
|
||||
specialCancel();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void onVideoProgressChanged(long timeMs) {
|
||||
if (mShowed) {
|
||||
int currentTimeMs = (int) (timeMs / 1000);//转为ms值
|
||||
if (mVideoProgressController != null) {
|
||||
mVideoProgressController.setCurrentTimeMs(currentTimeMs);
|
||||
}
|
||||
mCurTime = currentTimeMs;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 特效的按钮被按下
|
||||
*/
|
||||
private void specialDown(View v) {
|
||||
if (mCurTime >= mVideoDuration) {
|
||||
mSpecialStartMark = false;
|
||||
return;
|
||||
}
|
||||
mSpecialStartMark = true;
|
||||
int color = 0;
|
||||
int effect = 0;
|
||||
int i = v.getId();
|
||||
if (i == R.id.btn_special_1) {
|
||||
color = 0xAA1FBCB6;
|
||||
effect = TXVideoEditConstants.TXEffectType_ROCK_LIGHT;
|
||||
|
||||
} else if (i == R.id.btn_special_2) {
|
||||
color = 0xAAEC8435;
|
||||
effect = TXVideoEditConstants.TXEffectType_SPLIT_SCREEN;
|
||||
|
||||
} else if (i == R.id.btn_special_3) {
|
||||
color = 0xAA449FF3;
|
||||
effect = TXVideoEditConstants.TXEffectType_DARK_DRAEM;
|
||||
|
||||
} else if (i == R.id.btn_special_4) {
|
||||
color = 0xAAEC5F9B;
|
||||
effect = TXVideoEditConstants.TXEffectType_SOUL_OUT;
|
||||
|
||||
}
|
||||
if (mColorfulProgress != null) {
|
||||
mColorfulProgress.startMark(color);
|
||||
}
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onSpecialStart(effect, mCurTime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 特效的按钮被抬起
|
||||
*/
|
||||
private void otherSpecialUp(View v) {
|
||||
if (!mSpecialStartMark) {
|
||||
return;
|
||||
}
|
||||
mSpecialStartMark = false;
|
||||
int effect = 0;
|
||||
int i = v.getId();
|
||||
if (i == R.id.btn_special_1) {
|
||||
effect = TXVideoEditConstants.TXEffectType_ROCK_LIGHT;
|
||||
|
||||
} else if (i == R.id.btn_special_2) {
|
||||
effect = TXVideoEditConstants.TXEffectType_SPLIT_SCREEN;
|
||||
|
||||
} else if (i == R.id.btn_special_3) {
|
||||
effect = TXVideoEditConstants.TXEffectType_DARK_DRAEM;
|
||||
|
||||
} else if (i == R.id.btn_special_4) {
|
||||
effect = TXVideoEditConstants.TXEffectType_SOUL_OUT;
|
||||
|
||||
}
|
||||
if (mColorfulProgress != null) {
|
||||
mColorfulProgress.endMark();
|
||||
}
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onSpecialEnd(effect, mCurTime);
|
||||
}
|
||||
showBtnSpecialCancel();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 撤销最后一次特效
|
||||
*/
|
||||
private void specialCancel() {
|
||||
if (mColorfulProgress != null) {
|
||||
ColorfulProgress.MarkInfo markInfo = mColorfulProgress.deleteLastMark();
|
||||
if (markInfo != null) {
|
||||
if(mVideoProgressController!=null){
|
||||
mVideoProgressController.setCurrentTimeMs(markInfo.startTimeMs);
|
||||
}
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onSpecialCancel(markInfo.startTimeMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
showBtnSpecialCancel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示或隐藏撤销其他特效的按钮
|
||||
*/
|
||||
private void showBtnSpecialCancel() {
|
||||
if (mBtnSpecialCancel != null && mColorfulProgress != null) {
|
||||
if (mColorfulProgress.getMarkListSize() > 0) {
|
||||
if (mBtnSpecialCancel.getVisibility() != View.VISIBLE) {
|
||||
mBtnSpecialCancel.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
if (mBtnSpecialCancel.getVisibility() == View.VISIBLE) {
|
||||
mBtnSpecialCancel.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void show(boolean showSpecial) {
|
||||
mShowed = true;
|
||||
if (mContentView != null && mContentView.getVisibility() != View.VISIBLE) {
|
||||
mContentView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (showSpecial) {
|
||||
if (mTip != null) {
|
||||
mTip.setText(R.string.video_edit_cut_tip_2);
|
||||
}
|
||||
if (mSpecialGroup != null && mSpecialGroup.getVisibility() != View.VISIBLE) {
|
||||
mSpecialGroup.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
if (mTip != null) {
|
||||
mTip.setText(R.string.video_edit_cut_tip);
|
||||
}
|
||||
if (mSpecialGroup != null && mSpecialGroup.getVisibility() == View.VISIBLE) {
|
||||
mSpecialGroup.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
mShowed = false;
|
||||
if (mContentView != null && mContentView.getVisibility() == View.VISIBLE) {
|
||||
mContentView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onHide();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface ActionListener {
|
||||
void onHide();
|
||||
|
||||
void onSeekChanged(long currentTimeMs);
|
||||
|
||||
void onCutTimeChanged(long startTime, long endTime);
|
||||
|
||||
void onSpecialStart(int effect, long currentTimeMs);
|
||||
|
||||
void onSpecialEnd(int effect, long currentTimeMs);
|
||||
|
||||
void onSpecialCancel(long currentTimeMs);
|
||||
}
|
||||
|
||||
public void setActionListener(ActionListener actionListener) {
|
||||
mActionListener = actionListener;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
mActionListener = null;
|
||||
}
|
||||
|
||||
public boolean isShowed() {
|
||||
return mShowed;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package com.yunbao.video.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.yunbao.beauty.bean.FilterBean;
|
||||
import com.yunbao.common.views.AbsViewHolder;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.beauty.adapter.FilterAdapter;
|
||||
import com.yunbao.common.interfaces.OnItemClickListener;
|
||||
import com.yunbao.common.utils.BitmapUtil;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/8.
|
||||
* 视频编辑 滤镜
|
||||
*/
|
||||
|
||||
public class VideoEditFilterViewHolder extends AbsViewHolder implements OnItemClickListener<FilterBean>, View.OnClickListener {
|
||||
|
||||
private ActionListener mActionListener;
|
||||
private boolean mShowed;
|
||||
private Bitmap mBitmap;
|
||||
|
||||
|
||||
public VideoEditFilterViewHolder(Context context, ViewGroup parentView) {
|
||||
super(context, parentView);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.view_video_edit_filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
findViewById(R.id.root).setOnClickListener(this);
|
||||
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
|
||||
recyclerView.setHasFixedSize(true);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false));
|
||||
FilterAdapter adapter = new FilterAdapter(mContext);
|
||||
adapter.setOnItemClickListener(this);
|
||||
recyclerView.setAdapter(adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(FilterBean bean, int position) {
|
||||
if (mBitmap != null) {
|
||||
mBitmap.recycle();
|
||||
}
|
||||
if (mActionListener != null) {
|
||||
int filterSrc = bean.getFilterSrc();
|
||||
if (filterSrc != 0) {
|
||||
Bitmap bitmap = BitmapUtil.getInstance().decodeBitmap(filterSrc);
|
||||
if (bitmap != null) {
|
||||
mBitmap = bitmap;
|
||||
mActionListener.onFilterChanged(bitmap);
|
||||
} else {
|
||||
mActionListener.onFilterChanged(null);
|
||||
}
|
||||
} else {
|
||||
mActionListener.onFilterChanged(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void show() {
|
||||
mShowed = true;
|
||||
if (mContentView != null && mContentView.getVisibility() != View.VISIBLE) {
|
||||
mContentView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
mShowed = false;
|
||||
if (mContentView != null && mContentView.getVisibility() == View.VISIBLE) {
|
||||
mContentView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onHide();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
hide();
|
||||
}
|
||||
|
||||
public interface ActionListener {
|
||||
void onHide();
|
||||
|
||||
void onFilterChanged(Bitmap bitmap);
|
||||
}
|
||||
|
||||
public void setActionListener(ActionListener actionListener) {
|
||||
mActionListener = actionListener;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
mActionListener = null;
|
||||
if (mBitmap != null) {
|
||||
mBitmap.recycle();
|
||||
}
|
||||
mBitmap = null;
|
||||
}
|
||||
|
||||
public boolean isShowed() {
|
||||
return mShowed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
package com.yunbao.video.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.yunbao.beauty.custom.TextSeekBar;
|
||||
import com.yunbao.common.utils.StringUtil;
|
||||
import com.yunbao.common.views.AbsViewHolder;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.bean.MusicBean;
|
||||
import com.yunbao.video.custom.RangeSlider;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/8.
|
||||
* 视频编辑 音量
|
||||
*/
|
||||
|
||||
public class VideoEditMusicViewHolder extends AbsViewHolder implements View.OnClickListener {
|
||||
|
||||
private View mCutGroup;
|
||||
private TextView mStartTime;//起始时间
|
||||
private TextView mEndTime;//结束时间
|
||||
private RangeSlider mRangeSlider;
|
||||
private TextSeekBar mOriginSeekBar;//原声
|
||||
private TextSeekBar mBgmSeekBar;//背景音
|
||||
private TextView mMusicName;//音乐名称
|
||||
private ActionListener mActionListener;
|
||||
private boolean mShowed;
|
||||
private long mMusicDuration;
|
||||
private boolean mHasOriginBgm;//是否在录制的时候有背景音乐
|
||||
private MusicBean mCurMusicBean;
|
||||
|
||||
public VideoEditMusicViewHolder(Context context, ViewGroup parentView, boolean hasOriginBgm, MusicBean curMusicBean) {
|
||||
super(context, parentView, hasOriginBgm,curMusicBean);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processArguments(Object... args) {
|
||||
if (args[0] != null) {
|
||||
mHasOriginBgm = (boolean) args[0];
|
||||
}
|
||||
if (args[1] != null) {
|
||||
mCurMusicBean = (MusicBean) args[1];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.view_video_edit_volume;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
mCutGroup = findViewById(R.id.cut_group);
|
||||
mStartTime = (TextView) findViewById(R.id.start_time);
|
||||
mMusicName = (TextView) findViewById(R.id.music_name);
|
||||
mEndTime = (TextView) findViewById(R.id.end_time);
|
||||
mRangeSlider = (RangeSlider) findViewById(R.id.range_slider);
|
||||
mRangeSlider.setRangeChangeListener(new RangeSlider.OnRangeChangeListener() {
|
||||
@Override
|
||||
public void onKeyDown(int type) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyUp(int type, int leftPinIndex, int rightPinIndex) {
|
||||
if (mMusicDuration > 0) {
|
||||
long startTime = mMusicDuration * leftPinIndex / 100;
|
||||
long endTime = mMusicDuration * rightPinIndex / 100;
|
||||
showCutTime(startTime, endTime);
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onBgmCutTimeChanged(startTime, endTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
findViewById(R.id.root).setOnClickListener(this);
|
||||
findViewById(R.id.btn_cancel).setOnClickListener(this);
|
||||
mOriginSeekBar = (TextSeekBar) findViewById(R.id.btn_origin);
|
||||
mBgmSeekBar = (TextSeekBar) findViewById(R.id.seek_bgm);
|
||||
TextSeekBar.OnSeekChangeListener seekChangeListener = new TextSeekBar.OnSeekChangeListener() {
|
||||
@Override
|
||||
public void onProgressChanged(View v, int progress) {
|
||||
if (mActionListener != null) {
|
||||
int i = v.getId();
|
||||
if (i == R.id.btn_origin) {
|
||||
mActionListener.onOriginalVolumeChanged(progress / 100f);
|
||||
} else if (i == R.id.seek_bgm) {
|
||||
mActionListener.onBgmVolumeChanged(progress / 100f);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
mOriginSeekBar.setOnSeekChangeListener(seekChangeListener);
|
||||
mBgmSeekBar.setOnSeekChangeListener(seekChangeListener);
|
||||
|
||||
if (mBgmSeekBar != null) {
|
||||
mBgmSeekBar.setProgress(0);
|
||||
mBgmSeekBar.setEnabled(false);
|
||||
}
|
||||
|
||||
if (mCurMusicBean != null) {
|
||||
setMusicBean(mCurMusicBean);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置背景音乐
|
||||
*/
|
||||
public void setMusicBean(MusicBean bean) {
|
||||
if (bean == null) {
|
||||
return;
|
||||
}
|
||||
if (mCutGroup != null && mCutGroup.getVisibility() != View.VISIBLE) {
|
||||
mCutGroup.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (mMusicName != null) {
|
||||
mMusicName.setText(bean.getTitle());
|
||||
}
|
||||
//如果在录制的时候有背景音,则要把原声禁用
|
||||
if (mHasOriginBgm) {
|
||||
if (mOriginSeekBar != null) {
|
||||
mOriginSeekBar.setEnabled(false);
|
||||
mOriginSeekBar.setProgress(0);
|
||||
}
|
||||
}
|
||||
if (mBgmSeekBar != null) {
|
||||
mBgmSeekBar.setProgress(80);
|
||||
mBgmSeekBar.setEnabled(true);
|
||||
}
|
||||
if (mRangeSlider != null) {
|
||||
mRangeSlider.resetRangePos();
|
||||
}
|
||||
mMusicDuration = bean.getDuration();
|
||||
showCutTime(0, mMusicDuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消背景音乐
|
||||
*/
|
||||
private void cancelMusic() {
|
||||
if (mCutGroup != null && mCutGroup.getVisibility() == View.VISIBLE) {
|
||||
mCutGroup.setVisibility(View.GONE);
|
||||
}
|
||||
if (mOriginSeekBar != null) {
|
||||
mOriginSeekBar.setProgress(80);
|
||||
mOriginSeekBar.setEnabled(true);
|
||||
}
|
||||
if (mBgmSeekBar != null) {
|
||||
mBgmSeekBar.setProgress(0);
|
||||
mBgmSeekBar.setEnabled(false);
|
||||
}
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onBgmCancelClick();
|
||||
}
|
||||
hide();
|
||||
}
|
||||
|
||||
|
||||
private void showCutTime(long startTime, long endTime) {
|
||||
if (mStartTime != null) {
|
||||
mStartTime.setText(StringUtil.getDurationText(startTime));
|
||||
}
|
||||
if (mEndTime != null) {
|
||||
mEndTime.setText(StringUtil.getDurationText(endTime));
|
||||
}
|
||||
}
|
||||
|
||||
public void show() {
|
||||
mShowed = true;
|
||||
if (mContentView != null && mContentView.getVisibility() != View.VISIBLE) {
|
||||
mContentView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
mShowed = false;
|
||||
if (mContentView != null && mContentView.getVisibility() == View.VISIBLE) {
|
||||
mContentView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onHide();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int i = v.getId();
|
||||
if (i == R.id.root) {
|
||||
hide();
|
||||
|
||||
} else if (i == R.id.btn_cancel) {
|
||||
cancelMusic();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public interface ActionListener {
|
||||
void onHide();
|
||||
|
||||
void onOriginalVolumeChanged(float value);
|
||||
|
||||
void onBgmVolumeChanged(float value);
|
||||
|
||||
void onBgmCancelClick();
|
||||
|
||||
void onBgmCutTimeChanged(long startTime, long endTime);
|
||||
}
|
||||
|
||||
public void setActionListener(ActionListener actionListener) {
|
||||
mActionListener = actionListener;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
mActionListener = null;
|
||||
}
|
||||
|
||||
public boolean isShowed() {
|
||||
return mShowed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.yunbao.video.views;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.yunbao.common.custom.CommonRefreshView;
|
||||
import com.yunbao.common.views.AbsViewHolder;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.adapter.MusicAdapter;
|
||||
import com.yunbao.video.interfaces.VideoMusicActionListener;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/8.
|
||||
*/
|
||||
|
||||
public abstract class VideoMusicChildViewHolder extends AbsViewHolder {
|
||||
|
||||
protected CommonRefreshView mRefreshView;
|
||||
protected MusicAdapter mAdapter;
|
||||
protected VideoMusicActionListener mActionListener;
|
||||
|
||||
|
||||
public VideoMusicChildViewHolder(Context context, ViewGroup parentView, VideoMusicActionListener actionListener) {
|
||||
super(context, parentView, actionListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processArguments(Object... args) {
|
||||
mActionListener = (VideoMusicActionListener) args[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
mRefreshView = (CommonRefreshView) findViewById(R.id.refreshView);
|
||||
mRefreshView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false));
|
||||
}
|
||||
|
||||
|
||||
public void loadData() {
|
||||
if (mRefreshView != null) {
|
||||
mRefreshView.initData();
|
||||
}
|
||||
}
|
||||
|
||||
public void show() {
|
||||
if (mContentView != null && mContentView.getVisibility() != View.VISIBLE) {
|
||||
mContentView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
if (mContentView != null && mContentView.getVisibility() == View.VISIBLE) {
|
||||
mContentView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void release() {
|
||||
mActionListener = null;
|
||||
if (mAdapter != null) {
|
||||
mAdapter.setActionListener(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void collectChanged(MusicAdapter adapter, int musicId, int collect) {
|
||||
if (mAdapter != null) {
|
||||
mAdapter.collectChanged(adapter, musicId, collect);
|
||||
}
|
||||
}
|
||||
|
||||
public void collapse() {
|
||||
if (mAdapter != null) {
|
||||
mAdapter.collapse();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.yunbao.video.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.yunbao.common.adapter.RefreshAdapter;
|
||||
import com.yunbao.common.custom.CommonRefreshView;
|
||||
import com.yunbao.common.http.HttpCallback;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.adapter.MusicAdapter;
|
||||
import com.yunbao.video.bean.MusicBean;
|
||||
import com.yunbao.video.http.VideoHttpUtil;
|
||||
import com.yunbao.video.interfaces.VideoMusicActionListener;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/7.
|
||||
* 视频收藏音乐
|
||||
*/
|
||||
|
||||
public class VideoMusicCollectViewHolder extends VideoMusicChildViewHolder {
|
||||
|
||||
public VideoMusicCollectViewHolder(Context context, ViewGroup parentView, VideoMusicActionListener actionListener) {
|
||||
super(context, parentView, actionListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.view_video_music_collect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
super.init();
|
||||
mRefreshView.setEmptyLayoutId(R.layout.view_no_data_music_collect);
|
||||
|
||||
mRefreshView.setDataHelper(new CommonRefreshView.DataHelper<MusicBean>() {
|
||||
@Override
|
||||
public RefreshAdapter<MusicBean> getAdapter() {
|
||||
if (mAdapter == null) {
|
||||
mAdapter = new MusicAdapter(mContext);
|
||||
mAdapter.setActionListener(mActionListener);
|
||||
}
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadData(int p, HttpCallback callback) {
|
||||
VideoHttpUtil.getMusicCollectList(p, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MusicBean> processData(String[] info) {
|
||||
return JSON.parseArray(Arrays.toString(info), MusicBean.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefreshSuccess(List<MusicBean> list, int listCount) {
|
||||
if(mActionListener!=null){
|
||||
mActionListener.onStopMusic();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefreshFailure() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMoreSuccess(List<MusicBean> loadItemList, int loadItemCount) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMoreFailure() {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.yunbao.video.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.yunbao.common.adapter.RefreshAdapter;
|
||||
import com.yunbao.common.custom.CommonRefreshView;
|
||||
import com.yunbao.common.http.HttpCallback;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.adapter.MusicAdapter;
|
||||
import com.yunbao.video.bean.MusicBean;
|
||||
import com.yunbao.video.http.VideoHttpUtil;
|
||||
import com.yunbao.video.interfaces.VideoMusicActionListener;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/7.
|
||||
* 视频热门音乐
|
||||
*/
|
||||
|
||||
public class VideoMusicHotViewHolder extends VideoMusicChildViewHolder {
|
||||
|
||||
public VideoMusicHotViewHolder(Context context, ViewGroup parentView, VideoMusicActionListener actionListener) {
|
||||
super(context, parentView, actionListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.view_video_music_hot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
super.init();
|
||||
mRefreshView.setEmptyLayoutId(R.layout.view_no_data_music);
|
||||
|
||||
mRefreshView.setDataHelper(new CommonRefreshView.DataHelper<MusicBean>() {
|
||||
@Override
|
||||
public RefreshAdapter<MusicBean> getAdapter() {
|
||||
if (mAdapter == null) {
|
||||
mAdapter = new MusicAdapter(mContext);
|
||||
mAdapter.setActionListener(mActionListener);
|
||||
}
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadData(int p, HttpCallback callback) {
|
||||
VideoHttpUtil.getHotMusicList(p, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MusicBean> processData(String[] info) {
|
||||
return JSON.parseArray(Arrays.toString(info), MusicBean.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefreshSuccess(List<MusicBean> list, int listCount) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefreshFailure() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMoreSuccess(List<MusicBean> loadItemList, int loadItemCount) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMoreFailure() {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.yunbao.video.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.yunbao.common.adapter.RefreshAdapter;
|
||||
import com.yunbao.common.custom.CommonRefreshView;
|
||||
import com.yunbao.common.http.HttpCallback;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.adapter.MusicAdapter;
|
||||
import com.yunbao.video.bean.MusicBean;
|
||||
import com.yunbao.video.http.VideoHttpUtil;
|
||||
import com.yunbao.video.interfaces.VideoMusicActionListener;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/7.
|
||||
* 视频搜索音乐
|
||||
*/
|
||||
|
||||
public class VideoMusicSearchViewHolder extends VideoMusicChildViewHolder {
|
||||
|
||||
private String mKey;
|
||||
|
||||
public VideoMusicSearchViewHolder(Context context, ViewGroup parentView, VideoMusicActionListener actionListener) {
|
||||
super(context, parentView, actionListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.view_video_music_search;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
super.init();
|
||||
mRefreshView.setEmptyLayoutId(R.layout.view_no_data_search);
|
||||
mRefreshView.setDataHelper(new CommonRefreshView.DataHelper<MusicBean>() {
|
||||
@Override
|
||||
public RefreshAdapter<MusicBean> getAdapter() {
|
||||
if (mAdapter == null) {
|
||||
mAdapter = new MusicAdapter(mContext);
|
||||
mAdapter.setActionListener(mActionListener);
|
||||
}
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadData(int p, HttpCallback callback) {
|
||||
if (!TextUtils.isEmpty(mKey)) {
|
||||
VideoHttpUtil.videoSearchMusic(mKey, p, callback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MusicBean> processData(String[] info) {
|
||||
return JSON.parseArray(Arrays.toString(info), MusicBean.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefreshSuccess(List<MusicBean> list, int listCount) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefreshFailure() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMoreSuccess(List<MusicBean> loadItemList, int loadItemCount) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMoreFailure() {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void setKey(String key) {
|
||||
mKey = key;
|
||||
}
|
||||
|
||||
public void clearData() {
|
||||
mKey=null;
|
||||
if(mAdapter!=null){
|
||||
mAdapter.clearData();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,472 @@
|
||||
package com.yunbao.video.views;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.yunbao.common.CommonAppConfig;
|
||||
import com.yunbao.common.Constants;
|
||||
import com.yunbao.common.http.HttpCallback;
|
||||
import com.yunbao.common.interfaces.OnItemClickListener;
|
||||
import com.yunbao.common.utils.DialogUitl;
|
||||
import com.yunbao.common.utils.DownloadUtil;
|
||||
import com.yunbao.common.utils.ScreenDimenUtil;
|
||||
import com.yunbao.common.utils.ToastUtil;
|
||||
import com.yunbao.common.views.AbsViewHolder;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.adapter.MusicAdapter;
|
||||
import com.yunbao.video.adapter.MusicClassAdapter;
|
||||
import com.yunbao.video.bean.MusicBean;
|
||||
import com.yunbao.video.bean.MusicClassBean;
|
||||
import com.yunbao.video.dialog.VideoMusicClassDialog;
|
||||
import com.yunbao.video.http.VideoHttpConsts;
|
||||
import com.yunbao.video.http.VideoHttpUtil;
|
||||
import com.yunbao.video.interfaces.VideoMusicActionListener;
|
||||
import com.yunbao.video.utils.MusicMediaPlayerUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/7.
|
||||
* 视频音乐逻辑
|
||||
*/
|
||||
|
||||
public class VideoMusicViewHolder extends AbsViewHolder implements View.OnClickListener, OnItemClickListener<MusicClassBean>, VideoMusicActionListener {
|
||||
|
||||
private View mRoot;
|
||||
private RecyclerView mMusicClassRecyclerView;//音乐分类recyclerView
|
||||
private ObjectAnimator mShowAnimator;
|
||||
private ObjectAnimator mHideAnimator;
|
||||
private boolean mAnimating;
|
||||
private boolean mShowed;
|
||||
private ViewGroup mContainer1;
|
||||
private VideoMusicHotViewHolder mHotViewHolder;
|
||||
private VideoMusicCollectViewHolder mCollectViewHolder;
|
||||
private List<VideoMusicChildViewHolder> mVideoMusicChildViewHolderList;
|
||||
private boolean mLoadData;
|
||||
private MusicMediaPlayerUtil mMusicMediaPlayerUtil;
|
||||
private DownloadUtil mDownloadUtil;
|
||||
private VideoMusicSearchViewHolder mSearchViewHolder;
|
||||
private EditText mInput;
|
||||
private MyHandler mHandler;
|
||||
private ActionListener mActionListener;
|
||||
|
||||
public VideoMusicViewHolder(Context context, ViewGroup parentView) {
|
||||
super(context, parentView);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.view_video_music;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
mRoot = findViewById(R.id.root);
|
||||
View group = findViewById(R.id.group);
|
||||
int screenHeight = ScreenDimenUtil.getInstance().getScreenHeight();
|
||||
group.setTranslationY(screenHeight);
|
||||
TimeInterpolator interpolator = new AccelerateDecelerateInterpolator();
|
||||
mShowAnimator = ObjectAnimator.ofFloat(group, "translationY", 0);
|
||||
mShowAnimator.setInterpolator(interpolator);
|
||||
mShowAnimator.setDuration(300);
|
||||
mHideAnimator = ObjectAnimator.ofFloat(group, "translationY", screenHeight);
|
||||
mHideAnimator.setInterpolator(interpolator);
|
||||
mHideAnimator.setDuration(300);
|
||||
mShowAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mAnimating = true;
|
||||
if (mRoot != null && mRoot.getVisibility() != View.VISIBLE) {
|
||||
mRoot.setVisibility(View.VISIBLE);
|
||||
}
|
||||
mShowed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mAnimating = false;
|
||||
loadData();
|
||||
}
|
||||
});
|
||||
mHideAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mAnimating = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mAnimating = false;
|
||||
mShowed = false;
|
||||
if (mRoot != null && mRoot.getVisibility() == View.VISIBLE) {
|
||||
mRoot.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onHide();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
mMusicClassRecyclerView = (RecyclerView) findViewById(R.id.music_class_recyclerView);
|
||||
mMusicClassRecyclerView.setHasFixedSize(true);
|
||||
mMusicClassRecyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false));
|
||||
mContainer1 = (ViewGroup) findViewById(R.id.container_1);
|
||||
findViewById(R.id.btn_close).setOnClickListener(this);
|
||||
findViewById(R.id.btn_hot).setOnClickListener(this);
|
||||
findViewById(R.id.btn_favorite).setOnClickListener(this);
|
||||
mHotViewHolder = new VideoMusicHotViewHolder(mContext, mContainer1, this);
|
||||
mHotViewHolder.addToParent();
|
||||
|
||||
mVideoMusicChildViewHolderList = new ArrayList<>();
|
||||
mVideoMusicChildViewHolderList.add(mHotViewHolder);
|
||||
mHandler = new MyHandler(this);
|
||||
mInput = (EditText) findViewById(R.id.input);
|
||||
mInput.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
|
||||
searchMusic();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
mInput.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.VIDEO_SEARCH_MUSIC);
|
||||
if (mHandler != null) {
|
||||
mHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
if (!TextUtils.isEmpty(s)) {
|
||||
if (mHandler != null) {
|
||||
mHandler.sendEmptyMessageDelayed(0, 500);
|
||||
}
|
||||
} else {
|
||||
if (mSearchViewHolder != null) {
|
||||
mSearchViewHolder.clearData();
|
||||
mSearchViewHolder.hide();
|
||||
onStopMusic();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void loadData() {
|
||||
if (mLoadData) {
|
||||
return;
|
||||
}
|
||||
mLoadData = true;
|
||||
VideoHttpUtil.getMusicClassList(new HttpCallback() {
|
||||
@Override
|
||||
public void onSuccess(int code, String msg, String[] info) {
|
||||
if (code == 0 && info.length > 0 && mMusicClassRecyclerView != null) {
|
||||
List<MusicClassBean> list = JSON.parseArray(Arrays.toString(info), MusicClassBean.class);
|
||||
MusicClassAdapter adapter = new MusicClassAdapter(mContext, list);
|
||||
adapter.setOnItemClickListener(VideoMusicViewHolder.this);
|
||||
mMusicClassRecyclerView.setAdapter(adapter);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (mHotViewHolder != null) {
|
||||
mHotViewHolder.loadData();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索音乐
|
||||
*/
|
||||
private void searchMusic() {
|
||||
if (mInput == null) {
|
||||
return;
|
||||
}
|
||||
String key = mInput.getText().toString().trim();
|
||||
if (TextUtils.isEmpty(key)) {
|
||||
ToastUtil.show(R.string.content_empty);
|
||||
return;
|
||||
}
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.VIDEO_SEARCH_MUSIC);
|
||||
if (mHandler != null) {
|
||||
mHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
if (mSearchViewHolder == null) {
|
||||
mSearchViewHolder = new VideoMusicSearchViewHolder(mContext, (ViewGroup) findViewById(R.id.container_2), this);
|
||||
mSearchViewHolder.addToParent();
|
||||
if (mVideoMusicChildViewHolderList != null) {
|
||||
mVideoMusicChildViewHolderList.add(mSearchViewHolder);
|
||||
}
|
||||
}
|
||||
doStopMusic();
|
||||
mSearchViewHolder.show();
|
||||
mSearchViewHolder.setKey(key);
|
||||
mSearchViewHolder.loadData();
|
||||
}
|
||||
|
||||
public void show() {
|
||||
if (!mShowed && mShowAnimator != null) {
|
||||
mShowAnimator.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
doStopMusic();
|
||||
if (mShowed && mHideAnimator != null) {
|
||||
mHideAnimator.start();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isShowed() {
|
||||
return mShowed;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
mActionListener = null;
|
||||
if (mMusicMediaPlayerUtil != null) {
|
||||
mMusicMediaPlayerUtil.destroy();
|
||||
}
|
||||
mMusicMediaPlayerUtil = null;
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.GET_MUSIC_CLASS_LIST);
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.GET_HOT_MUSIC_LIST);
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.GET_MUSIC_COLLECT_LIST);
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.SET_MUSIC_COLLECT);
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.VIDEO_SEARCH_MUSIC);
|
||||
if (mHandler != null) {
|
||||
mHandler.release();
|
||||
}
|
||||
mHandler = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mAnimating) {
|
||||
return;
|
||||
}
|
||||
int i = v.getId();
|
||||
if (i == R.id.btn_close) {
|
||||
hide();
|
||||
|
||||
} else if (i == R.id.btn_hot) {
|
||||
hideCollect();
|
||||
|
||||
} else if (i == R.id.btn_favorite) {
|
||||
showCollect();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void showCollect() {
|
||||
doStopMusic();
|
||||
if (mCollectViewHolder == null) {
|
||||
mCollectViewHolder = new VideoMusicCollectViewHolder(mContext, mContainer1, this);
|
||||
mCollectViewHolder.addToParent();
|
||||
if (mVideoMusicChildViewHolderList != null) {
|
||||
mVideoMusicChildViewHolderList.add(mCollectViewHolder);
|
||||
}
|
||||
}
|
||||
mCollectViewHolder.show();
|
||||
mCollectViewHolder.loadData();
|
||||
}
|
||||
|
||||
private void hideCollect() {
|
||||
doStopMusic();
|
||||
if (mCollectViewHolder != null) {
|
||||
mCollectViewHolder.hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 点击音乐分类回调
|
||||
*/
|
||||
@Override
|
||||
public void onItemClick(MusicClassBean bean, int position) {
|
||||
if (!canClick()) {
|
||||
return;
|
||||
}
|
||||
doStopMusic();
|
||||
VideoMusicClassDialog dialog = new VideoMusicClassDialog(mContext, mParentView, bean.getTitle(), bean.getId(), this);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* 播放音乐回调
|
||||
*/
|
||||
@Override
|
||||
public void onPlayMusic(final MusicAdapter adapter, final MusicBean bean, final int position) {
|
||||
String fileName = Constants.VIDEO_MUSIC_NAME_PREFIX + bean.getId();
|
||||
String path = CommonAppConfig.MUSIC_PATH + fileName;
|
||||
File file = new File(path);
|
||||
if (file.exists()) {
|
||||
bean.setLocalPath(path);
|
||||
adapter.expand(position);
|
||||
startPlayMusic(path);
|
||||
} else {
|
||||
final Dialog dialog = DialogUitl.loadingDialog(mContext);
|
||||
dialog.show();
|
||||
if (mDownloadUtil == null) {
|
||||
mDownloadUtil = new DownloadUtil();
|
||||
}
|
||||
mDownloadUtil.download(fileName, CommonAppConfig.MUSIC_PATH, fileName, bean.getFileUrl(), new DownloadUtil.Callback() {
|
||||
@Override
|
||||
public void onSuccess(File file) {
|
||||
dialog.dismiss();
|
||||
String musicPath = file.getAbsolutePath();
|
||||
bean.setLocalPath(musicPath);
|
||||
adapter.expand(position);
|
||||
startPlayMusic(musicPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgress(int progress) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void startPlayMusic(String path) {
|
||||
if (mMusicMediaPlayerUtil == null) {
|
||||
mMusicMediaPlayerUtil = new MusicMediaPlayerUtil();
|
||||
}
|
||||
mMusicMediaPlayerUtil.startPlay(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止播放音乐回调
|
||||
*/
|
||||
@Override
|
||||
public void onStopMusic() {
|
||||
if (mMusicMediaPlayerUtil != null) {
|
||||
mMusicMediaPlayerUtil.stopPlay();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用音乐回调
|
||||
*/
|
||||
@Override
|
||||
public void onUseClick(MusicBean bean) {
|
||||
if (mShowed && mHideAnimator != null) {
|
||||
mHideAnimator.start();
|
||||
}
|
||||
if (mActionListener != null && bean != null) {
|
||||
mActionListener.onChooseMusic(bean);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 收藏音乐回调
|
||||
*/
|
||||
@Override
|
||||
public void onCollect(MusicAdapter adapter, int musicId, int collect) {
|
||||
if (mVideoMusicChildViewHolderList != null) {
|
||||
for (VideoMusicChildViewHolder vmcvh : mVideoMusicChildViewHolderList) {
|
||||
if (vmcvh != null) {
|
||||
vmcvh.collectChanged(adapter, musicId, collect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doStopMusic() {
|
||||
if (mVideoMusicChildViewHolderList != null) {
|
||||
for (VideoMusicChildViewHolder vmcvh : mVideoMusicChildViewHolderList) {
|
||||
if (vmcvh != null) {
|
||||
vmcvh.collapse();
|
||||
}
|
||||
}
|
||||
}
|
||||
onStopMusic();
|
||||
}
|
||||
|
||||
private static class MyHandler extends Handler {
|
||||
|
||||
private VideoMusicViewHolder mViewHolder;
|
||||
|
||||
public MyHandler(VideoMusicViewHolder viewHolder) {
|
||||
mViewHolder = new WeakReference<>(viewHolder).get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (mViewHolder != null) {
|
||||
mViewHolder.searchMusic();
|
||||
}
|
||||
}
|
||||
|
||||
public void release() {
|
||||
removeCallbacksAndMessages(null);
|
||||
mViewHolder = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (mMusicMediaPlayerUtil != null) {
|
||||
mMusicMediaPlayerUtil.resumePlay();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
if (mMusicMediaPlayerUtil != null) {
|
||||
mMusicMediaPlayerUtil.pausePlay();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static abstract class ActionListener {
|
||||
public abstract void onChooseMusic(MusicBean bean);
|
||||
|
||||
public void onHide() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void setActionListener(ActionListener actionListener) {
|
||||
mActionListener = actionListener;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
package com.yunbao.video.views;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AccelerateInterpolator;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import com.tencent.rtmp.ITXVodPlayListener;
|
||||
import com.tencent.rtmp.TXLiveConstants;
|
||||
import com.tencent.rtmp.TXVodPlayConfig;
|
||||
import com.tencent.rtmp.TXVodPlayer;
|
||||
import com.tencent.rtmp.ui.TXCloudVideoView;
|
||||
import com.yunbao.common.utils.L;
|
||||
import com.yunbao.common.views.AbsViewHolder;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.bean.VideoBean;
|
||||
import com.yunbao.video.http.VideoHttpConsts;
|
||||
import com.yunbao.video.http.VideoHttpUtil;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/11/30.
|
||||
* 视频播放器
|
||||
*/
|
||||
|
||||
public class VideoPlayViewHolder extends AbsViewHolder implements ITXVodPlayListener, View.OnClickListener {
|
||||
|
||||
private TXCloudVideoView mTXCloudVideoView;
|
||||
private View mVideoCover;
|
||||
private TXVodPlayer mPlayer;
|
||||
private boolean mPaused;//生命周期暂停
|
||||
private boolean mClickPaused;//点击暂停
|
||||
private ActionListener mActionListener;
|
||||
private View mPlayBtn;
|
||||
private ObjectAnimator mPlayBtnAnimator;//暂停按钮的动画
|
||||
private boolean mStartPlay;
|
||||
private boolean mEndPlay;
|
||||
private VideoBean mVideoBean;
|
||||
private String mCachePath;
|
||||
private TXVodPlayConfig mTXVodPlayConfig;
|
||||
|
||||
public VideoPlayViewHolder(Context context, ViewGroup parentView) {
|
||||
super(context, parentView);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.view_video_play;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
mCachePath = mContext.getCacheDir().getAbsolutePath();
|
||||
mTXCloudVideoView = (TXCloudVideoView) findViewById(R.id.video_view);
|
||||
mTXCloudVideoView.setRenderMode(TXLiveConstants.RENDER_MODE_FULL_FILL_SCREEN);
|
||||
mPlayer = new TXVodPlayer(mContext);
|
||||
mTXVodPlayConfig = new TXVodPlayConfig();
|
||||
mTXVodPlayConfig.setMaxCacheItems(15);
|
||||
mTXVodPlayConfig.setProgressInterval(200);
|
||||
mPlayer.setConfig(mTXVodPlayConfig);
|
||||
mPlayer.setAutoPlay(true);
|
||||
mPlayer.setVodListener(this);
|
||||
mPlayer.setPlayerView(mTXCloudVideoView);
|
||||
findViewById(R.id.root).setOnClickListener(this);
|
||||
mVideoCover = findViewById(R.id.video_cover);
|
||||
mPlayBtn = findViewById(R.id.btn_play);
|
||||
//暂停按钮动画
|
||||
mPlayBtnAnimator = ObjectAnimator.ofPropertyValuesHolder(mPlayBtn,
|
||||
PropertyValuesHolder.ofFloat("scaleX", 4f, 0.8f, 1f),
|
||||
PropertyValuesHolder.ofFloat("scaleY", 4f, 0.8f, 1f),
|
||||
PropertyValuesHolder.ofFloat("alpha", 0f, 1f));
|
||||
mPlayBtnAnimator.setDuration(150);
|
||||
mPlayBtnAnimator.setInterpolator(new AccelerateInterpolator());
|
||||
}
|
||||
|
||||
/**
|
||||
* 播放器事件回调
|
||||
*/
|
||||
@Override
|
||||
public void onPlayEvent(TXVodPlayer txVodPlayer, int e, Bundle bundle) {
|
||||
switch (e) {
|
||||
case TXLiveConstants.PLAY_EVT_PLAY_BEGIN://加载完成,开始播放的回调
|
||||
mStartPlay = true;
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onPlayBegin();
|
||||
}
|
||||
|
||||
break;
|
||||
case TXLiveConstants.PLAY_EVT_PLAY_LOADING: //开始加载的回调
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onPlayLoading();
|
||||
}
|
||||
break;
|
||||
case TXLiveConstants.PLAY_EVT_PLAY_END://获取到视频播放完毕的回调
|
||||
replay();
|
||||
if (!mEndPlay) {
|
||||
mEndPlay = true;
|
||||
if (mVideoBean != null) {
|
||||
VideoHttpUtil.videoWatchEnd(mVideoBean.getUid(), mVideoBean.getId());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TXLiveConstants.PLAY_EVT_RCV_FIRST_I_FRAME://获取到视频首帧回调
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onFirstFrame();
|
||||
}
|
||||
if (mPaused && mPlayer != null) {
|
||||
mPlayer.pause();
|
||||
}
|
||||
break;
|
||||
case TXLiveConstants.PLAY_EVT_CHANGE_RESOLUTION://获取到视频宽高回调
|
||||
onVideoSizeChanged(bundle.getInt("EVT_PARAM1", 0), bundle.getInt("EVT_PARAM2", 0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetStatus(TXVodPlayer txVodPlayer, Bundle bundle) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取到视频宽高回调
|
||||
*/
|
||||
public void onVideoSizeChanged(float videoWidth, float videoHeight) {
|
||||
if (mTXCloudVideoView != null && videoWidth > 0 && videoHeight > 0) {
|
||||
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mTXCloudVideoView.getLayoutParams();
|
||||
int targetH = 0;
|
||||
if (videoWidth / videoHeight > 0.5625f) {//横屏 9:16=0.5625
|
||||
targetH = (int) (mTXCloudVideoView.getWidth() / videoWidth * videoHeight);
|
||||
} else {
|
||||
targetH = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
}
|
||||
if (targetH != params.height) {
|
||||
params.height = targetH;
|
||||
mTXCloudVideoView.requestLayout();
|
||||
}
|
||||
if (mVideoCover != null && mVideoCover.getVisibility() == View.VISIBLE) {
|
||||
mVideoCover.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始播放
|
||||
*/
|
||||
public void startPlay(VideoBean videoBean) {
|
||||
mStartPlay = false;
|
||||
mClickPaused = false;
|
||||
mEndPlay = false;
|
||||
mVideoBean = videoBean;
|
||||
if (mVideoCover != null && mVideoCover.getVisibility() != View.VISIBLE) {
|
||||
mVideoCover.setVisibility(View.VISIBLE);
|
||||
}
|
||||
hidePlayBtn();
|
||||
L.e("播放视频--->" + videoBean);
|
||||
if (videoBean == null) {
|
||||
return;
|
||||
}
|
||||
String url = videoBean.getHref();
|
||||
if (TextUtils.isEmpty(url)) {
|
||||
return;
|
||||
}
|
||||
if (mTXVodPlayConfig == null) {
|
||||
mTXVodPlayConfig = new TXVodPlayConfig();
|
||||
mTXVodPlayConfig.setMaxCacheItems(15);
|
||||
mTXVodPlayConfig.setProgressInterval(200);
|
||||
}
|
||||
if (url.endsWith(".m3u8")) {
|
||||
mTXVodPlayConfig.setCacheFolderPath(null);
|
||||
} else {
|
||||
mTXVodPlayConfig.setCacheFolderPath(mCachePath);
|
||||
}
|
||||
mPlayer.setConfig(mTXVodPlayConfig);
|
||||
if (mPlayer != null) {
|
||||
mPlayer.startPlay(url);
|
||||
}
|
||||
VideoHttpUtil.videoWatchStart(videoBean.getUid(), videoBean.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止播放
|
||||
*/
|
||||
public void stopPlay() {
|
||||
if (mPlayer != null) {
|
||||
mPlayer.stopPlay(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 循环播放
|
||||
*/
|
||||
private void replay() {
|
||||
if (mPlayer != null) {
|
||||
mPlayer.seek(0);
|
||||
mPlayer.resume();
|
||||
}
|
||||
}
|
||||
|
||||
public void release() {
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.VIDEO_WATCH_START);
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.VIDEO_WATCH_END);
|
||||
if (mPlayer != null) {
|
||||
mPlayer.stopPlay(false);
|
||||
mPlayer.setPlayListener(null);
|
||||
}
|
||||
mPlayer = null;
|
||||
mActionListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生命周期暂停
|
||||
*/
|
||||
public void pausePlay() {
|
||||
mPaused = true;
|
||||
if (!mClickPaused && mPlayer != null) {
|
||||
mPlayer.pause();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生命周期恢复
|
||||
*/
|
||||
public void resumePlay() {
|
||||
if (mPaused) {
|
||||
if (!mClickPaused && mPlayer != null) {
|
||||
mPlayer.resume();
|
||||
}
|
||||
}
|
||||
mPaused = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示开始播放按钮
|
||||
*/
|
||||
private void showPlayBtn() {
|
||||
if (mPlayBtn != null && mPlayBtn.getVisibility() != View.VISIBLE) {
|
||||
mPlayBtn.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏开始播放按钮
|
||||
*/
|
||||
private void hidePlayBtn() {
|
||||
if (mPlayBtn != null && mPlayBtn.getVisibility() == View.VISIBLE) {
|
||||
mPlayBtn.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 点击切换播放和暂停
|
||||
*/
|
||||
private void clickTogglePlay() {
|
||||
if (!mStartPlay) {
|
||||
return;
|
||||
}
|
||||
if (mPlayer != null) {
|
||||
if (mClickPaused) {
|
||||
mPlayer.resume();
|
||||
} else {
|
||||
mPlayer.pause();
|
||||
}
|
||||
}
|
||||
mClickPaused = !mClickPaused;
|
||||
if (mClickPaused) {
|
||||
showPlayBtn();
|
||||
if (mPlayBtnAnimator != null) {
|
||||
mPlayBtnAnimator.start();
|
||||
}
|
||||
} else {
|
||||
hidePlayBtn();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int i = v.getId();
|
||||
if (i == R.id.root) {
|
||||
clickTogglePlay();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface ActionListener {
|
||||
void onPlayBegin();
|
||||
|
||||
void onPlayLoading();
|
||||
|
||||
void onFirstFrame();
|
||||
}
|
||||
|
||||
|
||||
public void setActionListener(ActionListener actionListener) {
|
||||
mActionListener = actionListener;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,460 @@
|
||||
package com.yunbao.video.views;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.ScaleAnimation;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.yunbao.common.Constants;
|
||||
import com.yunbao.common.bean.UserBean;
|
||||
import com.yunbao.common.glide.ImgLoader;
|
||||
import com.yunbao.common.http.CommonHttpUtil;
|
||||
import com.yunbao.common.http.HttpCallback;
|
||||
import com.yunbao.common.interfaces.CommonCallback;
|
||||
import com.yunbao.common.utils.RouteUtil;
|
||||
import com.yunbao.common.utils.ToastUtil;
|
||||
import com.yunbao.common.views.AbsViewHolder;
|
||||
import com.yunbao.live.activity.LiveReportActivity;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.activity.AbsVideoPlayActivity;
|
||||
import com.yunbao.video.bean.VideoBean;
|
||||
import com.yunbao.video.dialog.VideoShareDialogFragment;
|
||||
import com.yunbao.video.event.VideoLikeEvent;
|
||||
import com.yunbao.video.http.VideoHttpUtil;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/11/26.
|
||||
* 视频播放外框
|
||||
*/
|
||||
|
||||
public class VideoPlayWrapViewHolder extends AbsViewHolder implements View.OnClickListener {
|
||||
|
||||
private ViewGroup mVideoContainer;
|
||||
private ImageView mCover;
|
||||
private ImageView mAvatar;
|
||||
private TextView mName;
|
||||
private TextView mTitle;
|
||||
private ImageView mBtnLike;//点赞按钮
|
||||
private TextView mLikeNum;//点赞数
|
||||
private TextView mCommentNum;//评论数
|
||||
private TextView mShareNum;//分享数
|
||||
private ImageView mBtnFollow;//关注按钮
|
||||
private VideoBean mVideoBean;
|
||||
private Drawable mFollowDrawable = null;//已关注
|
||||
private Drawable mUnFollowDrawable;//未关注
|
||||
private Animation mFollowAnimation;
|
||||
private boolean mCurPageShowed;//当前页面是否可见
|
||||
private ValueAnimator mLikeAnimtor;
|
||||
private Drawable[] mLikeAnimDrawables;//点赞帧动画
|
||||
private int mLikeAnimIndex;
|
||||
private String mTag;
|
||||
private TextView tv_video_report;
|
||||
|
||||
public VideoPlayWrapViewHolder(Context context, ViewGroup parentView) {
|
||||
super(context, parentView);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.view_video_play_wrap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
mTag = this.toString();
|
||||
mVideoContainer = (ViewGroup) findViewById(R.id.video_container);
|
||||
mCover = (ImageView) findViewById(R.id.cover);
|
||||
mAvatar = (ImageView) findViewById(R.id.avatar2);
|
||||
mName = (TextView) findViewById(R.id.name);
|
||||
mTitle = (TextView) findViewById(R.id.title);
|
||||
mBtnLike = (ImageView) findViewById(R.id.btn_like);
|
||||
mLikeNum = (TextView) findViewById(R.id.like_num);
|
||||
mCommentNum = (TextView) findViewById(R.id.comment_num);
|
||||
mShareNum = (TextView) findViewById(R.id.share_num);
|
||||
mBtnFollow = (ImageView) findViewById(R.id.btn_follow2);
|
||||
|
||||
tv_video_report = (TextView) findViewById(R.id.tv_video_report);
|
||||
|
||||
// mFollowDrawable = ContextCompat.getDrawable(mContext, R.mipmap.icon_video_follow_1);
|
||||
mUnFollowDrawable = ContextCompat.getDrawable(mContext, R.mipmap.icon_video_follow_0);
|
||||
mAvatar.setOnClickListener(this);
|
||||
mBtnFollow.setOnClickListener(this);
|
||||
mBtnLike.setOnClickListener(this);
|
||||
findViewById(R.id.btn_comment).setOnClickListener(this);
|
||||
findViewById(R.id.btn_share).setOnClickListener(this);
|
||||
findViewById(R.id.tv_video_report).setOnClickListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化点赞动画
|
||||
*/
|
||||
private void initLikeAnimtor() {
|
||||
if (mLikeAnimDrawables != null && mLikeAnimDrawables.length > 0) {
|
||||
mLikeAnimtor = ValueAnimator.ofFloat(0, mLikeAnimDrawables.length);
|
||||
mLikeAnimtor.setDuration(800);
|
||||
mLikeAnimtor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
float v = (float) animation.getAnimatedValue();
|
||||
int index = (int) v;
|
||||
if (mLikeAnimIndex != index) {
|
||||
mLikeAnimIndex = index;
|
||||
if (mBtnLike != null && mLikeAnimDrawables != null && index < mLikeAnimDrawables.length) {
|
||||
mBtnLike.setImageDrawable(mLikeAnimDrawables[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化关注动画
|
||||
*/
|
||||
public void initFollowAnimation() {
|
||||
mFollowAnimation = new ScaleAnimation(1, 0.3f, 1, 0.3f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
|
||||
mFollowAnimation.setRepeatMode(Animation.REVERSE);
|
||||
mFollowAnimation.setRepeatCount(1);
|
||||
mFollowAnimation.setDuration(200);
|
||||
mFollowAnimation.setAnimationListener(new Animation.AnimationListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {
|
||||
if (mBtnFollow != null && mVideoBean != null) {
|
||||
if (mVideoBean.getAttent() == 1) {
|
||||
mBtnFollow.setImageDrawable(mFollowDrawable);
|
||||
} else {
|
||||
mBtnFollow.setImageDrawable(mUnFollowDrawable);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setLikeAnimDrawables(Drawable[] drawables) {
|
||||
mLikeAnimDrawables = drawables;
|
||||
}
|
||||
|
||||
public void setData(VideoBean bean, Object payload) {
|
||||
if (bean == null) {
|
||||
return;
|
||||
}
|
||||
mVideoBean = bean;
|
||||
UserBean u = mVideoBean.getUserBean();
|
||||
if (payload == null) {
|
||||
if (mCover != null) {
|
||||
setCoverImage();
|
||||
}
|
||||
if (mTitle != null) {
|
||||
mTitle.setText(bean.getTitle());
|
||||
}
|
||||
if (u != null) {
|
||||
if (mAvatar != null) {
|
||||
ImgLoader.displayAvatar(mContext, u.getAvatar(), mAvatar);
|
||||
}
|
||||
if (mName != null) {
|
||||
mName.setText("@" + u.getUserNiceName());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mBtnLike != null) {
|
||||
if (bean.getLike() == 1) {
|
||||
if (mLikeAnimDrawables != null && mLikeAnimDrawables.length > 0) {
|
||||
mBtnLike.setImageDrawable(mLikeAnimDrawables[mLikeAnimDrawables.length - 1]);
|
||||
}
|
||||
} else {
|
||||
mBtnLike.setImageResource(R.mipmap.icon_video_zan_01);
|
||||
}
|
||||
}
|
||||
if (mLikeNum != null) {
|
||||
mLikeNum.setText(bean.getLikeNum());
|
||||
}
|
||||
if (mCommentNum != null) {
|
||||
mCommentNum.setText(bean.getCommentNum());
|
||||
}
|
||||
if (mShareNum != null) {
|
||||
mShareNum.setText(bean.getShareNum());
|
||||
}
|
||||
// if (u != null && mBtnFollow != null) {
|
||||
// String toUid = u.getId();
|
||||
// if (!TextUtils.isEmpty(toUid) && !toUid.equals(CommonAppConfig.getInstance().getUid())) {
|
||||
// if (mBtnFollow.getVisibility() != View.VISIBLE) {
|
||||
// mBtnFollow.setVisibility(View.VISIBLE);
|
||||
// }
|
||||
// if (bean.getAttent() == 1) {
|
||||
// mBtnFollow.setImageDrawable(mFollowDrawable);
|
||||
// } else {
|
||||
// mBtnFollow.setImageDrawable(mUnFollowDrawable);
|
||||
// }
|
||||
// } else {
|
||||
// if (mBtnFollow.getVisibility() == View.VISIBLE) {
|
||||
// mBtnFollow.setVisibility(View.INVISIBLE);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if (!Constants.myUid.endsWith(bean.getUid())) {
|
||||
// if (bean.getAttent() == 2) {
|
||||
// mBtnFollow.setVisibility(View.VISIBLE);
|
||||
// if (bean.getAttent() == 1) {
|
||||
// mBtnFollow.setImageDrawable(mFollowDrawable);
|
||||
// } else {
|
||||
// mBtnFollow.setImageDrawable(mUnFollowDrawable);
|
||||
// }
|
||||
// } else {
|
||||
// mBtnFollow.setVisibility(View.GONE);
|
||||
// }
|
||||
} else {
|
||||
// mBtnFollow.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void setCoverImage() {
|
||||
ImgLoader.displayDrawable(mContext, mVideoBean.getThumb(), new ImgLoader.DrawableCallback() {
|
||||
@Override
|
||||
public void onLoadSuccess(Drawable drawable) {
|
||||
if (mCover != null && drawable != null) {
|
||||
float w = drawable.getIntrinsicWidth();
|
||||
float h = drawable.getIntrinsicHeight();
|
||||
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mCover.getLayoutParams();
|
||||
int targetH = 0;
|
||||
if (w / h > 0.5625f) {//横屏 9:16=0.5625
|
||||
targetH = (int) (mCover.getWidth() / w * h);
|
||||
} else {
|
||||
targetH = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
}
|
||||
if (targetH != params.height) {
|
||||
params.height = targetH;
|
||||
mCover.requestLayout();
|
||||
}
|
||||
mCover.setImageDrawable(drawable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFailed() {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void addVideoView(View view) {
|
||||
if (mVideoContainer != null && view != null) {
|
||||
ViewParent parent = view.getParent();
|
||||
if (parent != null) {
|
||||
ViewGroup viewGroup = (ViewGroup) parent;
|
||||
if (viewGroup != mVideoContainer) {
|
||||
viewGroup.removeView(view);
|
||||
mVideoContainer.addView(view);
|
||||
}
|
||||
} else {
|
||||
mVideoContainer.addView(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public VideoBean getVideoBean() {
|
||||
return mVideoBean;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取到视频首帧回调
|
||||
*/
|
||||
public void onFirstFrame() {
|
||||
if (mCover != null && mCover.getVisibility() == View.VISIBLE) {
|
||||
mCover.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 滑出屏幕
|
||||
*/
|
||||
public void onPageOutWindow() {
|
||||
mCurPageShowed = false;
|
||||
if (mCover != null && mCover.getVisibility() != View.VISIBLE) {
|
||||
mCover.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 滑入屏幕
|
||||
*/
|
||||
public void onPageInWindow() {
|
||||
if (mCover != null) {
|
||||
if (mCover.getVisibility() != View.VISIBLE) {
|
||||
mCover.setVisibility(View.VISIBLE);
|
||||
}
|
||||
mCover.setImageDrawable(null);
|
||||
setCoverImage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 滑动到这一页 准备开始播放
|
||||
*/
|
||||
public void onPageSelected() {
|
||||
mCurPageShowed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (!canClick()) {
|
||||
return;
|
||||
}
|
||||
int i = v.getId();
|
||||
if (i == R.id.btn_follow2) {
|
||||
clickFollow();
|
||||
} else if (i == R.id.btn_comment) {
|
||||
clickComment();
|
||||
} else if (i == R.id.btn_share) {
|
||||
clickShare();
|
||||
} else if (i == R.id.btn_like) {
|
||||
clickLike();
|
||||
} else if (i == R.id.avatar2) {
|
||||
clickAvatar();
|
||||
} else if (i == R.id.tv_video_report) {
|
||||
if (mVideoBean == null) {
|
||||
return;
|
||||
}
|
||||
LiveReportActivity.forward2(mContext, mVideoBean.getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击头像
|
||||
*/
|
||||
public void clickAvatar() {
|
||||
if (mVideoBean != null) {
|
||||
RouteUtil.forwardUserHome(mContext, mVideoBean.getUid(), 2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 点赞,取消点赞
|
||||
*/
|
||||
private void clickLike() {
|
||||
if (mVideoBean == null) {
|
||||
return;
|
||||
}
|
||||
VideoHttpUtil.setVideoLike(mTag, mVideoBean.getId(), new HttpCallback() {
|
||||
@Override
|
||||
public void onSuccess(int code, String msg, String[] info) {
|
||||
if (code == 0 && info.length > 0) {
|
||||
JSONObject obj = JSON.parseObject(info[0]);
|
||||
String likeNum = obj.getString("likes");
|
||||
int like = obj.getIntValue("islike");
|
||||
if (mVideoBean != null) {
|
||||
mVideoBean.setLikeNum(likeNum);
|
||||
mVideoBean.setLike(like);
|
||||
EventBus.getDefault().post(new VideoLikeEvent(mVideoBean.getId(), like, likeNum));
|
||||
}
|
||||
if (mLikeNum != null) {
|
||||
mLikeNum.setText(likeNum);
|
||||
}
|
||||
if (mBtnLike != null) {
|
||||
if (like == 1) {
|
||||
if (mLikeAnimtor == null) {
|
||||
initLikeAnimtor();
|
||||
}
|
||||
mLikeAnimIndex = -1;
|
||||
if (mLikeAnimtor != null) {
|
||||
mLikeAnimtor.start();
|
||||
}
|
||||
} else {
|
||||
mBtnLike.setImageResource(R.mipmap.icon_video_zan_01);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ToastUtil.show(msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击关注按钮
|
||||
*/
|
||||
private void clickFollow() {
|
||||
if (mVideoBean == null) {
|
||||
return;
|
||||
}
|
||||
final UserBean u = mVideoBean.getUserBean();
|
||||
if (u == null) {
|
||||
return;
|
||||
}
|
||||
CommonHttpUtil.setAttention(mTag, u.getId(), new CommonCallback<Integer>() {
|
||||
@Override
|
||||
public void callback(Integer attent) {
|
||||
mVideoBean.setAttent(attent);
|
||||
if (mCurPageShowed) {
|
||||
if (mFollowAnimation == null) {
|
||||
initFollowAnimation();
|
||||
}
|
||||
mBtnFollow.startAnimation(mFollowAnimation);
|
||||
} else {
|
||||
if (attent == 1) {
|
||||
mBtnFollow.setImageDrawable(mFollowDrawable);
|
||||
} else {
|
||||
mBtnFollow.setImageDrawable(mUnFollowDrawable);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击评论按钮
|
||||
*/
|
||||
private void clickComment() {
|
||||
((AbsVideoPlayActivity) mContext).openCommentWindow(mVideoBean.getId(), mVideoBean.getUid());
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击分享按钮
|
||||
*/
|
||||
private void clickShare() {
|
||||
if (mVideoBean == null) {
|
||||
return;
|
||||
}
|
||||
VideoShareDialogFragment fragment = new VideoShareDialogFragment();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(Constants.VIDEO_BEAN, mVideoBean);
|
||||
fragment.setArguments(bundle);
|
||||
fragment.show(((AbsVideoPlayActivity) mContext).getSupportFragmentManager(), "VideoShareDialogFragment");
|
||||
}
|
||||
|
||||
public void release() {
|
||||
VideoHttpUtil.cancel(mTag);
|
||||
if (mLikeAnimtor != null) {
|
||||
mLikeAnimtor.cancel();
|
||||
}
|
||||
if (mBtnFollow != null && mFollowAnimation != null) {
|
||||
mBtnFollow.clearAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.yunbao.video.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.yunbao.common.views.AbsViewHolder;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.custom.NumberProgressBar;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/12/6.
|
||||
* 视频处理进度条
|
||||
*/
|
||||
|
||||
public class VideoProcessViewHolder extends AbsViewHolder implements View.OnClickListener {
|
||||
|
||||
private TextView mTitle;
|
||||
private String mTitleString;
|
||||
private NumberProgressBar mProgressBar;
|
||||
private ActionListener mActionListener;
|
||||
private int mProgress;
|
||||
|
||||
public VideoProcessViewHolder(Context context, ViewGroup parentView, String title) {
|
||||
super(context, parentView, title);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processArguments(Object... args) {
|
||||
mTitleString = (String) args[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.view_video_process;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
mTitle = (TextView) findViewById(R.id.title);
|
||||
mTitle.setText(mTitleString);
|
||||
mProgressBar = (NumberProgressBar) findViewById(R.id.progressbar);
|
||||
findViewById(R.id.btn_cancel).setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int i = v.getId();
|
||||
if (i == R.id.btn_cancel) {
|
||||
if (mActionListener != null) {
|
||||
mActionListener.onCancelProcessClick();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void setProgress(int progress) {
|
||||
if (mProgress != progress) {
|
||||
mProgress = progress;
|
||||
if (mProgressBar != null) {
|
||||
mProgressBar.setProgress(progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getProgress(){
|
||||
return mProgress;
|
||||
}
|
||||
|
||||
|
||||
public interface ActionListener {
|
||||
void onCancelProcessClick();
|
||||
}
|
||||
|
||||
public void setActionListener(ActionListener actionListener) {
|
||||
mActionListener = actionListener;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
package com.yunbao.video.views;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.yunbao.common.event.FollowEvent;
|
||||
import com.yunbao.common.views.AbsViewHolder;
|
||||
import com.yunbao.video.R;
|
||||
import com.yunbao.video.activity.AbsVideoPlayActivity;
|
||||
import com.yunbao.video.adapter.VideoScrollAdapter;
|
||||
import com.yunbao.video.bean.VideoBean;
|
||||
import com.yunbao.video.custom.VideoLoadingBar;
|
||||
import com.yunbao.video.event.VideoCommentEvent;
|
||||
import com.yunbao.video.event.VideoLikeEvent;
|
||||
import com.yunbao.video.event.VideoShareEvent;
|
||||
import com.yunbao.video.http.VideoHttpConsts;
|
||||
import com.yunbao.video.http.VideoHttpUtil;
|
||||
import com.yunbao.video.interfaces.VideoScrollDataHelper;
|
||||
import com.yunbao.video.utils.VideoStorge;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by cxf on 2018/11/26.
|
||||
* 视频滑动
|
||||
*/
|
||||
|
||||
public class VideoScrollViewHolder extends AbsViewHolder implements
|
||||
VideoScrollAdapter.ActionListener, SwipeRefreshLayout.OnRefreshListener,
|
||||
VideoPlayViewHolder.ActionListener, View.OnClickListener {
|
||||
|
||||
private VideoPlayViewHolder mVideoPlayViewHolder;
|
||||
private View mPlayView;
|
||||
private SwipeRefreshLayout mRefreshLayout;
|
||||
private RecyclerView mRecyclerView;
|
||||
private VideoScrollAdapter mVideoScrollAdapter;
|
||||
private int mPosition;
|
||||
private String mVideoKey;
|
||||
private VideoPlayWrapViewHolder mVideoPlayWrapViewHolder;
|
||||
private VideoLoadingBar mVideoLoadingBar;
|
||||
private int mPage;
|
||||
// private HttpCallback mRefreshCallback;//下拉刷新回调
|
||||
// private HttpCallback mLoadMoreCallback;//上拉加载更多回调
|
||||
private VideoScrollDataHelper mVideoDataHelper;
|
||||
private VideoBean mVideoBean;
|
||||
private boolean mPaused;//生命周期暂停
|
||||
|
||||
public VideoScrollViewHolder(Context context, ViewGroup parentView, int position, String videoKey, int page) {
|
||||
super(context, parentView, position, videoKey, page);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processArguments(Object... args) {
|
||||
mPosition = (int) args[0];
|
||||
mVideoKey = (String) args[1];
|
||||
mPage = (int) args[2];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.view_video_scroll;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
List<VideoBean> list = VideoStorge.getInstance().get(mVideoKey);
|
||||
if (list == null || list.size() == 0) {
|
||||
return;
|
||||
}
|
||||
mVideoPlayViewHolder = new VideoPlayViewHolder(mContext, null);
|
||||
mVideoPlayViewHolder.setActionListener(this);
|
||||
mPlayView = mVideoPlayViewHolder.getContentView();
|
||||
mRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.refreshLayout);
|
||||
mRefreshLayout.setOnRefreshListener(this);
|
||||
mRefreshLayout.setColorSchemeResources(R.color.global);
|
||||
mRefreshLayout.setEnabled(false);//产品不让使用刷新
|
||||
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
|
||||
mRecyclerView.setHasFixedSize(true);
|
||||
mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false));
|
||||
mVideoScrollAdapter = new VideoScrollAdapter(mContext, list, mPosition);
|
||||
mVideoScrollAdapter.setActionListener(this);
|
||||
mRecyclerView.setAdapter(mVideoScrollAdapter);
|
||||
mVideoLoadingBar = (VideoLoadingBar) findViewById(R.id.video_loading);
|
||||
findViewById(R.id.input_tip).setOnClickListener(this);
|
||||
findViewById(R.id.btn_face).setOnClickListener(this);
|
||||
EventBus.getDefault().register(this);
|
||||
// mRefreshCallback = new HttpCallback() {
|
||||
// @Override
|
||||
// public void onSuccess(int code, String msg, String[] info) {
|
||||
// if (code == 0) {
|
||||
// List<VideoBean> list = JSON.parseArray(Arrays.toString(info), VideoBean.class);
|
||||
// if (mVideoScrollAdapter != null) {
|
||||
// mVideoScrollAdapter.setList(list);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFinish() {
|
||||
// if (mRefreshLayout != null) {
|
||||
// mRefreshLayout.setRefreshing(false);
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// mLoadMoreCallback = new HttpCallback() {
|
||||
// @Override
|
||||
// public void onSuccess(int code, String msg, String[] info) {
|
||||
// if (code == 0) {
|
||||
// List<VideoBean> list = JSON.parseArray(Arrays.toString(info), VideoBean.class);
|
||||
// if (list.size() > 0) {
|
||||
// if (mVideoScrollAdapter != null) {
|
||||
// mVideoScrollAdapter.insertList(list);
|
||||
// }
|
||||
// EventBus.getDefault().post(new VideoScrollPageEvent(mVideoKey, mPage));
|
||||
// } else {
|
||||
// ToastUtil.show(R.string.video_no_more_video);
|
||||
// mPage--;
|
||||
// }
|
||||
// } else {
|
||||
// mPage--;
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
if (mVideoScrollAdapter != null) {
|
||||
mVideoScrollAdapter.insertList(list);
|
||||
}
|
||||
|
||||
mVideoDataHelper = VideoStorge.getInstance().getDataHelper(mVideoKey);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPageSelected(VideoPlayWrapViewHolder videoPlayWrapViewHolder, boolean needLoadMore) {
|
||||
if (videoPlayWrapViewHolder != null) {
|
||||
VideoBean videoBean = videoPlayWrapViewHolder.getVideoBean();
|
||||
if (videoBean != null) {
|
||||
mVideoBean = videoBean;
|
||||
mVideoPlayWrapViewHolder = videoPlayWrapViewHolder;
|
||||
videoPlayWrapViewHolder.addVideoView(mPlayView);
|
||||
if (mVideoPlayViewHolder != null) {
|
||||
mVideoPlayViewHolder.startPlay(videoBean);
|
||||
}
|
||||
if (mVideoLoadingBar != null) {
|
||||
mVideoLoadingBar.setLoading(true);
|
||||
}
|
||||
}
|
||||
if (needLoadMore) {
|
||||
onLoadMore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageOutWindow(VideoPlayWrapViewHolder vh) {
|
||||
if (mVideoPlayWrapViewHolder != null && mVideoPlayWrapViewHolder == vh && mVideoPlayViewHolder != null) {
|
||||
mVideoPlayViewHolder.stopPlay();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVideoDeleteAll() {
|
||||
((AbsVideoPlayActivity) mContext).onBackPressed();
|
||||
}
|
||||
|
||||
public void release() {
|
||||
VideoHttpUtil.cancel(VideoHttpConsts.GET_HOME_VIDEO_LIST);
|
||||
EventBus.getDefault().unregister(this);
|
||||
if (mVideoPlayViewHolder != null) {
|
||||
mVideoPlayViewHolder.release();
|
||||
}
|
||||
mVideoPlayWrapViewHolder = null;
|
||||
if (mVideoLoadingBar != null) {
|
||||
mVideoLoadingBar.endLoading();
|
||||
}
|
||||
mVideoLoadingBar = null;
|
||||
if (mRefreshLayout != null) {
|
||||
mRefreshLayout.setOnRefreshListener(null);
|
||||
}
|
||||
mRefreshLayout = null;
|
||||
if (mVideoScrollAdapter != null) {
|
||||
mVideoScrollAdapter.release();
|
||||
}
|
||||
mVideoScrollAdapter = null;
|
||||
mVideoDataHelper = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 下拉刷新
|
||||
*/
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
// mPage = 1;
|
||||
// if (mVideoDataHelper != null) {
|
||||
// mVideoDataHelper.loadData(mPage, mRefreshCallback);
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载更多
|
||||
*/
|
||||
private void onLoadMore() {
|
||||
// mPage++;
|
||||
// if (mVideoDataHelper != null) {
|
||||
// mVideoDataHelper.loadData(mPage, mLoadMoreCallback);
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayBegin() {
|
||||
if (mVideoLoadingBar != null) {
|
||||
mVideoLoadingBar.setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayLoading() {
|
||||
if (mVideoLoadingBar != null) {
|
||||
mVideoLoadingBar.setLoading(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFirstFrame() {
|
||||
if (mVideoPlayWrapViewHolder != null) {
|
||||
mVideoPlayWrapViewHolder.onFirstFrame();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关注发生变化
|
||||
*/
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onFollowEvent(FollowEvent e) {
|
||||
if (mVideoScrollAdapter != null && mVideoPlayWrapViewHolder != null) {
|
||||
VideoBean videoBean = mVideoPlayWrapViewHolder.getVideoBean();
|
||||
if (videoBean != null) {
|
||||
mVideoScrollAdapter.onFollowChanged(!mPaused, videoBean.getId(), e.getToUid(), e.getIsAttention());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 点赞发生变化
|
||||
*/
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onVideoLikeEvent(VideoLikeEvent e) {
|
||||
if (mVideoScrollAdapter != null) {
|
||||
mVideoScrollAdapter.onLikeChanged(!mPaused, e.getVideoId(), e.getIsLike(), e.getLikeNum());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分享数发生变化
|
||||
*/
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onVideoShareEvent(VideoShareEvent e) {
|
||||
if (mVideoScrollAdapter != null) {
|
||||
mVideoScrollAdapter.onShareChanged(e.getVideoId(), e.getShareNum());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 评论数发生变化
|
||||
*/
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onVideoCommentEvent(VideoCommentEvent e) {
|
||||
if (mVideoScrollAdapter != null) {
|
||||
mVideoScrollAdapter.onCommentChanged(e.getVideoId(), e.getCommentNum());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除视频
|
||||
*/
|
||||
public void deleteVideo(VideoBean videoBean) {
|
||||
if (mVideoScrollAdapter != null) {
|
||||
mVideoScrollAdapter.deleteVideo(videoBean);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int i = v.getId();
|
||||
if (i == R.id.input_tip) {
|
||||
openCommentInputWindow(false);
|
||||
|
||||
} else if (i == R.id.btn_face) {
|
||||
openCommentInputWindow(true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开评论输入框
|
||||
*/
|
||||
private void openCommentInputWindow(boolean openFace) {
|
||||
if (mVideoBean != null) {
|
||||
((AbsVideoPlayActivity) mContext).openCommentInputWindow(openFace, mVideoBean.getId(), mVideoBean.getUid(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* VideoBean 数据发生变化
|
||||
*/
|
||||
public void onVideoBeanChanged(String videoId) {
|
||||
if (mVideoScrollAdapter != null) {
|
||||
mVideoScrollAdapter.onVideoBeanChanged(videoId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mPaused = true;
|
||||
if (mVideoPlayViewHolder != null) {
|
||||
mVideoPlayViewHolder.pausePlay();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mPaused = false;
|
||||
if (mVideoPlayViewHolder != null) {
|
||||
mVideoPlayViewHolder.resumePlay();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user