饺子视频播放器使用说明
主要特点
- 可以完全自定义UI和任何功能
- 一行代码切换播放引擎,支持的视频格式和协议取决于播放引擎,android.media.MediaPlayer ijkplayer
- 完美检测列表滑动
- 可实现全屏播放,小窗播放
- 能在
ListView
、ViewPager
和ListView
、ViewPager
和Fragment
等多重嵌套模式下全屏工作 - 可以在加载、暂停、播放等各种状态中正常进入全屏和退出全屏
- 多种视频适配屏幕的方式,可铺满全屏,可以全屏剪裁
- 重力感应自动进入全屏
- 全屏后手势修改进度和音量
- Home键退出界面暂停播放,返回界面继续播放
- WebView嵌套本地视频控件
- demo中添加视频缓存的例子
- 倍速播放
集成使用
即便是自定义UI,或者对Library有过修改,把自定义的逻辑写到继承JzvdStd的类中,然后依然通过如下骤调用播放器。
1.添加类库
compile 'cn.jzvd:jiaozivideoplayer:release'
2.添加布局
"match_parent"
android:layout_height="200dp">
"@+id/jz_video"
android:layout_width="match_parent"
android:layout_height="200dp" />
复制代码
3.设置视频地址、缩略图地址、标题
MyJzvdStd jzvdStd = (MyJzvdStd) findViewById(R.id.jz_video);
jzvdStd.setUp("http://jzvd.nathen.cn/c6e3dc12a1154626b3476d9bf3bd7266/6b56c5f0dc31428083757a45764763b0-5287d2089db37e62345123a1be272f8b.mp4"
, "饺子闭眼睛");
jzvdStd.thumbImageView.setImage("http://p.qpic.cn/videoyun/0/2449_43b6f696980311e59ed467f22794e792_1/640");
复制代码
4.在Activity中
@Override
protected void onPause() {
super.onPause();
Jzvd.resetAllVideos();
}
@Override
public void onBackPressed() {
if (Jzvd.backPress()) {
return;
}
super.onBackPressed();
}
复制代码
在AndroidManifest.xml中
".MainActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:screenOrientation="portrait" />
复制代码
在proguard-rules.pro中按需添加
-keep public class cn.jzvd.JZMediaSystem {*; }
-keep public class cn.jzvd.demo.CustomMedia.CustomMedia {*; }
-keep public class cn.jzvd.demo.CustomMedia.JZMediaIjk {*; }
-keep public class cn.jzvd.demo.CustomMedia.JZMediaSystemAssertFolder {*; }
-keep class tv.danmaku.ijk.media.player.** {*; }
-dontwarn tv.danmaku.ijk.media.player.*
-keep interface tv.danmaku.ijk.media.player.** { *; }
复制代码
基本使用
加缩略载图
Glide.with(this).load(Url).into(myJzvdStd.thumbImageView); //推荐使用Glide
复制代码
自动播放
自动播放有两种 这里随便选择添加一个,
1. myJzvdStd.startButton.performClick();
2. myJzvdStd.startVideo();
复制代码
跳转制定位置播放
//这里只有开始播放时才生效
mJzvdStd.seekToInAdvance = 20000;
复制代码
2.播放sd卡下视频
mJzvdStd.setUp(Environment.getExternalStorageDirectory().getAbsolutePath() + "/DCIM/Camera/local_video.mp4", "饺子不信", Jzvd.SCREEN_NORMAL);
这里很多人问为什么播不了,请认真怒url,播不了就是url没怒对
复制代码
播放assets目录下的视频
复制Demo中JZMediaSystemAssertFolder类到你的项目下
----------------------------------------------------------------------------
JZDataSource jzDataSource = null;
try {
jzDataSource = new JZDataSource(getAssets().openFd("local_video.mp4"));
jzDataSource.title = "饺子快长大";
} catch (IOException e) {
e.printStackTrace();
}
jzvdStd.setUp(jzDataSource, JzvdStd.SCREEN_NORMAL, JZMediaSystemAssertFolder.class);
复制代码
直接全屏播放
JzvdStd.startFullscreenDirectly(this, JzvdStd.class, VideoConstant.videoUrlList[6], "饺子辛苦了");
复制代码
开启小窗播放
mJzvdStd.gotoScreenTiny();
复制代码
列表Item划出开启小窗播放
1.Listview
//划出屏幕暂停
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (Jzvd.CURRENT_JZVD == null) return;
int lastVisibleItem = firstVisibleItem + visibleItemCount;
int currentPlayPosition = Jzvd.CURRENT_JZVD.positionInList;
// Log.e(TAG, "onScrollReleaseAllVideos: " +
// currentPlayPosition + " " + firstVisibleItem + " " + currentPlayPosition + " " + lastVisibleItem);
if (currentPlayPosition >= 0) {
if ((currentPlayPosition < firstVisibleItem || currentPlayPosition > (lastVisibleItem - 1))) {
if (Jzvd.CURRENT_JZVD.screen != Jzvd.SCREEN_FULLSCREEN) {
Jzvd.resetAllVideos();//为什么最后一个视频横屏会调用这个,其他地方不会
}
}
}
}
});
2. RecyclerView 划出列表开启小窗
recyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
@Override
public void onChildViewAttachedToWindow(View view) {//这个的本质是gotoThisJzvd,不管他是不是原来的容器
//如果这个容器中jzvd的url是currentJzvd的url,那么直接回到这里,不用管其他的
JzvdStdTinyWindow jzvd = view.findViewById(R.id.videoplayer);
JzvdStdTinyWindow currentJzvd = (JzvdStdTinyWindow) Jzvd.CURRENT_JZVD;
if (jzvd != null && currentJzvd != null &&
jzvd.jzDataSource.containsTheUrl(Jzvd.CURRENT_JZVD.jzDataSource.getCurrentUrl())
&& Jzvd.CURRENT_JZVD.state == Jzvd.STATE_PLAYING) {
ViewGroup vp = (ViewGroup) jzvd.getParent();
vp.removeAllViews();
((ViewGroup) currentJzvd.getParent()).removeView(currentJzvd);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
vp.addView(currentJzvd, lp);
currentJzvd.setScreenNormal();
Jzvd.CONTAINER_LIST.pop();
}
}
@Override
public void onChildViewDetachedFromWindow(View view) {
JzvdStdTinyWindow jzvd = view.findViewById(R.id.videoplayer);
if (jzvd != null && Jzvd.CURRENT_JZVD != null &&
jzvd.jzDataSource.containsTheUrl(Jzvd.CURRENT_JZVD.jzDataSource.getCurrentUrl())
&& Jzvd.CURRENT_JZVD.screen != Jzvd.SCREEN_TINY) {
if (Jzvd.CURRENT_JZVD.state == Jzvd.STATE_PAUSE) {
Jzvd.resetAllVideos();
} else {
((JzvdStdTinyWindow) Jzvd.CURRENT_JZVD).gotoScreenTiny();
}
}
}
});
2.1 RecyclerView划出屏幕释放JZ,同时也是不开启列表划出显示小窗
recyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
@Override
public void onChildViewAttachedToWindow(View view) {
}
@Override
public void onChildViewDetachedFromWindow(View view) {
Jzvd jzvd = view.findViewById(R.id.videoplayer);
if (jzvd != null && Jzvd.CURRENT_JZVD != null &&
jzvd.jzDataSource.containsTheUrl(Jzvd.CURRENT_JZVD.jzDataSource.getCurrentUrl())) {
if (Jzvd.CURRENT_JZVD != null && Jzvd.CURRENT_JZVD.screen != Jzvd.SCREEN_FULLSCREEN) {
Jzvd.resetAllVideos();
}
}
}
});
复制代码
小屏播放无声音,全屏有声音
创建一个类继承JzvdStd并在XML设置
public class JzvdStdVolumeAfterFullscreen extends JzvdStd {
public JzvdStdVolumeAfterFullscreen(Context context) {
super(context);
}
public JzvdStdVolumeAfterFullscreen(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onPrepared() {
super.onPrepared();
if (screen == SCREEN_FULLSCREEN) {
mediaInterface.setVolume(1f, 1f);
} else {
mediaInterface.setVolume(0f, 0f);
}
}
/**
* 进入全屏模式的时候关闭静音模式
*/
@Override
public void gotoScreenFullscreen() {
super.gotoScreenFullscreen();
}
@Override
public void setScreenFullscreen() {
super.setScreenFullscreen();
if (mediaInterface != null)
mediaInterface.setVolume(1f, 1f);
}
@Override
public void setScreenNormal() {
super.setScreenNormal();
if (mediaInterface != null)
mediaInterface.setVolume(0f, 0f);
}
}
复制代码
全屏状态播放完成,不退出全屏
创建一个类继承JzvdStd并在XML设置
public class JzvdStdAutoCompleteAfterFullscreen extends JzvdStd {
public JzvdStdAutoCompleteAfterFullscreen(Context context) {
super(context);
}
public JzvdStdAutoCompleteAfterFullscreen(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void startVideo() {
if (screen == SCREEN_FULLSCREEN) {
Log.d(TAG, "startVideo [" + this.hashCode() + "] ");
JZMediaInterface.SAVED_SURFACE = null;
addTextureView();
AudioManager mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
mAudioManager.requestAudioFocus(onAudioFocusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
JZUtils.scanForActivity(getContext()).getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// JZMediaPlayer.instance().positionInList = positionInList;
onStatePreparing();
} else {
super.startVideo();
}
}
@Override
public void onAutoCompletion() {
if (screen == SCREEN_FULLSCREEN) {
onStateAutoComplete();
} else {
super.onAutoCompletion();
}
}
}
复制代码
播放MP3
public class JzvdStdMp3 extends JzvdStd {
public JzvdStdMp3(Context context) {
super(context);
}
public JzvdStdMp3(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public int getLayoutId() {
return R.layout.jz_layout_standard_mp3;
}
@Override
public void onClick(View v) {
if (v.getId() == cn.jzvd.R.id.thumb &&
(state == STATE_PLAYING ||
state == STATE_PAUSE)) {
onClickUiToggle();
} else if (v.getId() == R.id.fullscreen) {
} else {
super.onClick(v);
}
}
//changeUiTo 真能能修改ui的方法
@Override
public void changeUiToNormal() {
super.changeUiToNormal();
}
@Override
public void changeUiToPreparing() {
super.changeUiToPreparing();
}
@Override
public void changeUiToPlayingShow() {
super.changeUiToPlayingShow();
thumbImageView.setVisibility(View.VISIBLE);
}
@Override
public void changeUiToPlayingClear() {
super.changeUiToPlayingClear();
thumbImageView.setVisibility(View.VISIBLE);
}
@Override
public void changeUiToPauseShow() {
super.changeUiToPauseShow();
thumbImageView.setVisibility(View.VISIBLE);
}
@Override
public void changeUiToPauseClear() {
super.changeUiToPauseClear();
thumbImageView.setVisibility(View.VISIBLE);
}
@Override
public void changeUiToComplete() {
super.changeUiToComplete();
}
@Override
public void changeUiToError() {
super.changeUiToError();
}
}
复制代码
播放完成不显示预览图
public class JzvdStdShowTextureViewAfterAutoComplete extends JzvdStd {
public JzvdStdShowTextureViewAfterAutoComplete(Context context) {
super(context);
}
public JzvdStdShowTextureViewAfterAutoComplete(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onAutoCompletion() {
super.onAutoCompletion();
thumbImageView.setVisibility(View.GONE);
}
}
复制代码
Home键退出界面暂停播放,返回界面继续播放
@Override
protected void onResume() {
super.onResume();
//home back
JzvdStd.goOnPlayOnResume();
}
@Override
protected void onPause() {
super.onPause();
// Jzvd.clearSavedProgress(this, null);
//home back
JzvdStd.goOnPlayOnPause();
}
复制代码
边播边缓存和清晰度切换
1. 集成videocache implementation 'com.danikula:videocache:2.7.0',并初始化
public class ApplicationDemo extends Application {
@Override
public void onCreate() {
super.onCreate();
// LeakCanary.install(this);
}
private HttpProxyCacheServer proxy;
public static HttpProxyCacheServer getProxy(Context context) {
ApplicationDemo app = (ApplicationDemo) context.getApplicationContext();
return app.proxy == null ? (app.proxy = app.newProxy()) : app.proxy;
}
private HttpProxyCacheServer newProxy() {
return new HttpProxyCacheServer(this);
}
}
2.引用
LinkedHashMap map = new LinkedHashMap();
String proxyUrl = ApplicationDemo.getProxy(this).getProxyUrl(VideoConstant.videoUrls[0][9]);
map.put("高清", proxyUrl);
map.put("标清", VideoConstant.videoUrls[0][6]);
map.put("普清", VideoConstant.videoUrlList[0]);
JZDataSource jzDataSource = new JZDataSource(map, "饺子不信");
jzDataSource.looping = true;
jzDataSource.currentUrlIndex = 2;
jzDataSource.headerMap.put("key", "value");//header 这里可以加请求头 mediaplayer
mJzvdStd.setUp(jzDataSource
, JzvdStd.SCREEN_NORMAL);
Glide.with(this).load(VideoConstant.videoThumbList[0]).into(mJzvdStd.thumbImageView);
复制代码
重复播放
创建一个类集成JzvdStd并在XML设置
public class JZVideoPlayerStandardLoopVideo extends JzvdStd{
public JZVideoPlayerStandardLoopVideo (Context context) {
super(context);
}
public JZVideoPlayerStandardLoopVideo (Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onAutoCompletion() {
super.onAutoCompletion();
startVideo(); //播放完成开启自动播放 这里选择 startVideo();
}
}
还有一种方法就是上面清晰度切换loop循环标志
复制代码
重力感应自动进入全屏
SensorManager mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
Jzvd.JZAutoFullscreenListener mSensorEventListener = new Jzvd.JZAutoFullscreenListener();
@Override
protected void onResume() {
super.onResume();
Sensor accelerometerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(mSensorEventListener, accelerometerSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(mSensorEventListener);
}
复制代码
重力感应
Jzvd.FULLSCREEN_ORIENTATION=ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
Jzvd.NORMAL_ORIENTATION = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
两个变量控制全屏前后的屏幕方向
复制代码
不保存播放进度
Jzvd.SAVE_PROGRESS = false;
复制代码
取消播放时在非WIFIDialog提示
Jzvd.WIFI_TIP_DIALOG_SHOWED=true;
复制代码
清除某个URL进度
Jzvd.clearSavedProgress(this, "url");
复制代码
切换播放内核
ijk
复制Demo中JZMediaIjk类到你的项目下 //记着SO
implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.4'
implementation 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.4'
jzvdStd.setUp("http://jzvd.nathen.cn/342a5f7ef6124a4a8faf00e738b8bee4/cf6d9db0bd4d41f59d09ea0a81e918fd-5287d2089db37e62345123a1be272f8b.mp4"
, "饺子快长大", JzvdStd.SCREEN_NORMAL, JZMediaIjk.class); // ijkMediaPlayer
Mediaplayer
jzvdStd.setUp("http://jzvd.nathen.cn/342a5f7ef6124a4a8faf00e738b8bee4/cf6d9db0bd4d41f59d09ea0a81e918fd-5287d2089db37e62345123a1be272f8b.mp4"
, "饺子快长大", JzvdStd.SCREEN_NORMAL, JZMediaSystem.class);
exo
复制Demo中JZMediaExo类到你的项目下
implementation 'com.google.android.exoplayer:exoplayer:2.7.1'
jzvdStd.setUp("http://jzvd.nathen.cn/342a5f7ef6124a4a8faf00e738b8bee4/cf6d9db0bd4d41f59d09ea0a81e918fd-5287d2089db37e62345123a1be272f8b.mp4"
, "饺子快长大", JzvdStd.SCREEN_NORMAL, JZMediaExo.class); //exo
复制代码
##相关函数回调,屏幕状态,播放器状态,事件 #####继承JzvdStd之后,可以通过父类的mCurrentState,取得当前的播放状态。
- CURRENT_STATE_IDLE 未知状态,指控件被new出来之后什么都没做
- CURRENT_STATE_NORMAL 普通状态
- CURRENT_STATE_PREPARING 视频准备状态
- CURRENT_STATE_PREPARING_CHANGING_URL 播放中切换url的准备状态
- CURRENT_STATE_PLAYING 播放中状态
- CURRENT_STATE_PAUSE 暂停状态
- CURRENT_STATE_AUTO_COMPLETE 自动播放完成状态
- CURRENT_STATE_ERROR 错误状态
复写进入播放状态的函数,取得播放状态的回调
- onStateNormal 进入普通状态,通常指setUp之后
- onStatePreparing 进入准备中状态,就是loading状态
- onStatePlaying 进入播放状态
- onStatePause 进入暂停状态
- onStateError 进入错误状态
- onStateAutoComplete 进入自动播放完成状态
了解当前屏幕类型
全屏、小窗、非全屏分别是不同的实例,在继承JzvdStd后,通过mCurrentScreen变量,取得当前屏幕类型
- SCREEN_WINDOW_NORMAL 普通窗口(进入全屏之前的)
- SCREEN_WINDOW_LIST 列表窗口(进入全屏之前)
- SCREEN_WINDOW_FULLSCREEN 全屏
- SCREEN_WINDOW_TINY 小窗 ####事件
- 复写onProgress函数,取得每次播放器设置底部seekBar的进度回调
- 调用changeUrl函数,切换url
- 复写onClick函数,取得各种按钮的点击事件
- 复写onTouch函数,取得全屏之后的手势操作
自定义相关 详细请看类说明
/**
* 事件回调,相关操作,请参考上面的相关函数回调,屏幕状态,播放器状态,事件来,实现你的逻辑
*/
public class cxw extends JzvdStd {
private Button button;
public cxw(Context context) {
super(context);
}
public cxw(Context context, AttributeSet attrs) {
super(context, attrs);
}
//-----------------------增加某个控件-----------------------------------------//
@Override
public int getLayoutId() {
return R.layout.jz_layout_std; //复制DEMO下的jz_layout_std(可以重命名,但不能删除控件或修改控件的ID) 增加你想要的控件
}
@Override
public void init(Context context) {
super.init(context);
button = findViewById(R.id.button); //获取添加的控件
button.setOnClickListener(this); //给控件设置监听回调 这一步很重要不然没法响应点击事件
}
@Override
public void onClick(View v) {
//这里可以在父类之前获取你想要点击控件之间做的时
super.onClick(v);
if (v.getId() == R.id.button) {
//点击button事件 响应
}
}
//-----------------------UI 修改 显隐---------------------------------------//
// 比如说 你想在某个状态影藏控件 就复写下面的函数 做显隐
// 控件查找参考 Jzvd 和JzvdStd 类 找到你想要显隐 的控件实例名
@Override
public void changeUiToPlayingShow() { //这里是播放的时候点击屏幕出现的UI
super.changeUiToPlayingShow();
}
@Override
public void changeUiToPlayingClear() { //这里是播放的时候屏幕上面UI消失 只显示下面底部的进度条UI
super.changeUiToPlayingClear();
}
@Override
public void changeUiToPauseShow() { //这里是暂停的时候屏幕出现的UI
super.changeUiToPauseShow();
}
@Override
public void changeUiToPauseClear() { //这里是暂停的时候点击屏幕消失的UI 只显示下面底部的进度条UI
super.changeUiToPauseClear();
}
@Override
public void changeUiToComplete() { //这里是播放完成显示的UI
super.changeUiToComplete();
}
@Override
public void changeUiToError() { //这里是出错的UI
super.changeUiToError();
}
@Override
public void changeUiToNormal() { //这里是Normal UI
super.changeUiToNormal();
}
@Override
public void changeUiToPreparing() { //这里是 Preparing 的UI
super.changeUiToPreparing();
loadingProgressBar.setVisibility(GONE); //这里 我影藏 Preparing 时 加载的圆圈进度
}
}
复制代码
##常见问题 视频有声音,无画面
- 开启硬件加速
关于播放直播流,m3u8
- 是否支持播放取决于播放内核,如果该内核不能播放,请切换内核,或者自己编译Ijk 让他支持。
获取视频某一帧
/**
* context 上下文
* uri 视频地址
* imageView 设置image
* frameTimeMicros 获取某一时间帧
*/
public static void loadVideoScreenshot(final Context context, String uri, ImageView imageView, long frameTimeMicros) {
RequestOptions requestOptions = RequestOptions.frameOf(frameTimeMicros);
requestOptions.set(FRAME_OPTION, MediaMetadataRetriever.OPTION_CLOSEST);
requestOptions.transform(new BitmapTransformation() {
@Override
protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
return toTransform;
}
@Override
public void updateDiskCacheKey(MessageDigest messageDigest) {
try {
messageDigest.update((context.getPackageName() + "RotateTransform").getBytes("utf-8"));
} catch (Exception e) {
e.printStackTrace();
}
}
});
Glide.with(context).load(uri).apply(requestOptions).into(imageView);
}
复制代码
视频圆角
ViewOutlineProvider (注:该类是5.0的特性,低于5.0没效果,如果要适配5.0以下这里给出一个思路.9图遮罩)
创建一个类继承ViewOutLineProvider 实现改该方法
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);
Rect selfRect = new Rect(0, 0,
view.getWeight(),view.getHeight());
outline.setRoundRect(selfRect,mRadius);
}
}
mJzvdStd.setOutlineProvider(new JzViewOutlineProvider(radius));
mJzvdStd.setClipToOutline(true);
复制代码
点击全屏按钮闪退,报错空指针
- 检查是否正确按照基本使用在manifest中配置。Activity是否继承自AppCompatActivity
".xxxxxxxActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:screenOrientation="portrait" />
复制代码
视屏宽高不填充屏幕,有黑边
Jzvd.setTextureViewRotation(90); //视频旋转90度
根据自己情况选择一个 填充
Jzvd.setVideoImageDisplayType(Jzvd.VIDEO_IMAGE_DISPLAY_TYPE_FILL_PARENT);
Jzvd.setVideoImageDisplayType(Jzvd.VIDEO_IMAGE_DISPLAY_TYPE_FILL_SCROP);
Jzvd.setVideoImageDisplayType(Jzvd.VIDEO_IMAGE_DISPLAY_TYPE_ORIGINAL); //原始大小
复制代码
背景高斯模糊
- 以module的形式导入项目,在jz_layout_standard.xml 的布局下添加一个Imageview
"@+id/surface_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
"@+id/iv"
android:layout_width="match_parent"
android:layout_height="match_parent" />
这里我为了方便重写了Imageview 使他宽填充屏幕宽,这里怎么简单怎么来想进一切办法让他填充满宽度
复制代码
在JzvdStd类下的init 方法里面获取上面的Imageview控件,好了到此就完了,然后在设置缩略图的下面用能高斯模糊的方法设置就OK,下面是我的做法你可以根据你自己来。
myJzvdStd.setUp("http://jzvd.nathen.cn/342a5f7ef6124a4a8faf00e738b8bee4/cf6d9db0bd4d41f59d09ea0a81e918fd-5287d2089db37e62345123a1be272f8b.mp4"
, "饺子快长大", JzvdStd.SCREEN_WINDOW_NORMAL);
Glide.with(this).load("http://jzvd-pic.nathen.cn/jzvd-pic/1bb2ebbe-140d-4e2e-abd2-9e7e564f71ac.png").into(myJzvdStd.thumbImageView);
Jzvd.setJzUserAction(new MyUserActionStd());
Glide.with(ActivityMain.this)
.load("http://t2.hddhhn.com/uploads/tu/201810/9999/9139710e12.jpg")
.dontAnimate()
// 设置高斯模糊
.bitmapTransform(new BlurTransformation(this, 14, 5))
.into(myJzvdStd.mFrameLayout);
复制代码
ViewPager翻页视频还在播放
@Override
public void onPageSelected(int position) {
Jzvd.resetAllVideos();
}
复制代码
视频一直在loading中
- 检查链接是否是Https或手机版本是否是9.0因为9.0不支持http
- 是否添加了网络权限
- 是否该内核支持该视频流
- 把链接放demo中,看能否播放,如果以上三步没问题不能播放请上github提issuse