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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值