Android中使用SurfaceView和Canvas来绘制动画

其实每个View中都有Canvas可以用来绘制动画,只需要在这个View中重载onDraw()方法就可以,但是SurfaceView类是一个专门用来制动动画的类。

Canvas(中文叫做"画布")就和HTML5中的canvas标签一样可以在一定区域内自由绘制图形。Canvas+SurfaceView制作的动画与View Animation和Property Animation这类动画比起来更加适合大量的集中播放的动画,比如游戏画面、相机的图像显示等。

因为SurfaceView通常会在另一个专门的线程中不断重绘界面,所以不像其他动画那样要在主线程(UI线程)中播放动画的同时还要消耗一定的流畅度用来响应用户输入。

在使用SurfaceView时需要注意下面这些要点:

1)每个SurfaceView都需要一个SurfaceHolder对象来处理这个SurfaceView的生命周期和获取这个SurfaceView的Canvas对象,可以通过调用SurfaceView的getHolder()方法来获取它的SurfaceHolder对象。

2)使用SurfaceView时一般是通过继承SurfaceView的方式来实现,可以顺便implements两个接口,分别是Runnable和SurfaceHolder.Callback。第二个接口需要重载三个函数,这三个函数就是SurfaceView的生命周期处理了,可以通过SurfaceHolder对象的addCallback()方法把实现好的Callback对象传进去。

3)在使用SurfaceView的Canvas时一定要记得加锁同步,因为不能让画布同时绘制多个图案,通过调用这个SurfaceView的SurfaceHolder对象的lockCanvas()就可以做到这一点。绘制完毕后在调用SurfaceHolder对象的unlockCanvasAndPost()方法就可以解锁并更新。

下面给出了一个用SurfaceView和Canvas绘制动画的例子,一般直接复制上就可以运行看到效果:

package com.example.canvastest;

import android.app.Activity;
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.os.Bundle;
import android.view.Menu;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;

public class MainActivity extends Activity {
	/*
	 * 这个类用来当测试的物件,会沿着方形路线持续移动
	 */
	class GameObject {
		private float x;
		private float y;
		private Bitmap img;
		private Paint paint;

		public GameObject() {
			this.img = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
			this.x = 100;
			this.y = 100;
			this.paint = new Paint();
		}

		// 在SurfaceView加锁同步后传给自己的Canvas上绘制自己
		public void drawSelf(Canvas canvas) {
			canvas.drawBitmap(img, x, y, paint);
		}

		// 获取物件下一次要绘制的位置(这里是沿着一个边长为400的正方形不断运动的)
		public void getNextPos() {
			if (y == 100 && x != 500)
				x += 5;
			else if (x == 500 && y != 500)
				y += 5;
			else if (y == 500 && x != 100)
				x -= 5;
			else if (x == 100 && y != 100)
				y -= 5;
		}
	}

	/*
	 * 这个类就是加工了SurfaceView之后的类,所有要运动的物件都最终放在这里进行绘制
	 */
	class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
		private Thread thread; // SurfaceView通常需要自己单独的线程来播放动画
		private Canvas canvas;
		private SurfaceHolder surfaceHolder;

		private GameObject obj;

		public MySurfaceView(Context c) {
			super(c);
			this.surfaceHolder = this.getHolder();
			this.surfaceHolder.addCallback(this);
			this.obj = new GameObject();
		}

		@Override
		public void run() {
			while (true) {
				obj.getNextPos();
				canvas = this.surfaceHolder.lockCanvas(); // 通过lockCanvas加锁并得到該SurfaceView的画布
				canvas.drawColor(Color.BLACK);
				obj.drawSelf(canvas); // 把SurfaceView的画布传给物件,物件会用这个画布将自己绘制到上面的某个位置
				this.surfaceHolder.unlockCanvasAndPost(canvas); // 释放锁并提交画布进行重绘
				try {
					Thread.sleep(10); // 这个就相当于帧频了,数值越小画面就越流畅
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}

		@Override
		public void surfaceDestroyed(SurfaceHolder arg0) {
			Toast.makeText(getApplicationContext(), "SurfaceView已经销毁", Toast.LENGTH_LONG).show();
		}

		@Override
		public void surfaceCreated(SurfaceHolder arg0) {
			Toast.makeText(getApplicationContext(), "SurfaceView已经创建", Toast.LENGTH_LONG).show();
			this.thread = new Thread(this);
			this.thread.start();
		}

		@Override
		public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
			// 这里是SurfaceView发生变化的时候触发的部分
		}
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(new MySurfaceView(getApplicationContext())); // 别忘了开始的时候载入我们加工好的的SurfaceView
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
}

如果转载请注明出处:http://blog.csdn.net/gophers

Android中使用SurfaceView和Canvas来绘制动画,布布扣,bubuko.com

时间: 2024-10-08 11:13:21

Android中使用SurfaceView和Canvas来绘制动画的相关文章

android中自定义view涉及到的绘制知识

android中自定义view的过程中,需要了解的绘制知识. 1.画笔paint: 画笔设置: <span style="font-size:14px;"> paint.setAntiAlias(true);//抗锯齿功能 paint.setColor(Color.RED); //设置画笔颜色 paint.setStyle(Style.FILL);//设置填充样式 paint.setStrokeWidth(30);//设置画笔宽度 paint.setShadowLayer(

android中的surfaceview控件

SurfaceView是继承于View类的,有绘制动态图片,播放视频的作用.View负责在主线程中更新动画,而在SurfaceView是在一个新线程中更新动画,并且它是一个2D的画布效果,将自己放置于屏幕的最低层进行图画的显示, SurfaceView的使用方法: 1.当单独建立一个SurfaceView的工程 需要将这个工程继承SurfaceView 并接口于SurfaceHolder的Callback和Runnable  其中SurfaceHolder是用来监听画布,Runnable则是用来

Android中实现一个简单的逐帧动画(附代码下载)

场景 Android中的逐帧动画,就是由连续的一张张照片组成的动画. 效果 注: 博客: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 获取编程相关电子书.教程推送与免费下载. 实现 首先准备一组不同表情的照片,放在res/drawable下,然后在此目录下新建动画资源文件fairy.xml <?xml version="1.0" encoding="utf-8"?> <animati

Android中使用SurfaceView+MediaPlayer+自定义的MediaController实现自定义的视屏播放器

效果图如下: (PS本来是要给大家穿gif动态图的,无奈太大了,没法上传) 功能实现:暂停,播放,快进,快退,全屏,退出全屏,等基本功能 实现的思路: 在主布局中放置一个SurfaceView,在SurfaceView中放置一个MediaPlayer ,在其下方自定义一个MediaController,不过也不能称之为MediaController,使用的是PupupWindow来实现的,在PupupWindow布局中放置几个textView,Button,最重要的使我们的SeekBar控件,创

android中surface,surfaceview,sufaceholder以及surface客户端的关系

这里以照相机camera功能的实现来解释surface,surfaceview,sufaceholder以及surface客户端(本例子中指的是camera)的关系,surface及其client(客户端,本例子中指的是camera)之间的纽带就是surfaceholder,它控制着surface及其client(客户端,本例子中指的是camera)之间的连接or断开,surfaceView座位视图层级结构层面的组件,可以认为是它承载了surface,而surface是实际用来接收图像原始像素绘

Android中加activity退出和进入的动画

清单文件中引用 <activity android:name="com.example.MainActivity" android:configChanges="orientation|keyboardHidden" android:screenOrientation="portrait" android:theme="@style/Center_Zoom_NoTitle_FullScreen" /> <ac

Android中自定义视图View之---Canvas和Path对象

介绍Android中的Paint和Canvas的概念和使用方法 Android中的Paint和Canvas的概念是很简单的,就是我们用画笔在画布上进行绘制没什么难度的,我们只要拿到画笔Paint和画布Canvas对象就可以进行操作了.当然Canvas对象提供了很多绘制图形的方法,下面来看一下代码吧: package com.example.drawpathdemo; import android.annotation.SuppressLint; import android.content.Co

Android中绘制圆角矩形图片及任意形状图片

圆角矩形图片在苹果的产品中很流行,相比于普通的矩形,很多人都喜欢圆角矩形的图片,因为它避开了直角的生硬,带来更好的用户体验,下面是几个设计的例子: 下面在Android中实现将普通的矩形图片绘制成圆角矩形.首先看最终效果: 代码清单: package com.example.phototest; import android.os.Bundle; import android.app.Activity; import android.graphics.Bitmap; import android

Android中自定义视图View之---前奏篇

前言 好长时间没写blog了,心里感觉有点空荡荡的,今天有时间就来写一个关于自定义视图的的blog吧.关于这篇blog,网上已经有很多案例了,其实没什么难度的.但是我们在开发的过程中有时候会用到一些自定义的View以达到我们所需要的效果.其实网上的很多案例我们看完之后,发现这部分没什么难度的,我总结了两点: 1.准备纸和笔,计算坐标 2.在onDraw方法中开始画图,invalidate方法刷新,onTouchEvent方法监听触摸事件 对于绘图相关的知识,之前在弄JavaSE相关的知识的时候,