近来静极思动,决定写一堆博客。
没别的意思,单纯的想****
//小白使用文档
https://shimo.im/docs/xj5F85W1gqEEBXRJ
https://shimo.im/docs/xj5F85W1gqEEBXRJ/read
//简书
https://www.jianshu.com/p/4c187a09b838
//导入依赖 饺子播放器 https://github.com/lipangit/JiaoZiVideoPlayer
//视频播放器
compile 'cn.jzvd:jiaozivideoplayer:6.2.9'
//为了能够带入到项目中使用 需要自定播放器
public class MyJZVideoPlayerStandard extends JZVideoPlayerStandard {
private Context mContext;
public MyJZVideoPlayerStandard(Context context) {
super(context);
mContext=context;
}
public MyJZVideoPlayerStandard(Context context, AttributeSet attrs) {
super(context, attrs);
mContext=context;
}
@Override
public void init(Context context) {
super.init(context);
mContext=context;
}
@Override
public void onClick(View v) {
super.onClick(v);
}
@Override
public int getLayoutId() {
return cn.jzvd.R.layout.jz_layout_standard;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return super.onTouch(v, event);
}
@Override
public void startVideo() {
super.startVideo();
}
@Override
public void onStateNormal() {
super.onStateNormal();
}
@Override
public void onStatePreparing() {
super.onStatePreparing();
}
@Override
public void onStatePlaying() {
super.onStatePlaying();
if(MusicService.isPlaying){
EventBus.getDefault().postSticky(new MusicData(false,0));
Intent intent = new Intent(mContext, MusicService.class);
intent.setAction(MusicService.ACTION_Pause);
mContext.startService(intent);
}else{
Toast.makeText(mContext, "没有在播放", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onStatePause() {
super.onStatePause();
}
@Override
public void onStateError() {
super.onStateError();
}
@Override
public void onStateAutoComplete() {
super.onStateAutoComplete();
}
@Override
public void onInfo(int what, int extra) {
super.onInfo(what, extra);
}
@Override
public void onError(int what, int extra) {
super.onError(what, extra);
}
@Override
public void startWindowFullscreen() {
super.startWindowFullscreen();
}
@Override
public void startWindowTiny() {
super.startWindowTiny();
}
}
//xml
<com.as.apprehendschool.customviews.MyJZVideoPlayerStandard
android:id="@+id/videoplayer"
android:layout_width="match_parent"
android:layout_height="@dimen/x390" />
//使用
/**
* 视频分类 公共适配器 item video common
*/
public class SpflRecyclerAdapter extends BaseQuickAdapter<SPfenleiBean.DataBean, BaseViewHolder> {
public SpflRecyclerAdapter(int layoutResId, @Nullable List<SPfenleiBean.DataBean> data) {
super(layoutResId, data);
}
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void convert(BaseViewHolder helper, SPfenleiBean.DataBean item) {
helper.setText(R.id.tv_Spfl, item.getDescription());
// 看这里
final MyJZVideoPlayerStandard videoplayer_Spfl = helper.getView(R.id.videoplayer_Spfl);
SPfenleiBean.DataBean.VideoBean videoBean = item.getVideo().get(0);
videoplayer_Spfl.setUp(
videoBean.getFileurl(), JZVideoPlayer.SCREEN_WINDOW_LIST,
item.getTitle());
ImageView thumbImageView = videoplayer_Spfl.thumbImageView;
GlideLoadImageUtil.load(mContext,item.getThumb(),thumbImageView);
JZVideoPlayer.FULLSCREEN_ORIENTATION = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
}
}
//如果在别的地方需要暂停视频
boolean playing = JZMediaManager.isPlaying();
if(playing){
JZVideoPlayer currentJzvd = JZVideoPlayerManager.getCurrentJzvd();
currentJzvd.onEvent(JZUserAction.ON_CLICK_PAUSE);
JZMediaManager.pause();
currentJzvd.onStatePause();
}
//播放时 如果视频开着 先暂停 和上面一样的功能 2选一
JZVideoPlayer currentJzvd = JZVideoPlayerManager.getCurrentJzvd();
if(currentJzvd!=null){
boolean playing = JZMediaManager.isPlaying();
if(playing){
currentJzvd.onEvent(JZUserAction.ON_CLICK_PAUSE);
JZMediaManager.pause();
currentJzvd.onStatePause();
}
}
嗯,就这些了。
尺寸样式:
JZVideoPlayerStandard.setVideoImageDisplayType(JZVideoPlayerStandard.FOCUSABLE_AUTO);
还有好多种样式 比如铺满.具体可以点出来 关键字母 在 full fill auto.
如果样式不没有满足你的要求可以自己修改,遗憾的是 只会加不会减:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/butnostroke11"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:descendantFocusability="blocksDescendants">
<!--android:background="@android:color/transparent"-->
<FrameLayout
android:id="@+id/surface_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--android:background="@drawable/butnostroke11"-->
</FrameLayout>
<!--<ImageView-->
<!--android:id="@+id/thumb"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="match_parent"-->
<!--android:layout_alignParentBottom="true"-->
<!--android:layout_alignParentLeft="true"-->
<!--android:layout_alignParentStart="true"-->
<!--android:scaleType="fitXY" />-->
<cn.gavinliu.android.lib.shapedimageview.ShapedImageView
android:id="@+id/thumb"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:scaleType="fitXY"
app:round_radius="@dimen/x5"
app:shape_mode="round_rect"
app:stroke_color="@color/view_e2"
app:stroke_width="@dimen/x1" />
<LinearLayout
android:id="@+id/layout_bottom"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:background="@drawable/jz_bottom_bg"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="invisible">
<TextView
android:id="@+id/current"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="14dp"
android:text="00:00"
android:textColor="#ffffff" />
<SeekBar
android:id="@+id/bottom_seek_progress"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1.0"
android:background="@null"
android:max="100"
android:maxHeight="1dp"
android:minHeight="1dp"
android:paddingBottom="8dp"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:paddingTop="8dp"
android:progressDrawable="@drawable/jz_bottom_seek_progress"
android:thumb="@drawable/jz_bottom_seek_thumb" />
<TextView
android:id="@+id/total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00"
android:textColor="#ffffff" />
<TextView
android:id="@+id/clarity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:paddingLeft="20dp"
android:text="clarity"
android:textAlignment="center"
android:textColor="#ffffff" />
<ImageView
android:id="@+id/fullscreen"
android:layout_width="52.5dp"
android:layout_height="fill_parent"
android:paddingLeft="14dp"
android:paddingRight="14dp"
android:scaleType="centerInside"
android:src="@drawable/jz_enlarge" />
</LinearLayout>
<ProgressBar
android:id="@+id/bottom_progress"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="1.5dp"
android:layout_alignParentBottom="true"
android:max="100"
android:progressDrawable="@drawable/jz_bottom_progress" />
<ImageView
android:id="@+id/back_tiny"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginLeft="6dp"
android:layout_marginTop="6dp"
android:background="@drawable/jz_click_back_tiny_selector"
android:visibility="gone" />
<RelativeLayout
android:id="@+id/layout_top"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:background="@android:color/transparent"
android:gravity="center_vertical">
<ImageView
android:id="@+id/back"
android:layout_width="23dp"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:paddingLeft="12dp"
android:paddingStart="12dp"
android:scaleType="centerInside"
android:src="@drawable/jz_click_back_selector" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginEnd="12dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginStart="12dp"
android:layout_toEndOf="@+id/back"
android:layout_toLeftOf="@+id/battery_time_layout"
android:layout_toRightOf="@+id/back"
android:ellipsize="end"
android:maxLines="2"
android:textColor="#ffffff"
android:textSize="18sp" />
<LinearLayout
android:id="@+id/battery_time_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginEnd="14dp"
android:layout_marginRight="14dp"
android:gravity="center_vertical"
android:orientation="vertical">
<ImageView
android:id="@+id/battery_level"
android:layout_width="23dp"
android:layout_height="10dp"
android:layout_gravity="center_horizontal"
android:background="@drawable/jz_battery_level_10" />
<TextView
android:id="@+id/video_current_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center_vertical"
android:maxLines="1"
android:textColor="#ffffffff"
android:textSize="12.0sp" />
</LinearLayout>
</RelativeLayout>
<ProgressBar
android:id="@+id/loading"
android:layout_width="@dimen/jz_start_button_w_h_normal"
android:layout_height="@dimen/jz_start_button_w_h_normal"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:indeterminateDrawable="@drawable/jz_loading"
android:visibility="invisible" />
<LinearLayout
android:id="@+id/start_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_gravity="center_vertical">
<ImageView
android:id="@+id/start"
android:layout_width="@dimen/jz_start_button_w_h_normal"
android:layout_height="@dimen/jz_start_button_w_h_normal"
android:src="@drawable/jz_click_play_selector" />
</LinearLayout>
<TextView
android:id="@+id/replay_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/start_layout"
android:layout_centerHorizontal="true"
android:layout_marginTop="6dp"
android:text="@string/replay"
android:textColor="#ffffff"
android:textSize="12sp"
android:visibility="invisible" />
<LinearLayout
android:id="@+id/retry_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/video_loading_faild"
android:textColor="@android:color/white"
android:textSize="14sp" />
<TextView
android:id="@+id/retry_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:background="@drawable/retry_bg"
android:paddingBottom="4dp"
android:paddingLeft="9dp"
android:paddingRight="9dp"
android:paddingTop="4dp"
android:text="@string/click_to_restart"
android:textColor="@android:color/white"
android:textSize="14sp" />
</LinearLayout>
</RelativeLayout>
注意id 不可以变.
Android 视频播放器
Android
1.调用系统播放器,
2.VideoView 结合 MediaController
3.SurfaceView +MediaPlayer
4.第三方视频播放器:UniversalVideoview JiaoZiVideoPlayer (7K+star)...
主要介绍一下JiaoZiVideoPlayer
Manifest:
android:configChanges="orientation|screenSize|keyboardHidden"
1.高度自定义Ui
通过自定义 extends JZVideoPlayerStandard
@Override
public int getLayoutId() {
// return cn.jzvd.R.layout.jz_layout_standard;//默认返回
return R.layout.custom_jzvideo_palyer;//自定义
}
需要注意的是XML资源id不能变,可以修改颜色,添加控件,无ID控件删除.
2.各个阶段的状态
JZVideoPlayerStandard暴露出很多状态方便及时回调,比如:项目里有音乐和视频,要求不能同时播放,在onStatePlaying(视频即将进入播放),可以在这个方法里进行暂停音乐的操作,如果视频需要付费/解锁才能播放,可以在startVideo()这个 方法里进行判断,
3.多尺寸展示
Android 手机屏幕视频一般以16:9为主流.视频的尺寸可以自定义全屏铺满,或者视频原尺寸.
JZVideoPlayerStandard.setVideoImageDisplayType(JZVideoPlayerStandard.FOCUSABLE_AUTO);//原尺寸
这里有很多,关键字Focusable,auto,screen.
可以通过添加ViewOutlineProvider 为播放界面添加圆角.
4.列表滑动小窗//没用到
5.自带重力感应
在你手动设置了会禁掉.
// JZVideoPlayerStandard.FULLSCREEN_ORIENTATION= ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
// JZVideoPlayerStandard.NORMAL_ORIENTATION = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
sensorEventListener = new JZVideoPlayerStandard.JZAutoFullscreenListener();
onResume
Sensor accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(sensorEventListener, accelerometerSensor, SensorManager.SENSOR_DELAY_NORMAL);
@Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(sensorEventListener);
JZVideoPlayer.releaseAllVideos();
}
6.视频缓存 AndroidVideoCache
接入简单.Demo 有例子
7.还提供了JZVideoPlayerManager JZMediaManager 管理类.
JZVideoPlayerManager.getCurrentJzvd();获取当前正在播放的播放器
JZMediaManager.isPlaying();当前是否在播放
//强行暂停!
currentJzvd.onEvent(JZUserAction.ON_CLICK_PAUSE);
JZMediaManager.pause();
currentJzvd.onStatePause();
关于有些地方回调没用
可以在fragment不可见;了然后调
@Override
public void onSupportInvisible() {
super.onSupportInvisible();
JZVideoPlayer.releaseAllVideos();
}
给视频加圆角
videoplayer_spfl.setOutlineProvider(new JzViewOutlineProvider(20));
videoplayer_spfl.setClipToOutline(true);
//可以设计播放页面 圆角
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class JzViewOutlineProvider extends ViewOutlineProvider {
private float mRadius;
public JzViewOutlineProvider(float radius) {
this.mRadius = radius;
}
@Override
public void getOutline(View view, Outline outline) {
// Rect rect = new Rect();
// view.getGlobalVisibleRect(rect);
// int leftMargin = 0;
// int topMargin = 0;
// Rect selfRect = new Rect(leftMargin, topMargin,
// rect.right - rect.left - leftMargin, rect.bottom - rect.top - topMargin);
// outline.setRoundRect(selfRect,mRadius);
outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(),mRadius);
}
}
这里需要注意的是 如果你设置的宽高和视频不对应的话 ,视频顶部会出现黑线,所以这里也是需要动态设置宽高
//动态设置边距
LinearLayout ll_commen_root = helper.getView(R.id.ll_commen_root);
ll_commen_root.setPadding(16,16,16 ,16 );
//注意如果修改XML的话 values-21 也有的
//这里的视频控件高度设置为:宽度*宽高比9:16 因为设置了一个左右边距
videoplayer_spfl.getLayoutParams().height=(ScreenUtils.getScreenWidth()-32)*9/16;
补充: 如果当前列表播放的视频离开了屏幕就会让他关闭
mViewBinding.rvTuijian.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
@Override
public void onChildViewAttachedToWindow(View view) {
}
@Override
public void onChildViewDetachedFromWindow(View view) {
Jzvd jzvd = view.findViewById(R.id.videoplayer_Spfl);
if (jzvd != null && jzvd.jzDataSource.containsTheUrl(JZMediaManager.getCurrentUrl())) {
Jzvd currentJzvd = JzvdMgr.getCurrentJzvd();
if (currentJzvd != null && currentJzvd.currentScreen != Jzvd.SCREEN_WINDOW_FULLSCREEN) {
Jzvd.releaseAllVideos();
}
}
}
});
之前是Rv 中的可以监听,换成scrollview包裹的话
方法:
在播放中添加接口
//非全屏
public interface Ibofang {
void bofang(boolean isbofang, int rvpositon);
}
//在Rv 中的 位置
private int rvpositon;
public void setRvpositon(int rvpositon) {
this.rvpositon = rvpositon;
}
@Override
public void startVideo() {
if (ibofang != null) {
ibofang.bofang(true, rvpositon);
}
@Override
public void release() {
super.release();
if (ibofang != null) {
ibofang.bofang(false, rvpositon);
}
}
在Adapter中绑定
jzvp.setRvpositon(helper.getAdapterPosition());
jzvp.setIbofang(this); //在页面中(frag)进行处理
@Override
public void bofang(boolean isbofang, int rvpositon) {
if (ilistener != null) {
ilistener.listen(isbofang, rvpositon);
}
}
public interface Ilistener {
void listen(boolean isbofang, int rvpositon);
}
public Ilistener ilistener;
public void setIlistener(Ilistener ilistener) {
this.ilistener = ilistener;
}
Fragment中定好参数
boolean mIsbofang = false;
int mRvPosition = 0;
视频播放时会回调
findTuijianAdapter.setIlistener(new FindTuijianAdapter.Ilistener() {
@Override
public void listen(boolean isbofang, int rvpositon) {
mIsbofang = isbofang;
mRvPosition = rvpositon;
}
});
根据坐标的上移下移最后得到监听
int screenHeight = ScreenUtils.getScreenHeight();
//顶部栏
float dimension = getResources().getDimension(R.dimen.x90);
//底部导航
float dimension1 = getResources().getDimension(R.dimen.x110);
//状态栏
int statusBarHeight = BarUtils.getStatusBarHeight();
btm_over = screenHeight - statusBarHeight - dimension1;
mViewBinding.scrollviewFragFind.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
@Override
public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
if (mIsbofang) {
View jzvd = (MyJZVideoPlayerStandard) findTuijianAdapter.getViewByPosition(mViewBinding.rvTuijian, mRvPosition, R.id.jzvp);
int height = jzvd.getLayoutParams().height;
float v1 = height - statusBarHeight - dimension;
// System.out.println(" height :" + height); //553
// System.out.println(" screenHeight :" + screenHeight);// 2340
if (jzvd != null) {
int[] location = new int[2];
jzvd.getLocationInWindow(location);
if (location[1] <= -v1) {
Jzvd.releaseAllVideos();
} else if (location[1] >= btm_over + height - 100) {
Jzvd.releaseAllVideos();
}
}
}
}
});