androidx版本首次提交

This commit is contained in:
18401019693
2022-07-18 15:31:45 +08:00
commit 1791a114e3
2932 changed files with 218954 additions and 0 deletions

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}
}

View File

@@ -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");
}
}

View File

@@ -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

View File

@@ -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();
}
}

View 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);
}
}
}
}
}

View File

@@ -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());
}
}
}

View File

@@ -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());
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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());
// }
}
}

View 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);
}
};
}

View File

@@ -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;
}
}

View 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();
}
}

View File

@@ -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;
}
}

View 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];
}
};
}

View File

@@ -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 + '\'' +
'}';
}
}

View File

@@ -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;
}
}

View File

@@ -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;
// }
}

View 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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View 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;
}
}

View File

@@ -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);
}
}
}
}

View 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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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));
}
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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";
}

View 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);
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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();
}
}
}

View File

@@ -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();
}

View File

@@ -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();
}
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View 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();
}
}
}

View 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);
}
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
});
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}
}

View File

@@ -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() {
}
});
}
}

View File

@@ -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() {
}
});
}
}

View File

@@ -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();
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}
}