废话不多说:
通过监听vp的滑动位置,以及vp对应位置的root view,以代码动态添加,移除的方式,实现videoview的插入与移除,实现播放功能。
–因为videoview在布局中直接使用,会直接持有了activity的对象导致内存泄漏,所以通过代码动态添加来实现。
/**
* 创建video view
*/
public VideoView Builder(Context context, ViewGroup mPlayerRoot) {
Context applicationContext = context.getApplicationContext();
VideoView mPlayView = new VideoView(applicationContext);
mPlayerRoot.addView(mPlayView);
ViewGroup.LayoutParams params = mPlayView.getLayoutParams();
params.width = LinearLayout.LayoutParams.MATCH_PARENT;
params.height = LinearLayout.LayoutParams.MATCH_PARENT;
mPlayView.setLayoutParams(params);
MediaController mediaController = new MediaController(context);
mediaController.setVisibility(View.INVISIBLE);
mPlayView.setMediaController(mediaController);
return mPlayView;
}
/**
* 释放video view
*/
public void releaseVideoView(VideoView mPlayView) {
try {
mPlayView.stopPlayback();
mPlayView.suspend();
mPlayView.setOnErrorListener(null);
mPlayView.setOnPreparedListener(null);
mPlayView.setOnCompletionListener(null);
mPlayView.setMediaController(null);
} catch (Exception e) {
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VYraU3VJ-1648365008819)(https://upload-images.jianshu.io/upload_images/13738977-8e42d7acf5f38120.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]
通过自定义的videoview,可以定义设计稿上面的相关控件。这里使用的是代码动态添加view的方式。当然还可以自定义一个xml插入,这里就不过多叙述。要注意的是,videoview的添加or移除需要以代码的形式。核心代码如下:
/**
* add view
*/
public void addToParent(LinearLayout root) {
root.removeAllViews();
root.addView(this);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) this.getLayoutParams();
params.width = LinearLayout.LayoutParams.MATCH_PARENT;
params.height = LinearLayout.LayoutParams.MATCH_PARENT;
setLayoutParams(params);
//在把video view添加到该view
mPlayView = VideoBuilder.getInstance().Builder(getContext(), this);
RelativeLayout.LayoutParams layoutParams = (LayoutParams) mPlayView.getLayoutParams();
layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
mPlayView.setLayoutParams(layoutParams);
//把播放按钮设置到view
mPlayBt = new ImageView(getContext());
addView(mPlayBt);
RelativeLayout.LayoutParams btLayoutParams = (LayoutParams) mPlayBt.getLayoutParams();
btLayoutParams.width = 80;
btLayoutParams.height = 80;
btLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
mPlayBt.setLayoutParams(btLayoutParams);
//设置默认图片
mPlayBt.setImageResource(mPlayRes);
//监听事件---------------------------------------------------------------------------------
mPlayView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
mPlayProgress = 0;
updatePlayUI(false);
return true;
}
});
mPlayView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mPlayProgress = 0;
updatePlayUI(false);
}
});
mPlayBt.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mPlayView == null) {
return;
}
if (mPlayView.isPlaying()) {
mPlayView.pause();
mPlayProgress = mPlayView.getCurrentPosition();
updatePlayUI(false);
}else{
mPlayView.seekTo(mPlayProgress);
mPlayView.start();
updatePlayUI(true);
}
}
});
}
调用就相对简单了,监听到播放的事件后,直接new一个自定义videoview的对象,然后插入对应的vp布局。再者,当vp从当前位置滑动后,移除相关的view。而对于vp的布局对象,可以用一个list缓存,当界面销毁的时候,记得及时移除,不然会导致内存泄漏。调用代码如下:
package com.north.light.androidutils.viewpagervideo;
import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.VideoView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.PagerAdapter;
import com.north.light.androidutils.R;
import com.north.light.androidutils.log.LogUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* viewpager播放video
*/
public class ViewPagerVideoActivity extends AppCompatActivity {
private CusViewPager page1;
private Map viewMap = new HashMap<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_pager_video);
init();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
private void init() {
List viewList = new ArrayList<>();
for (int i = 0; i < 12; i++) {
View cacheView = View.inflate(ViewPagerVideoActivity.this, R.layout.viewpager_item, null);
viewList.add(cacheView);
}
CusPagerAdapter adapter = new CusPagerAdapter(ViewPagerVideoActivity.this, viewList);
page1 = findViewById(R.id.activity_view_pager_video_content);
page1.setAdapter(adapter);
page1.setPageListener(new CusViewPager.PageListener() {
@Override
public void pageChange(int oldPos, int newPos) {
LogUtil.d("pageChange old pos:" + oldPos + " new pos:" + newPos);
LinearLayout root = viewMap.get(oldPos);
if (root == null) {
return;
}
root.removeAllViews();
}
});
}
private class CusPagerAdapter extends PagerAdapter {
private Context context;
private List viewList = new ArrayList<>();
public CusPagerAdapter(Context context, List viewList) {
this.context = context;
this.viewList = viewList;
}
@Override
public int getCount() {
return viewList.size();
}
@Override
public boolean isViewFromObject(@NonNull @NotNull View view, @NonNull @NotNull Object object) {
return view == object;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
viewMap.remove(position);
container.removeView((View) object);
}
@NotNull
@Override
public Object instantiateItem(@NonNull @NotNull ViewGroup container, int position) {
View root = viewList.get(position);
container.addView(root);
TextView tx = root.findViewById(R.id.viewpager_item_tx);
LinearLayout mVideoRoot = root.findViewById(R.id.viewpager_item_video_root);
tx.setText(String.valueOf(position));
viewMap.put(position, mVideoRoot);
tx.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (position == 1) {
tx.setBackgroundColor(getResources().getColor(R.color.colorAccent));
} else if (position == 2) {
tx.setBackgroundColor(getResources().getColor(R.color.colorPrimaryDark));
} else if (position == 3) {
tx.setBackgroundColor(getResources().getColor(R.color.color_F06091));
} else if (position == 4) {
tx.setBackgroundColor(getResources().getColor(R.color.color_a8a8a8));
} else {
tx.setBackgroundColor(getResources().getColor(R.color.blue_light));
}
dealClickInfo(position);
}
});
return viewList.get(position);
}
}
/**
* 处理点击事件
*/
private void dealClickInfo(int position) {
LinearLayout root = viewMap.get(position);
if (root == null) {
return;
}
CusVideoView videoView = new CusVideoView(this);
videoView.setPlayRes(R.mipmap.ic_heart1,R.mipmap.ic_heart_sel);
videoView.addToParent(root);
if (position % 2 == 1) {
String path1 = Environment.getExternalStorageDirectory().getPath() +
"/DCIM/Camera/share_893adea390ed3b7a0f2da1223092a3ef.mp4";
videoView.play(path1);
} else if (position % 2 == 0) {
String path2 = Environment.getExternalStorageDirectory().getPath() +
"/DCIM/Camera/share_adb4ba0e521ba0003e0ab7ca98843738.mp4";
videoView.play(path2);
} else {
String path3 = Environment.getExternalStorageDirectory().getPath() +
"/DCIM/Camera/share_adb4ba0e521ba0003e0ab7ca98843738.mp4";
videoView.play(path3);
}
}
}
代码地址
that’s all----------------------------------------------------------------------------------