一、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;
} }
}

Android自定义组件系列【12】——非UI线程绘图SurfaceView的更多相关文章

  1. Android自定义组件系列【7】——进阶实践(4)

    上一篇<Android自定义组件系列[6]--进阶实践(3)>中补充了关于Android中事件分发的过程知识,这一篇我们接着来分析任老师的<可下拉的PinnedHeaderExpan ...

  2. Android自定义组件系列【6】——进阶实践(3)

    上一篇<Android自定义组件系列[5]--进阶实践(2)>继续对任老师的<可下拉的PinnedHeaderExpandableListView的实现>进行了分析,这一篇计划 ...

  3. Android自定义组件系列【5】——进阶实践(2)

    上一篇<Android自定义组件系列[5]--进阶实践(1)>中对任老师的<可下拉的PinnedHeaderExpandableListView的实现>前一部分进行了实现,这一 ...

  4. Android自定义组件系列【4】——自定义ViewGroup实现双侧滑动

    在上一篇文章<Android自定义组件系列[3]--自定义ViewGroup实现侧滑>中实现了仿Facebook和人人网的侧滑效果,这一篇我们将接着上一篇来实现双面滑动的效果. 1.布局示 ...

  5. Android自定义组件系列【5】——进阶实践(1)

    接下来几篇文章将对任老师的博文<可下拉的PinnedHeaderExpandableListView的实现>分步骤来详细实现,来学习一下大神的代码并记录一下. 原文出处:http://bl ...

  6. Android自定义组件系列【3】——自定义ViewGroup实现侧滑

    有关自定义ViewGroup的文章已经很多了,我为什么写这篇文章,对于初学者或者对自定义组件比较生疏的朋友虽然可以拿来主义的用了,但是要一步一步的实现和了解其中的过程和原理才能真真脱离别人的代码,举一 ...

  7. Android自定义组件系列【8】——遮罩文字动画

    遮罩文字的动画我们在Flash中非常常见,作为Android的应用开发者你是否也想将这种动画做到你的应用中去呢?这一篇文章我们来看看如何自定义一个ImageView来实现让一张文字图片实现文字的遮罩闪 ...

  8. Android自定义组件系列【1】——自定义View及ViewGroup

    View类是ViewGroup的父类,ViewGroup具有View的所有特性,ViewGroup主要用来充当View的容器,将其中的View作为自己孩子,并对其进行管理,当然孩子也可以是ViewGr ...

  9. Android自定义组件系列【17】——教你如何高仿微信录音Toast

    一.Toast介绍 平时我们在Android开发中会经常用到一个叫Toast的东西,官方解释如下 A toast is a view containing a quick little message ...

随机推荐

  1. stuff(param1, startIndex, length, param2)

    1.作用 stuff(param1, startIndex, length, param2)将param1中自startIndex(SQL中都是从1开始,而非0)起,删除length个字符,然后用pa ...

  2. ipad mini2 升级9.0.2后解锁白屏解决

    解锁白屏是个什么现象?就是当你用手指滑动解锁后出现输入密码的界面后,1秒之内屏幕变白,中间一个黑色的苹果,几秒之后重新回到滑动解锁的界面.我出现这个现象不是因为升级了9.0.2,而是升级了9.0.2之 ...

  3. session 存入 memcahce

    <?php header('content-type:text/html;charset=utf-8'); class RedisSessionHandler{ public $ttl; //失 ...

  4. POJ1201Intervals(差分约束)

    题意 给出数轴上的n个区间[ai,bi],每个区间都是连续的int区间. 现在要在数轴上任意取一堆元素,构成一个元素集合V 要求每个区间[ai,bi]和元素集合V的交集至少有ci不同的元素 求集合V最 ...

  5. 紫书 习题 10-1UVa 111040(找规律)

    通过观察可以得 图可以分成很多个上面一个,中间两个,下面三个的"模板" 这个时候最上面一个知道,最下面得左右知道 那么可以设下面中间为x,左边为a1, 右边为a2, a1a2已知 ...

  6. hdu4691 Front compression(后缀数组)

    Front compression Time Limit: 5000/5000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others) ...

  7. 根据on,获取选中的元素

    打钩的元素有个on的class. // 礼物发送 function send_gift() { var type,diamond,name,id; var list = $('.live .on'); ...

  8. poj--1637--Sightseeing tour(网络流,最大流判断混合图是否存在欧拉图)

    Sightseeing tour Time Limit: 1000MS   Memory Limit: 10000KB   64bit IO Format: %I64d & %I64u Sub ...

  9. 从 dig(nslookup) bind —— windows 下的域名解析服务器信息的查看

    dig(domain information groper,之所以选择这三个词,在于这三个词的首字母构成的词 dig 也有探索挖掘的含义)本身是 Linux 下的查询 DNS 信息的工具,功能类似 n ...

  10. NET Remoting原理及应用

    .NET Remoting原理及应用实例: Remoting:(本文摘自百度百科) 简介:        什么是Remoting,简而言之,我们可以将其看作是一种分布式处理方 式.从微软的产品角度来看 ...