Android-自定义SurfaceView-案例入门

上一篇Android-View、SurfaceView、GLSurfaceView的区别认识 我们讲了了下View、SurfaceView、GLSurfaceView相关的知识点,下面我们就可以开始尝试看下案例怎么写了。先看SurfaceView吧,至于GLSurfaceView,小白先不说,以后看时间再搞。小白早期有个闹钟的demo,里面有简单的运用 Share Sprite...

自定义SurfaceView,除了常规的View的一些基本操作,测量,布局,绘制,touch事件。从官方告知的,如果我们要开启一个线程去做绘制操作,需要实现SurfaceHolder.Callback接口。

1. 然后就有三个对应的方法需要实现

image

2. 既然接口实现了,那么如何添加监听?getHolder()可以获取SurfaceViewHolder管理器,负责管理SurfaceView,同时设置监听回调接口

image

到此基本初始化就有了。

3. 之前官方说过,创建的绘制线程需要在create和desotry之间调用

image

因此我们首先需要在create中创建绘制线程,然后ondestroy中停止绘制线程。注意,线程一旦创建,如果想要保持不停渲染,就需要while(bIsDrawing)来控制不停的循环绘制.

So, 可以这样开启绘制线程

image

停止绘制

image

我们可以实现Runnable接口,然后实现run方法,以这样的方式简化创建逻辑

image
image
image

基本的雏形就OK了。然后剩下的就是绘制,绘制,再绘制。。一开始绘制不熟悉的情况,我们就随便简单绘制下...

4. 绘制需要canvas, SurfaceHolder可以通过lockCanvas获取画布

image

当绘制结束以后需要提交生效,则可以

image

很多情况下,我们看的文档貌似没有案例直接给出来,我们可以先过一遍api,可能大概通过解释能够明白,start....finish...应该就是成对的使用。再比如[setFixedSize](https://link.zhihu.com/?target=https%3A//developer.android.google.cn/reference/android/view/SurfaceHolder.html%3Fhl%3Dzh-cn%23setFixedSize%28int%2C%2520int%29)[setFormat](https://link.zhihu.com/?target=https%3A//developer.android.google.cn/reference/android/view/SurfaceHolder.html%3Fhl%3Dzh-cn%23setFormat%28int%29)这些可以设置固定尺寸,固定格式什么的等等相关方法。

5. 画布有了,需要一个Paint基本上就可以绘制了(自定义View的一开始的时候我们也简单进行了使用,只不过对于绘制不熟练,有机会后面搞点复杂的多练习练习)

image
image

很简单的一个矩形绘制就可以了赛。

***activity_custom_surface_view.xml ***布局

 <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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="com.example.hl.myapplication.CustomSurfaceViewActivity">

    <com.example.hl.myapplication.CustomSurfaceView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</android.support.constraint.ConstraintLayout>
image

6. 我们再完善下,判空,同时锁定surfaceHolder,避免多线程的问题, 另外在模拟器上可能背景不是黑色,但是在手机上整个surfaceview背景都是黑乎乎的,也需要做透明处理。 同时绘制的时候让颜色发生变化。。。

综上我们完善下简单demo...不然模拟器可能出现花屏的感觉...如果你也是自己一点点尝试,就会发现相关问题

CustomSurfaceView.java

package com.example.hl.myapplication;

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/*
 *@Description: 自定义SurfaceView
 *@Author: hl
 *@Time: 2018/12/4 9:45
 */
public class CustomSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
    private static final String TAG = CustomSurfaceView.class.getName();

    private SurfaceHolder surfaceHolder;
    private boolean bDrawing = false;
    private Paint mPaint;
    private String[] colors = new String[]{"#ff4ab1", "#e84626", "#3e18e8"};

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

    public CustomSurfaceView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public CustomSurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        this.surfaceHolder = getHolder();
        this.surfaceHolder.addCallback(this);
        ///< 画布透明处理
        this.setZOrderOnTop(true);
        this.surfaceHolder.setFormat(PixelFormat.TRANSLUCENT);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.e(TAG, "onDraw");
    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        Log.e(TAG, "surfaceCreated");

        ///< 初始化画笔
        mPaint = new Paint();
        mPaint.setColor(Color.parseColor(colors[0]));
        mPaint.setStrokeWidth(10f);

        ///< 开启绘制
        bDrawing = true;
        new Thread(this).start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
        Log.e(TAG, "surfaceChanged");
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        Log.e(TAG, "surfaceDestroyed");
        ///< 停止绘制
        bDrawing = false;
    }

    @Override
    public void run() {
        ///< 不停的绘制
        while (bDrawing) {
            ///< 绘制刷新处理
            drawingSomething();
            try {
                ///< 控制刷新频率
                Thread.sleep(200);
            } catch (InterruptedException e) {
            }
        }
    }

    /**
     * 绘制点东东
     */
    private void drawingSomething() {
        Canvas canvas = null;
        try {
            canvas = surfaceHolder.lockCanvas();
            if (null != canvas) {
                synchronized (surfaceHolder) {
                    ///< 清空画布-透明处理
                    canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);

                    mPaint.setColor(Color.parseColor(colors[(int) (Math.random() * 3 + 0)]));
                    ///< 绘制点东东
                    canvas.drawRect(new Rect(0,  0, 100, 100), mPaint);
                }
            }
        } finally {
            if (null != surfaceHolder && null != canvas) {
                surfaceHolder.unlockCanvasAndPost(canvas);
            }
        }
    }
}

image

o. 关于测量,布局啥的就不说了。另外关于touch事件也就飘过。 有兴趣可以自己做一个画板,利用touch事件存储路径,然后drawpath方法,应该就可以做一个随意涂鸦的简单画板了,更奇思妙想的想法需要你加油【演唱会/晚会等 举起手机的滚动弹幕,一闪一闪的,想想就可以搞了哟】。

注:如果不用surfaceview做一个单独的线程,而是在主线程(UI线程)里面做耗时的操作,或者说sleep,肯定就嗝屁了。

了解这个有助于我们自定义View的时候可以更高级,自定义动态绘制的SurfaceView,实现更酷炫的效果。到这里小白认为自定义View还应该包含自定义SurfaceView以及GLSurfaceView....啊哈哈哈....

分析分享(后面小白也要自己看源码学习下):

android SurfaceView 详解

Android SurfaceView入门学习

生活就是开心放松的坐直了工作,干活,敲代码,学习,看书,吃饭,等等一系列操作

---CPU

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容