上一篇Android-View、SurfaceView、GLSurfaceView的区别认识 我们讲了了下View、SurfaceView、GLSurfaceView相关的知识点,下面我们就可以开始尝试看下案例怎么写了。先看SurfaceView吧,至于GLSurfaceView,小白先不说,以后看时间再搞。小白早期有个闹钟的demo,里面有简单的运用 Share Sprite...
自定义SurfaceView,除了常规的View的一些基本操作,测量,布局,绘制,touch事件。从官方告知的,如果我们要开启一个线程去做绘制操作,需要实现SurfaceHolder.Callback接口。
1. 然后就有三个对应的方法需要实现
2. 既然接口实现了,那么如何添加监听?getHolder()可以获取SurfaceViewHolder管理器,负责管理SurfaceView,同时设置监听回调接口
到此基本初始化就有了。
3. 之前官方说过,创建的绘制线程需要在create和desotry之间调用
因此我们首先需要在create中创建绘制线程,然后ondestroy中停止绘制线程。注意,线程一旦创建,如果想要保持不停渲染,就需要while(bIsDrawing)来控制不停的循环绘制.
So, 可以这样开启绘制线程
停止绘制
我们可以实现Runnable接口,然后实现run方法,以这样的方式简化创建逻辑
基本的雏形就OK了。然后剩下的就是绘制,绘制,再绘制。。一开始绘制不熟悉的情况,我们就随便简单绘制下...
4. 绘制需要canvas, SurfaceHolder可以通过lockCanvas获取画布
当绘制结束以后需要提交生效,则可以
很多情况下,我们看的文档貌似没有案例直接给出来,我们可以先过一遍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的一开始的时候我们也简单进行了使用,只不过对于绘制不熟练,有机会后面搞点复杂的多练习练习)
很简单的一个矩形绘制就可以了赛。
***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>
6. 我们再完善下,判空,同时锁定surfaceHolder,避免多线程的问题, 另外在模拟器上可能背景不是黑色,但是在手机上整个surfaceview背景都是黑乎乎的,也需要做透明处理。 同时绘制的时候让颜色发生变化。。。
综上我们完善下简单demo...不然模拟器可能出现花屏的感觉...如果你也是自己一点点尝试,就会发现相关问题
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);
}
}
}
}
o. 关于测量,布局啥的就不说了。另外关于touch事件也就飘过。 有兴趣可以自己做一个画板,利用touch事件存储路径,然后drawpath方法,应该就可以做一个随意涂鸦的简单画板了,更奇思妙想的想法需要你加油【演唱会/晚会等 举起手机的滚动弹幕,一闪一闪的,想想就可以搞了哟】。
注:如果不用surfaceview做一个单独的线程,而是在主线程(UI线程)里面做耗时的操作,或者说sleep,肯定就嗝屁了。
了解这个有助于我们自定义View的时候可以更高级,自定义动态绘制的SurfaceView,实现更酷炫的效果。到这里小白认为自定义View还应该包含自定义SurfaceView以及GLSurfaceView....啊哈哈哈....
分析分享(后面小白也要自己看源码学习下):
生活就是开心放松的坐直了工作,干活,敲代码,学习,看书,吃饭,等等一系列操作
---CPU