最近在做视频播,项目不是专门的视频播放器类软件,其中有小窗口视频播放功能,之前做的看了下好多bug,更有个严重问题,视频拉伸严重,和不能全屏切换全屏播放(全屏播放需求暂时没有提,但我肯定老板后续肯定会提出这个需求的)。看着之前人写的一个类里2000多行代码又是各种的嵌套自定义接口瞬间觉得为了自己还是打算重新定义个视频播放器来的好点。
这里说下JieCaoVideoPlayer
主要特点
视频全屏播放和浮层小窗播放
可以完全自定义UI
能在ListView、ViewPager和ListView、ViewPager和Fragment等多重嵌套模式下全屏工作
手势修改进度和音量
视频大小的屏幕适配,宽或长至少有两个对边是充满屏幕的,另外两个方向居中
可以在加载、暂停、播放等各种状态中正常进入全屏和退出全屏
重力感应自动全屏
WebView嵌套本地视频控件
支持https和rtsp
小于 100kb
使用也很简单 添加依赖
compile ‘fm.jiecao:jiecaovideoplayer:5.5.4’
然后
<fm.jiecao.jcvideoplayer_lib.JCVideoPlayerStandard
android:id="@+id/videoplayer"
android:layout_width="match_parent"
android:layout_height="200dp"/>
调用
JCVideoPlayerStandard jcVideoPlayerStandard = (JCVideoPlayerStandard) findViewById(R.id.videoplayer);
jcVideoPlayerStandard.setUp(
"http://2449.vod.myqcloud.com/2449_22ca37a6ea9011e5acaaf51d105342e3.f20.mp4" , JCVideoPlayerStandard.SCREEN_LAYOUT_NORMAL,
"嫂子闭眼睛");
jcVideoPlayerStandard.thumbImageView.setImage(
"http://p.qpic.cn/videoyun/0/2449_43b6f696980311e59ed467f22794e792_1/640");
这里我看到这个setImage方法可能打不出来,其实可以替代的方法也很多。
例如
Picasso.with(this)
.load("http://img4.jiecaojingxuan.com/2016/11/23/00b026e7-b830-4994-bc87-38f4033806a6.jpg@!640_360")
.into(mJcVideoPlayerStandard.thumbImageView);
在Activity中
@Override
public void onBackPressed() {
if (JCVideoPlayer.backPress()) {
return;
}
super.onBackPressed();
}
@Override
protected void onPause() {
super.onPause();
JCVideoPlayer.releaseAllVideos();
}
在AndroidManifest.xml中
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:screenOrientation="portrait" /> <!-- or android:screenOrientation="landscape"-->
最后记得添加权限哦
=====================================================
下来重点说下自定义UI
1.下载jcvideoplayer-lib依赖,添加进自己的项目中。注意和项目中的版本号一直,否则会报错。
2.自定义JCVideoPlayerStandard类,
其中有个getLayoutId()方法
@Override
public int getLayoutId() {
return R.layout.jc_layout_standard;
}
这个返回的布局就是我们要自定义的布局文件。
这里我给出我的定义的布局文件,由于暂时用不到切换到全功能所以我把全屏功能隐藏了。
<?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="@android:color/black"
android:descendantFocusability="blocksDescendants">
<FrameLayout
android:id="@+id/surface_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
<ImageView
android:id="@+id/thumb"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:background="#000000"
android:scaleType="fitCenter" />
<RelativeLayout
android:id="@+id/layout_top"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="@drawable/media_tool_bg1"
android:gravity="center_vertical">
<ImageView
android:id="@+id/back"
android:layout_width="23dp"
android:layout_height="match_parent"
android:paddingLeft="14dp"
android:scaleType="centerInside"
android:visibility="visible"
android:src="@drawable/jc_click_back_selector" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:layout_toRightOf="@+id/back"
android:layout_centerVertical="true"
android:textColor="@android:color/white"
android:textSize="18sp" />
<ImageView
android:id="@+id/video_iv_lock_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="10dp"
android:src="@drawable/selector_btn_lock_close"
android:visibility="visible" />
</RelativeLayout>
<LinearLayout
android:id="@+id/layout_bottom"
android:layout_width="match_parent"
android:layout_height="55dp"
android:layout_alignParentBottom="true"
android:background="@drawable/media_tool_bg1"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="visible">
<ImageView
android:id="@+id/start"
android:layout_width="@dimen/jc_start_button_w_h_normal"
android:layout_height="@dimen/jc_start_button_w_h_normal"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_gravity="center_vertical"
android:src="@drawable/jc_click_play_selector" />
<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="1.0dip"
android:minHeight="1.0dip"
android:paddingBottom="8dp"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:paddingTop="8dp"
android:progressDrawable="@drawable/jc_bottom_seek_progress"
android:thumb="@drawable/jc_bottom_seek_thumb" />
<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" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="/"
android:textColor="#ffffff"/>
<TextView
android:id="@+id/total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00"
android:textColor="#ffffff"
android:layout_marginRight="14dp"/>
<!--全屏-->
<ImageView
android:id="@+id/fullscreen"
android:layout_width="24.5dp"
android:layout_height="fill_parent"
android:layout_marginLeft="14.0dip"
android:layout_marginRight="14.0dip"
android:scaleType="centerInside"
android:visibility="gone"
android:src="@drawable/jc_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/jc_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/jc_click_back_tiny_selector"
android:visibility="visible" />
<ProgressBar
android:id="@+id/loading"
android:layout_width="@dimen/jc_start_button_w_h_normal"
android:layout_height="@dimen/jc_start_button_w_h_normal"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:indeterminateDrawable="@drawable/jc_loading"
android:visibility="invisible" />
</RelativeLayout>
对应ID可以参考JCVideoPlayer中的init方法中的对应id因为JCVideoPlayerStandard是继承JCVideoPlayer的,所以JCVideoPlayer中findViewById过得空间在JCVideoPlayerStandard中不必再重复初始化了
public void init(Context context) {
View.inflate(context, getLayoutId(), this);
startButton = (ImageView) findViewById(R.id.start);//开始
fullscreenButton = (ImageView) findViewById(R.id.fullscreen);//全屏
progressBar = (SeekBar) findViewById(R.id.bottom_seek_progress);//进度条
currentTimeTextView = (TextView) findViewById(R.id.current);//当前时长
totalTimeTextView = (TextView) findViewById(R.id.total);//总时间
bottomContainer = (ViewGroup) findViewById(R.id.layout_bottom);//下方layout
textureViewContainer = (ViewGroup) findViewById(R.id.surface_container);//SurfaceView的容器
topContainer = (ViewGroup) findViewById(R.id.layout_top);//上方layout
startButton.setOnClickListener(this);
fullscreenButton.setOnClickListener(this);
progressBar.setOnSeekBarChangeListener(this);
bottomContainer.setOnClickListener(this);
textureViewContainer.setOnClickListener(this);
textureViewContainer.setOnTouchListener(this);
mScreenWidth = getContext().getResources().getDisplayMetrics().widthPixels;
mScreenHeight = getContext().getResources().getDisplayMetrics().heightPixels;
mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
mHandler = new Handler();
}
这里需要注意的是 id一定要和其中的保持一致。结合官网给出的一些做法
参照JCVideoPlayerSimple,JCVideoPlayerStandard,JCVideoPlayerStandardWithShareButton
继承JCVideoPlayer,JCVideoPlayer中包含所有关于播放的代码,不包含任何UI的代码
getLayoutId();布局的id
Override init(Context context);这里初始化自定义控件
Override setStateAndUi(int state);是重点,自定义各个状态的UI,如果在其他地方修改UI应该保持谨慎
Override onTouch(),onClick();如果有需要
在自定义UI之后,应该依然按照README.md中的4步骤来调用播放器
关于控件id的问题,在Base simple ui example中的所有最基础的id是写死在JCVideoPlayer中的,下面的控件id已经findViewById过了不需要再findViewById控件 id
开始按钮 start
全屏按钮 fullscreen
进度条 progress
总共时间 total
下方layout layout_bottom
上方layout layout_top
SurfaceView的容器 surface_container
如果想快速的集成视频播放功能,建议参照JCVideoPlayerStandardWithShareButton来做,它继承JCVideoPlayerStandard,JCVideoPlayerStandard的目标是和今日头条的细节保持一致
如果想完全自定义UI,参照JCVideoPlayerStandard
我的自定义出来的效果图就是
时间不早了,回头我会上传源码,今天就介绍到这里
源码