Day11:SurfaceView
技能:播放视频+各种图形+歌词滚动
一.SurfaceView介绍
1.SurfaceView和View的区别:
- View 主要适用于主动更新的情况,而 surfaceView 主要适用于被动更新,例如频繁的刷新。
- View 在主线程中对画面进行刷新,而 surfaceView 通常会通过一个子线程来进行页面的刷新
- View 在绘图时没有使用双缓冲机制,而 surfaceView 在底层实现机制上就已经实现了双缓冲机制。
总结就是,如果你的自定义 View 需要频繁刷新,或者刷新时数据处理量很大,考虑用 SurfaceView 来替代 View。
2.双缓冲:
二.使用SurfaceView播放视频
思路:surfaceview展示画面+Mediaplayer媒体资源+将mediaPlayer放在surfaceview上面显示
1.布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SurfaceViewActivity">
<YaoVideoView
android:id="@+id/surface"
android:layout_width="match_parent"
android:layout_height="400dp" />
</LinearLayout>
2.java代码
/**
* 一.Surfaceview的使用场景
* 1. 播放视频
* 2.绘制滚动的图形:画圆 画线 画矩形 画图片 画文字
* 3.画板功能:截图之后可以涂鸦
* 4.歌词滚动
* 5.飞机大战
* 二.特点:频繁的更新UI,原因是双缓冲机制
* 三.实现
* 1.播放视频+MediaPlayer
* 2.surfaceview的生命周期:创建成功绘制各种画面
*
* */
public class YaoVideoView extends SurfaceView implements SurfaceHolder.Callback{
private SurfaceHolder surfaceHolder;
private MediaPlayer mediaPlayer;
public YaoVideoView(Context context) {
super(context);
}
//xml布局执行该构造
public YaoVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
if(mediaPlayer == null){
mediaPlayer = new MediaPlayer();
}
}
//播放指定视频
public void setData(String url){
if(mediaPlayer != null){
mediaPlayer.reset();
try {
mediaPlayer.setDataSource(url);
} catch (IOException e) {
e.printStackTrace();
}
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
}
});
}
}
public YaoVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public YaoVideoView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
mediaPlayer.setDisplay(surfaceHolder);//
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
}
三.播放视频横竖屏切换
1.清单文件设置acitivy支持横竖屏切换
android:configChanges="keyboard|screenSize|orientation"
2.切换横屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
3.切换竖屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
四.使用SurfaceView绘制各种图形
思路:画布+画笔
1.画布Canvas:画线/画圆/画文字/画椭圆/画弧度/画矩形/画点/画图片
- 画线
- 画圆
- 画文字
- 画矩形
- 画点
- 画图片
- 画弧度
2.画笔:Paint
- setColor(int color): 设置绘制的颜色,使用颜色值来表示,该颜色值包括透明度和RGB颜色。
- setStyle(Paint.Style style):设置画笔的样式,为FILL,FILL_OR_STROKE,或STROKE Style.FILL: 实心 STROKE:空心 FILL_OR_STROKE:同时实心与空心
- setTextSize(float textSize):设置绘制文字的字号大小
- setAntiAlias(true):抗锯齿
- setStrokeWidth(30):设置画笔宽度
3.绘制各种图形
- 画点:canvas.drawPoint
- 画线:canvas.drawLine
- 画圆:canvas.drawCircle
- 画椭圆:canvas.drawOval
- 画矩形:canvas.drawRect
- 画扇形: canvas.drawArc
- 画文字: canvas.drawText
- 画图片:canvas.drawBitmap
- 画路径:canvas.drawPath
注意:绘制滚动的图形的时候,需要在线程中绘制
//画画:画笔paint+画布canves
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void surfaceCreated(SurfaceHolder holder) {
//TODO 1:画笔
Paint paint = new Paint();
paint.setColor(Color.GREEN);//颜色
paint.setStrokeWidth(30);//画笔宽度
paint.setTextSize(60);//文字的大小
paint.setAntiAlias(true);//抗锯齿,默认false
//TODO 2:画布
Canvas canvas = holder.lockCanvas();//锁定 我在画的时候,不让其他人的话
//画点
canvas.drawPoint(200,300,paint);
//画线
canvas.drawLine(200,300,400,500,paint);
//画圆
canvas.drawOval(100,200,300,400,paint);
//画矩形
canvas.drawRect(300,400,500,600,paint);
//画扇形
canvas.drawArc(500,500,700,700,20,180,true,paint);
//画文字:歌词滚动
canvas.drawText("我是帅哥承谦益",800,800,paint);
//画图片
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher),800,900,paint);
holder.unlockCanvasAndPost(canvas);//解除锁定
}
此处模仿的是发送弹幕功能:需要在子线程中更新UI
int x=0;
int y=200;
//画画:画笔paint+画布canves
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void surfaceCreated(SurfaceHolder holder) {
//TODO 1:画笔
Paint paint = new Paint();
paint.setColor(Color.GREEN);//颜色
paint.setStrokeWidth(30);//画笔宽度
paint.setTextSize(60);//文字的大小
paint.setAntiAlias(true);//抗锯齿,默认false
while (true){
//TODO 2:画布
Canvas canvas = holder.lockCanvas();//锁定 我在画的时候,不让其他人的话
if(canvas==null){
break;//画布为空 结束线程
}
canvas.drawColor(Color.WHITE);//刷白
//画文字:飞弹幕
canvas.drawText("我是帅哥承谦益",x+=10,y,paint);
holder.unlockCanvasAndPost(canvas);//解除锁定
}
}
三.播放视频的过程中画弹幕
源代码:
https://gitee.com/yaotainxue/A1811A/tree/master/day11_surfaceview_danmu
四.播放音乐的时候,滚动歌词
五.飞机大战游戏
源代码:
https://gitee.com/yaotainxue/a1807-a/tree/master/day11_surfaceview_game