第6天SurfaceView高级应用-播放视频-画板-正弦波

效果图

在这里插入图片描述在这里插入图片描述

在这里插入图片描述
代码
while (true){
Canvas canvas = surfaceHolder.lockCanvas();
if(canvas==null){//如果画布为空,直接结束线程
break;}
int y=(int)(100* Math.sin(x*Math.PI/180)+400);
canvas.drawPoint(x++,y,paint);
surfaceHolder.unlockCanvasAndPost(canvas);
}

Android绘制函数图象及正弦函数的介绍
https://www.jianshu.com/p/ae4e69437efb

一.为什么使用surfaceview播放视频:


在Android中,一般播放音频时我们可以去使用Android提供的MediaPlayer类,但是想要播放视频仅仅依靠MediaPlayer类是远远不够的...这里还需要使用到一个SurfaceView这个组件来完成..为什么?因为像视频和SD图形等都需要迅速的更新...如果这个更新实在主线程内去完成,那么显然是不合理的,因为一个视频的播放,系统会首先确定视频的格式,然后得到视频的编码..然后对编码进行解码,得到一帧一帧的图像,最后在画布上进行迅速更新...这就是视频播放的机制...那么这个过程显然我们需要在另外一个线程内部去完成...这样主线程的其他内容,比如说其他的渲染操作,图片加载什么的,就不会导致主线程阻塞...这样我们就可以使用SurfaceView来完成

二.MediaPlayer使用到的方法:

  • 调用player.setDataSource()方法设置要播放的资源,可以是文件、文件路径、或者URL。
  • 调用MediaPlayer.setDisplay(holder)设置surfaceHolder,surfaceHolder可以通过surfaceview的getHolder()方法获得。
  • 调用MediaPlayer.prepare()来准备。
  • 调用MediaPlayer.start()来播放视频。

三.画板代码:

public class HuaBan extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder holder;
    private Canvas canvas;
    private Paint paint;
    private Path path=new Path();//路径
    private Thread thread=new Thread(new Runnable() {
        @Override
        public void run() {
            while(true){
                paint=new Paint();
                paint.setStyle(Paint.Style.STROKE);//设置不是填充
                paint.setColor(Color.GREEN);
                paint.setStrokeWidth(10f);
                canvas=holder.lockCanvas();//锁定画布
                if(canvas==null{//如果画布为空,直接结束线程
               		break;}
                //按照路径画图
                canvas.drawPath(path,paint);
                holder.unlockCanvasAndPost(canvas);//解除画布
            }


        }
    });
    //重写触摸事件


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();//获得事件类型
        switch (action){
            case MotionEvent.ACTION_DOWN://按下
                path.moveTo(event.getX(),event.getY());
                break;
            case MotionEvent.ACTION_MOVE://移动
                path.lineTo(event.getX(),event.getY());
                break;
            case MotionEvent.ACTION_UP://移动
                break;
        }
        return true;
    }

    public HuaBan(Context context) {
        super(context);
    }

    public HuaBan(Context context, AttributeSet attrs) {
        super(context, attrs);
        holder=getHolder();
        holder.addCallback(this);
    }

    public HuaBan(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public HuaBan(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
            thread.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

    }
}

四.视频代码:

(1)布局:

<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=".video.VedioActivity"
    android:orientation="vertical">
    <!--不需要自定义SurfaceView,不需要我们在上面画画,我们只需要将视频放到surfaceView中播放-->
    <SurfaceView
        android:id="@+id/surfaceview"
        android:layout_width="match_parent"
        android:layout_height="300dp" />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="100dp">
        <Button
            android:id="@+id/play"
            android:text="播放"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <Button
            android:text="暂停"
            android:id="@+id/pause"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>


</LinearLayout>

(2)Java代码:

public class VedioActivity extends AppCompatActivity implements SurfaceHolder.Callback{
    private SurfaceView surfaceView;
    private Button play,pause;
    private MediaPlayer mediaPlayer;//播放视频
    private SurfaceHolder surfaceHolder;//将视频放到持有者上面
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_vedio);
        initView();
        initPlayer();
    }
	private void initPlayer(){
		if(mediaPlayer==null){
		 mediaPlayer=new MediaPlayer();//创建对象
		}
        File file = Environment.getExternalStorageDirectory();//获得SD卡根路
        File file1 = new File(file, "万能1.mp4");//获得视频的路径
        try {
            mediaPlayer.setDataSource(file1.getAbsolutePath());//设置视频的路径  可以是SD卡文件的路径  网络视频Url
            mediaPlayer.prepare();//准备播本地视频
            //mediaPlayer.prepareAsync();//播放网络视频
            mediaPlayer.start();//播放视频
        } catch (IOException e) {
            e.printStackTrace();
        }
        }
    private void initView() {
        surfaceView=findViewById(R.id.surfaceview);
        pause=findViewById(R.id.pause);
        play=findViewById(R.id.play);
        pause.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mediaPlayer.isPlaying()){
                    mediaPlayer.pause();
                }
            }
        });
        play.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(!mediaPlayer.isPlaying()){//处于暂停
                    mediaPlayer.start();
                }
            }
        });
        surfaceHolder=surfaceView.getHolder();//获得持有者
        surfaceHolder.addCallback(this);//接口回调,获得生命周期
    }

    //创建生命周期:播放视频
    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
          mediaPlayer.setDisplay(surfaceHolder);//将视频放surfaceholder
       
    }
    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }
    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

    }
}

五.正弦波代码

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用SurfaceView绘制正弦波的示例代码: 首先,在布局文件中添加SurfaceView: ```xml <SurfaceView android:id="@+id/surfaceView" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 然后,在Activity中获取SurfaceView引用,并使用一个新线程来绘制正弦波: ```java public class MainActivity extends AppCompatActivity { private SurfaceView surfaceView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); surfaceView = findViewById(R.id.surfaceView); // 使用新线程绘制正弦波 new Thread(new Runnable() { @Override public void run() { drawSinWave(); } }).start(); } private void drawSinWave() { // 获取SurfaceHolder引用 final SurfaceHolder holder = surfaceView.getHolder(); // 定义X,Y坐标轴的单位长度(每一个像素表示多少距离) final float xAxisUnit = 30f; final float yAxisUnit = 50f; // 获取SurfaceView的宽高 final int width = surfaceView.getWidth(); final int height = surfaceView.getHeight(); // 定义正弦函数的周期、振幅和相位 final float cycle = 2 * (float) Math.PI / xAxisUnit; final float amplitude = height / 4; final float phase = 0; while (true) { // 获取当前的Canvas对象 Canvas canvas = holder.lockCanvas(); if (canvas != null) { // 清空画布 canvas.drawColor(Color.WHITE); // 绘制坐标轴 paint.setColor(Color.BLACK); paint.setStrokeWidth(2f); canvas.drawLine(0f, height / 2f, width, height / 2f, paint); canvas.drawLine(width / 2f, 0f, width / 2f, height, paint); // 绘制正弦波 paint.setColor(Color.BLUE); paint.setStrokeWidth(3f); float lastX = 0f, lastY = 0f; for (float x = 0; x <= width; x += 1) { float y = (float) (amplitude * Math.sin(cycle * (x / xAxisUnit) + phase)) + height / 2f; if (x > 0) { canvas.drawLine(lastX, lastY, x, y, paint); } lastX = x; lastY = y; } // 释放当前的Canvas对象 holder.unlockCanvasAndPost(canvas); } // 暂停一定时间后再重新绘制 try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } } ``` 以上代码中,我们将绘制正弦波的代码放入了一个循环中,以便不断地更新SurfaceView上的内容。 具体细节见注释。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值