SurfaceView
SurfaceView 的使用场景
1.播放视频
2.发送弹幕,画板功能
3.绘制滚动图形(点,线,圆等)
特点
频繁更新UI,双缓冲机制
通常情况程序的View和用户响应都是在同一个线程中处理的,这也是为什么处理长时间事件(例如访问网络)需要放到另外的线程中去(防止阻塞当前UI线程的操作和绘制)。但是在其他线程中却不能修改UI元素,例如用后台线程更新自定义View(调用View的在自定义View中的onDraw函数)是不允许的。
如果需要在另外的线程绘制界面、需要迅速的更新界面,或者渲染UI界面需要较长的时间,这种情况就要使用SurfaceView了
只要继承SurfaceView类并实现SurfaceHolder.Callback接口就可以实现一个自定义的SurfaceView了,SurfaceHolder.Callback在底层的Surface状态发生变化的时候通知View,SurfaceHolder.Callback具有如下的接口:
1.surfaceCreated(SurfaceHolder holder):当Surface第一次创建后会立即调用该函数。程序可以在该函数中做些和绘制界面相关的初始化工作,一般情况下都是在另外的线程来绘制界面,所以不要在这个函数中绘制Surface。
2.surfaceChanged(SurfaceHolder holder, int format, int width,int height):当Surface的状态(大小和格式)发生变化的时候会调用该函数,在surfaceCreated调用后该函数至少会被调用一次。
3.surfaceDestroyed(SurfaceHolder holder):当Surface被摧毁前会调用该函数,该函数被调用后就不能继续使用Surface了,一般在该函数中来清理使用的资源。
SurfaceView需要与SurfaceHolder使用。
SurfaceView 和ViedoView 的区别
SurfaceView和View最本质的区别在于,surfaceView是在一个新起的单独线程中可以重新绘制画面,而View必须在UI的主线程中更新画面。
代码
播放视频
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
SurfaceView sv;//一个SurfaceView对应一个SurfaceHolder
SurfaceHolder surfaceHolder;//持有者,不能直接操作SurfaceView,通过它的SurfaceHolder来操作
MediaPlayer mediaPlayer=new MediaPlayer();//媒体资源文件
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sv=findViewById(R.id.sv);
surfaceHolder = sv.getHolder();
surfaceHolder.addCallback(this);//接口回调获得生命周期
initplayer();
}
private void initplayer() {
try {
//支持sd卡,网址等,要加权限
mediaPlayer.setDataSource("放资源");
//必须准备
mediaPlayer.prepare();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
//生命周期
//创建
@Override
public void surfaceCreated(SurfaceHolder holder) {
//mediaPlayer和surfaceholder进行绑定
mediaPlayer.setDisplay(surfaceHolder);
}
//改变
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
//销毁
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
加进度条
Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what==100){
sb.setMax(mediaPlayer.getDuration());
Log.e("###########",mediaPlayer.getDuration()+"");
sb.setProgress(mediaPlayer.getCurrentPosition());
Log.e("###########",mediaPlayer.getCurrentPosition()+"");
}
}
};
cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked==true){
mediaPlayer.start();
}else{
mediaPlayer.pause();
}
}
});
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
handler.sendEmptyMessage(100);
}
},0,200);
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
mediaPlayer.seekTo(sb.getProgress());
}
});
画布(点.线.圆.矩形.文字.图片.抗锯齿)
Paint paint = new Paint();
paint.setColor(Color.RED);//设置画笔颜色
paint.setStrokeWidth(30);//设置画笔宽度
paint.setTextSize(50);//文字大小
paint.setAntiAlias(true);//抗锯齿
Canvas canvas = holder2.lockCanvas();//锁定
canvas.drawPoint(50,100,paint);//画点
canvas.drawLine(100,200,500,400,paint);//画线
canvas.drawOval(500,100,200,200,paint);//画圆
canvas.drawRect(700,100,200,600,paint);//画矩形
canvas.drawText("哈哈哈哈哈",200,300,paint);//画文字
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher),350,10,paint);
holder2.unlockCanvasAndPost(canvas);//解锁