Android使用SurfaceView实现墨迹天气的风车效果

摘要:
使用SurfaceView,所有的绘图工作必须得在Surface被创建之后才能开始,所以Callback中的surfaceCreated和surfaceDestroyed就成了绘图处理代码的边界。实现SurfaceHolder.Callback接口需要重写的方法://在surface的大小发生改变时激发publicvoidsurfaceChanged{}//在创建时激发,一般在这里调用画图的线程。publicvoidsurfaceCreated{}//销毁时激发,一般在这里将画图的线程停止、释放。publicvoidsurfaceDestroyed{}SurfaceHolder有几个重要方法://锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。、abstractvoidunlockCanvasAndPost;//给SurfaceView当前的持有者一个回调对象。

SurfaceView也是继承自View,它和我们以前接触到的View(Button、TextView等)最大的不同是,SurfaceView可以有一个单独的线程进行绘制,这个线程区别于UI线程(主线程),因此SurfaceView绘制并不占用主线程资源

SurfaceView实现通常是自定义,继承SurfaceView并实现SurfaceHolder.Callback接口。使用SurfaceView,所有的绘图工作必须得在Surface 被创建之后才能开始,所以Callback 中的surfaceCreated 和surfaceDestroyed 就成了绘图处理代码的边界。

实现SurfaceHolder.Callback接口需要重写的方法:

//在surface的大小发生改变时激发
(1)publicvoidsurfaceChanged(SurfaceHolderholder,intformat,intwidth,intheight){}

//在创建时激发,一般在这里调用画图的线程。
(2)publicvoidsurfaceCreated(SurfaceHolderholder){}

//销毁时激发,一般在这里将画图的线程停止、释放。

(3)publicvoidsurfaceDestroyed(SurfaceHolderholder){}

SurfaceHolder有几个重要方法:

// 锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。
(1)、abstract Canvas lockCanvas();
// 锁定画布的某个区域进行画图等..因为画完图后,会调用下面的unlockCanvasAndPost来改变显示内容。
// 相对部分内存要求比较高的游戏来说,可以不用重画dirty外的其它区域的像素,可以提高速度。
(2)、abstract Canvas lockCanvas(Rect dirty);
// 结束锁定画图,并提交改变。

(3)、abstract void unlockCanvasAndPost(Canvas canvas);

//给SurfaceView当前的持有者一个回调对象。

(4)、abstract void addCallback(SurfaceHolder.Callback callback);

下面使用SurfaceView实现墨迹天气的风车效果:

public class WindmillView extends SurfaceView implements
		SurfaceHolder.Callback, Runnable {

	private SurfaceHolder holder;

	private boolean isRunning = true;

	

	/**
	 * 屏幕的像素
	 */
	private int screenWidth;
	private int screenHeiht;

	private Bitmap windPoint;

	/**
	 * 风车图片
	 */
	private Bitmap Windmill;

	/**
	 * 背景图片
	 */
	private Bitmap viewBg;

	public WindmillView(Context context) {
		super(context);
		this.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
				LayoutParams.MATCH_PARENT));
		holder = getHolder();
		holder.addCallback(this);
		holder.setFormat(PixelFormat.RGBA_8888); // 顶层绘制SurfaceView设成透明
		getViewSize(context);
		LoadWindmillImage();

	}

	private void LoadWindmillImage() {
		viewBg = BitmapFactory.decodeResource(getResources(), R.drawable.bg_na);
		Windmill = BitmapFactory.decodeResource(getResources(),
				R.drawable.na_windmill);
		windPoint = BitmapFactory.decodeResource(getResources(),
				R.drawable.na_point);
		float percent = percentumW();
		Log.v("icers", screenWidth + "");

		int _witdh = (int) (250 / percent);//250是风车基点左侧像素
		Log.v("icers", _witdh + "");
		Windmill = Bitmap.createScaledBitmap(Windmill, _witdh * 2, _witdh * 2,
				true);

	}


	// 获取屏幕的分辨率
	private void getViewSize(Context context) {
		DisplayMetrics metrics = new DisplayMetrics();
		WindowManager windowManager = (WindowManager) context
				.getSystemService(Context.WINDOW_SERVICE);
		windowManager.getDefaultDisplay().getMetrics(metrics);
		this.screenHeiht = metrics.heightPixels;
		this.screenWidth = metrics.widthPixels;

		Log.d("Windmill", "Windmill:"+screenHeiht+"|"+screenWidth);
	}

	/**
	 * 获取背景图和风车的比率 ,从而根据这个比例改变各个手机上面的风车图片大小
	 * 
	 * 
	 * @return
	 */
	private float percentumW() {
		float bg_width = viewBg.getWidth();
		return  bg_width/screenWidth ;
	}
	/**
	 * 获取背景图和风车的比率 ,从而根据这个比例改变各个手机上面的风车图片大小
	 * 
	 * 
	 * @return
	 */
	private float percentumH() {
		float bg_height = viewBg.getHeight();
		return  bg_height/(screenHeiht);
	}

	@Override
	public void run() {

		float rotate = 0;// 旋转角度变量

		while (isRunning) {
			Log.i("icer", "Running");
			Canvas canvas = null;
			synchronized (this) {
				try {
					canvas = holder.lockCanvas();
					if (canvas != null) {
						Paint paint = new Paint();
						paint.setAntiAlias(true);

						// 对图片抗锯齿
						paint.setFilterBitmap(true);
						RectF rect = new RectF(0, 0, screenWidth, screenHeiht
								);
						canvas.drawBitmap(viewBg, null, rect, paint);
						Matrix matrix = new Matrix();
						matrix.postRotate((rotate += 2) % 360f,
								Windmill.getWidth() / 2,
								Windmill.getHeight() / 2);
						
						int _dy = (int) (500 /percentumH()); //500是风车基点到背景定点的像素
						matrix.postTranslate(0, (_dy - (Windmill.getHeight()/2)));
						canvas.drawBitmap(Windmill, matrix, paint);

						int _dx = (int) (250 / percentumW());//250是风车基点左侧像素
						canvas.drawBitmap(windPoint,_dx-windPoint.getWidth()/2,_dy-windPoint.getHeight()/2,paint);
						Thread.sleep(3);
					}
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} finally {
					if (canvas != null) {
						holder.unlockCanvasAndPost(canvas);
					}
				}

			}

		}

	}

	public void setRunning(boolean state) {
		isRunning = state;

	}

	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub

	}

	@Override
	public void surfaceCreated(SurfaceHolder arg0) {

		new Thread(this).start();
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder arg0) {
		// TODO Auto-generated method stub
		isRunning = false;

	}

}

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        WindmillView view=new WindmillView(this);
		setContentView(view);
    }

整个过程:继承SurfaceView并实现SurfaceHolder.Callback接口 ----> SurfaceView.getHolder()获得SurfaceHolder对象 ---->SurfaceHolder.lockCanvas()获得Canvas对象并锁定画布----> Canvas绘画 ---->SurfaceHolder.unlockCanvasAndPost(Canvas canvas)结束锁定画图,并提交改变,将图形显示。

* @author 张兴业
* http://blog.csdn.net/xyz_lmn
* iOS入门群:83702688
* android开发进阶群:241395671
* 我的新浪微博:@张兴业TBOW
*/

Android使用SurfaceView实现墨迹天气的风车效果第1张

参考:

http://www.cnblogs.com/plokmju/p/android_SurfaceView.html

http://developer.android.com/reference/android/view/SurfaceView.html

http://blog.csdn.net/luoshengyang/article/details/8661317

http://blog.csdn.net/hellogv/article/details/5986835

http://developer.android.com/reference/android/view/SurfaceHolder.html

免责声明:文章转载自《Android使用SurfaceView实现墨迹天气的风车效果》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇【git】合并分支发生冲突[系统资源攻略]CPU使用率和负载下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

windbg笔记

数据结构 Module EEClass MD(Method Desc) MT(Method desc Table) Object 基本命令 ~*e!clrstack 查看所有持有和等待锁的线程(的下一条要执行的代码) k 观察非托管堆栈 x <模块名>!*<函数名>* 查看符号 lm -f 显示已经载入的模块及其完整路径 sx...

Windows几种线程同步方法介绍

系统中的所有线程都要访问系统资源,一个线程霸占某个资源,其他需要该资源的线程就不能完成自己的任务;另外如一个线程在读取某块内存中的数据,而另一个线程又正在修改这块内存的值,这同样不是我们想要的,所以线程之间必须要有一套自己的规则,不然就凌乱了。线程之间需要通信,如A线程霸占某个B线程需要的资源X,在A占用期间,B线程只能等待,或处于挂起状态,当A线程用完资...

C#线程锁(上)

本篇从Monitor,Mutex,ManualResetEvent,AutoResetEvent,WaitHandler的类关系图开始,希 望通过本篇的介绍能对常见的线程同步方法有一个整体的认识,而对每种方式的使用细节,适用场合不会过多解释。让我们来看看这几个类的关系图:         1.lock关键字       lock是C#关键词,它将语句块标记...

多线程中Object的wait(),notify()和Condition的wait()和singal()对锁的关联

通常将共享资源的操作放置在Sysnchronized定义的区域内,这样当其他线程也获取到这个锁时,必须的等待锁被释放时才能进入该区域。Object为任意一个对象,每个对象都存在一个标志位,并具有两个值,分别为0和1。一个线程运行到同步块时,首先检查该对象的标志位,如果为0状态,表明此同步块中存在其他线程在运行。这时该线程处于就绪状态,直到处于同步块中的线程...

delphi 多线程 数据库

// 线程类unit Unit2; interface uses Classes; type TMyThread = class(TThread) private FUserName: string; FPassWord: string; FFlag: Boolean; procedure GetUserName(const Value: string);...

【转】CUDA程序优化要点

CUDA程序优化应该考虑的点:精度:只在关键步骤使用双精度,其他部分仍然使用单精度浮点以获得指令吞吐量和精度的平衡;    目前 GPU 的单精度性能要远远超过双精度性能,整数乘法、求模、求余等运算的指令吞吐量也较为有限。在科学计算中,由于需要处理的数据量巨大,往往采用双精度或者四精度才能获得可靠的结果,目前的 Tesla 架构还不能很好的满足高精度计算的...