Android自定义组件系列【12】——非UI线程绘图SurfaceView
2024-10-19 19:41:19
一、SurfaceView的介绍
在前面我们已经会自定义View,使用canvas绘图,但是View的绘图机制存在一些缺陷。
1、View缺乏双缓冲机制。
2、程序必须重绘整个View上显示的图片,比较耗资源。
3、非UI线程无法更新View组件,所以会占用主线程资源,当需要在主线程中处理逻辑的时候会很慢。
在Android中为我们提供了一个SurfaceView来替代View实现绘制图形,一般在游戏绘图方面应用较广,所以如果是比较复杂的绘图建议使用SurfaceView.
二、SurfaceView的绘图机制
SurfaceView一般会与SurfaceHolder结合使用,SurfaceHolder用于与之关联的SurfaceView上绘图,调用SurfaceView的getHolder()方法可获取SurfaceView关联的SurfaceHolder.
SurfaceHolder提供了lockCanvas和lockCanvas(Rect dirty)来锁定绘图区域,并获取到该区域的画布(Canvas)我们通过该画布就可以进行图形的绘制了。
三、SurfaceView使用实例
1、一个简单的使用(绘制在UI线程)
package com.test.surfaceview; import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener; import com.example.testsurfaceview.R; public class MainActivity extends Activity{ private SurfaceHolder holder;
private Paint paint;
private Rect rect; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); paint = new Paint();
rect = new Rect(); SurfaceView surface = (SurfaceView)findViewById(R.id.show);
holder = surface.getHolder(); //由系统毁掉的三个函数
holder.addCallback(new SurfaceHolder.Callback() { @Override
public void surfaceDestroyed(SurfaceHolder holder) {
} @Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas canvas = holder.lockCanvas();
Bitmap bitmap = BitmapFactory.decodeResource(
MainActivity.this.getResources(), R.drawable.ic_launcher);
canvas.drawBitmap(bitmap, 0, 0, null);
holder.unlockCanvasAndPost(canvas);
} @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
}); //绑定事件监听
surface.setOnTouchListener(new OnTouchListener() { @Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
int cx = (int)event.getX();
int cy = (int)event.getY(); rect.set(cx - 50, cy - 50, cx + 50, cy + 50);
//锁定一个固定区域并锁定
Canvas canvas = holder.lockCanvas(rect);
//保存画布当前状态
canvas.save();
//旋转画布
canvas.rotate(30, cx, cy);
paint.setColor(Color.RED);
//绘制方块
canvas.drawRect(cx - 40, cy - 40, cx, cy, paint);
//恢复画布
canvas.restore();
paint.setColor(Color.GREEN);
//绘制方块
canvas.drawRect(cx, cy, cx + 40, cy + 40, paint);
//绘制完成,释放画布,提交修改
holder.unlockCanvasAndPost(canvas);
}
return false;
}
});
}
}
2、在非UI线程中绘制
package com.test.surfaceview; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView; import com.example.testsurfaceview.R; /**
* 阳光小强 http://blog.csdn.net/dawanganban
*
* @author Administrator
*
*/
public class MySurfaceView extends SurfaceView { private Context context;
private Rect rect;
private Paint paint; private AppStartDrawView appStartDrawView; public MySurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
rect = new Rect();
paint = new Paint();
appStartDrawView = new AppStartDrawView();
this.getHolder().addCallback(appStartDrawView);
} /**
* 停止动画
*/
public void stopAnim() {
appStartDrawView.cancel(true);
} private class AppStartDrawView extends AsyncTask<Void, Integer, Void> implements SurfaceHolder.Callback {
private boolean isStarted = false;
private SurfaceHolder holder; @Override
public void surfaceCreated(SurfaceHolder holder) {
this.holder = holder; //绘制一个图片
Canvas canvas = holder.lockCanvas();
Bitmap bitmap = BitmapFactory.decodeResource(
context.getResources(), R.drawable.ic_launcher);
canvas.drawBitmap(bitmap, 0, 0, null);
holder.unlockCanvasAndPost(canvas); if (!isStarted) {
this.execute();
isStarted = true;
}
} @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
this.holder = holder;
} @Override
public void surfaceDestroyed(SurfaceHolder holder) {
isStarted = false;
holder = null;
} @Override
protected Void doInBackground(Void... params) {
int cx = 0;
int cy = 0;
while(!isCancelled()){
//绘制动画
//TODO .....
rect.set(cx - 50, cy - 50, cx + 50, cy + 50);
//锁定一个固定区域并锁定
Canvas canvas = holder.lockCanvas(rect);
//保存画布当前状态
canvas.save();
//旋转画布
canvas.rotate(30, cx, cy);
paint.setColor(Color.RED);
//绘制方块
canvas.drawRect(cx - 40, cy - 40, cx, cy, paint);
//恢复画布
canvas.restore();
paint.setColor(Color.GREEN);
//绘制方块
canvas.drawRect(cx, cy, cx + 40, cy + 40, paint);
//绘制完成,释放画布,提交修改
holder.unlockCanvasAndPost(canvas); //TODO ....
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cx += 60;
cy += 60; if(cx >= 400){
stopAnim();
}
}
return null;
} }
}
最新文章
- ORACLE推导参数Derived Parameter介绍
- javaScript的简单学习
- Atitit. 获取cpu占有率的 java c# .net php node.js的实现
- iOS做新浪微博sso授权登录遇到的一些坑
- SignalR 简介
- oracle时间处理
- window系统查看端口被哪个进程占用
- c# 根据中文汉字获取到拼音
- PowerShell入门(序):为什么需要PowerShell?
- Let&#39;s Encrypt(开源SSL证书管理工具)
- LeetCode OJ 121. Best Time to Buy and Sell Stock
- Android 项目使用TensorFlow
- wifipineapple插件:codeInject的使用
- .net core 2.x - ids4 - identity - two factory 登录认证
- iPhone多次输入错误密码锁机后刷机恢复(原有内容会丢失)
- HL-D793G七位蓝色+PT6311驱动
- MVC 视图助手书写规范及注意点
- Outsider(HNOI2019)
- python3+selenium入门07-元素等待
- asp.net core 使用identityServer4的密码模式来进行身份认证(2) 认证授权原理
热门文章
- 1355: [Baltic2009]Radio Transmission
- 自动关闭Messbox
- Boom
- 关于FAT32分区的U盘4GB文件的测试
- 【ICM Technex 2018 and Codeforces Round #463 (Div. 1 + Div. 2, combined) A】 Palindromic Supersequence
- ArcGIS api for javascript——查询,然后单击显示信息窗口
- arcgis engine 获取高亮Feature、element
- resin后台输出中文乱码的解决的方法!
- TRIZ系列-创新原理-7-嵌套原理
- Cocos2d-x学习笔记(十四)CCAutoreleasePool具体解释