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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,047评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,807评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,501评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,839评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,951评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,117评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,188评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,929评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,372评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,679评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,837评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,536评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,168评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,886评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,129评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,665评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,739评论 2 351

推荐阅读更多精彩内容