主要SurfaceView类的介绍
一.SurfaceView:主要用于频繁的更新UI时使用的控件,主要用于播放视频展示画面
SurfaceView和View的区别:
SurfaceView继承自View的 (1)View 主要适用于主动更新的情况,而 surfaceView 主要适用于被动更新,例如频繁的刷新。 (2)View 在主线程中对画面进行刷新,而 surfaceView
通常会通过一个子线程来进行页面的刷新 (3)View 在绘图时没有使用双缓冲机制,而 surfaceView
在底层实现机制上就已经实现了双缓冲机制。总结就是,如果你的自定义 View 需要频繁刷新,或者刷新时数据处理量很大,考虑用 SurfaceView 来替代 View
二.SurfaceView和MediaPlayer播放视频(重点)
三.SurfaceView画各种图形
1.画圆:drawOval
2.画矩形:drawRect
3.画线:drawLine
4.画点:drawPoint
5.画扇形:drawArc
6.画文字:drawText
7.画图片:drawBitmap
8.画路径:drawPath :moveTo LineTo
9.画笔功能:setColor setStrokeWidth setStyle
项目主要需求:
1.完成视频播放功能
2.可以发送弹幕显示到SurfaceView上面
1.加载组件
private void initView() {
surfaceView1=findViewById(R.id.surface_media);
surfaceHolder1=surfaceView1.getHolder();
surfaceHolder1.addCallback(this);
//弹幕
surfaceView2=findViewById(R.id.surface_text);
surfaceHolder2=surfaceView2.getHolder();
surfaceHolder2.addCallback(this);
//设置透明
surfaceView2.setZOrderOnTop(true);
surfaceHolder2.setFormat(PixelFormat.TRANSLUCENT);
button=findViewById(R.id.send);
editText=findViewById(R.id.say_text);
}
2.播放方法
private void initPlayer() throws IOException {
if(mediaPlayer==null){
mediaPlayer=new MediaPlayer();
}
mediaPlayer.reset();
//设置网络资源
mediaPlayer.setDataSource("http://uvideo.spriteapp.cn/video/2019/0512/56488d0a-7465-11e9-b91b-1866daeb0df1_wpd.mp4");
mediaPlayer.prepare();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
}
});
}
3.封装数据源
public class DanMu {
String text;
int height;
int x;
//构造创建默认赋值
//横坐标默认初始值为0
//高给一个随机值
public DanMu(String text) {
this.text = text;
int y=(int)(Math.random()*300+50);//随机的高度
this.height = y;
this.x=0;
}
}
4.动态将字符串添加到集合
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//将字符串添加到集合里
list.add(new DanMu(editText.getText().toString()));
Toast.makeText(DanMuActivity.this, "添加成功", Toast.LENGTH_SHORT).show();
}
});
5.开启绘制线程
boolean flag=true;
@Override
public void surfaceCreated(SurfaceHolder holder) {
if(holder==surfaceHolder1){
mediaPlayer.setDisplay(surfaceHolder1);
}else if(holder==surfaceHolder2){
//弹幕
new Thread(new Runnable() {
@Override
public void run() {
while (flag){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
Paint paint = new Paint();
//设置画笔颜色
paint.setColor(Color.WHITE);
//设置画笔宽度
paint.setStrokeWidth(10);
//设置字体大小
paint.setTextSize(50);
Canvas canvas = surfaceHolder2.lockCanvas();
//不刷白了,刷透明
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
//遍历集合
for(int i=0;i<list.size();i++){
canvas.drawText(list.get(i).text,list.get(i).x+=10,list.get(i).height,paint);
//判断如果弹幕超出屏幕外,将此条弹幕删除
if(list.get(i).x>=surfaceView1.getWidth()){
Log.d("shanchu","删除了:"+list.get(i).text);
list.remove(i);
}
}
surfaceHolder2.unlockCanvasAndPost(canvas);
}
}
}).start();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//在视图销毁的时候,结束线程
flag=false;
}
4.主要效果