天 下

士不可以不弘毅 任重而道远

【Android开发学习08】SurfaceView显示动画效果

基础知识:

SurfaceView继承自View,View负责在主线程中更新动画,而SurfaceView是在一个新线程中更新动画。

SurfaceView类的主要方法:
// 在SurfaceView创建时调用
pubilic abstract void surfaceCreated(SurfaceHolder holder)
// 在SurfaceView改变时调用
pubilic abstract void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
// 在SurfaceView销毁时调用
pubilic abstract void surfaceDestroyed(SurfaceHolder holder)
// 绘制SurfaceView画面
protected void onDraw(Canvas canvas)
(参数canvas是该SurfaceView的画笔,每一次SurfaceView中画面改变都是调用了该方法)


二、实现效果:

首先有一副图片从屏幕的左下角开始向右上方运动,当图片上沿与手机屏幕上沿相撞时,图片的水平速度大小与方向均不变,竖直方向上速度大小不变,
方向相反;当下沿相撞后,同样效果,直到图片飞出屏幕。之后,屏幕渐渐地显示一幅图片。


三、编程实现:

1. 界面编辑(res\layout\main.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />
</LinearLayout>


2. 代码编辑:

(\src\wyf\zcl\MyActivity.java)

package wyf.zcl;
/*
 * 	该例子演示surfaceView中简单场景的绘制
 * 	MyActivity.java		为程序的主Activity
 * 	MySurfaceView.java	为程序的SurfaceView类
 * 	Constant.java		常量类,将常量全部写在该类中
 * 	OnDrawThread.java	该类的作用是时时刷新onDraw,进行画面的重绘
 * 	PicRunThread.java	该类是控制duke图片运动的类
 * */
import android.app.Activity;						//引入相关包
import android.content.pm.ActivityInfo;				//引入相关包
import android.os.Bundle;							//引入相关包
import android.view.Window;							//引入相关包
import android.view.WindowManager;					//引入相关包	
public class MyActivity extends Activity {
    /** Called when the activity is first created. */
	private MySurfaceView msv;			//得到surfaceView的引用
    @Override
    public void onCreate(Bundle savedInstanceState) {	//Activity的生命周期函数,该函数是在程序创建时调用
        super.onCreate(savedInstanceState);
        msv=new MySurfaceView(MyActivity.this);			//实例化MySurfaceView的对象
		requestWindowFeature(Window.FEATURE_NO_TITLE);	//设置屏幕显示没有title栏 
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN ,  
		              WindowManager.LayoutParams.FLAG_FULLSCREEN);	//设置全屏
		//设置只允许横屏
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        setContentView(msv);							//设置Activity显示的内容为msv
    }
}

(\src\wyf\zcl\Constant.java)

package wyf.zcl;
import android.view.Display;
//Constant.java		常量类,将常量全部写在该类中
public class Constant {
	public static int SCREENWIDTH=480;	//屏幕宽(本程序为横屏)
	public static int SCREENHEIGHT=320;		//屏幕高
	public static int PICWIDTH=64;			//图片宽度
	public static int PICHEIGHT=64;			//图片高度
	public static int ONDRAWSPEED=30;		//onDraw线程类的绘制间隔时间
	public static float PICXSPEED=1.5f;		//图片水平移动速度
	public static float PICYSPEED=2;		//图片垂直移动速度
	public static int PICRUNSPEED=30;		//图片的运动线程的刷新速度
	public static int PICALPHASPEED=20;	//图片渐暗效果演示刷新速度
}

(\src\wyf\zcl\MySurfaceView.java)

package wyf.zcl;
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.view.Display;					//引入相关包
import android.view.SurfaceHolder;				//引入相关包
import android.view.SurfaceView;				//引入相关包
public class MySurfaceView extends SurfaceView
implements SurfaceHolder.Callback{			
	//此处实现SurfaceHolder.Callback接口,为surfaceView添加生命周期回调函数
	int dy=Display.DEFAULT_DISPLAY;
	MyActivity ma;							//得到MyActivity的引用
	Paint paint;							//画笔的引用
	OnDrawThread odt;						//OnDrawThread类引用
	PicRunThread prt;						//图片运动的Thread类引用
	private float picX=0;						//图片x坐标
	private float picY=0;						//图片y坐标
	boolean picAlphaFlag=false;					//图片变暗效果的标记,false为不显示,true为显示。
	int picAlphaNum=0;							//图片变暗效果中画笔的alpha值
	public MySurfaceView(Context context) {
		super(context);
		this.ma=(MyActivity) context;			
		//将ma的引用指向调用了该Surfaceview类构造器方法的对象,本例为MyActivity
		this.getHolder().addCallback(this);		//注册回调接口
		paint=new Paint();						//实例化画笔
		odt=new OnDrawThread(this);				//实例化OnDrawThread类
		prt=new PicRunThread(this);				//实例化PicRunThread类
		prt.start();
	}
	public void setPicX(float picX) {			//图片x坐标的设置器
		this.picX = picX;
	}
	public void setPicY(float picY) {			//图片y坐标的设置器
		this.picY = picY;
	}
	public void setPicAlphaNum(int picAlphaNum) {//图片变暗效果alpha参数设置器
		this.picAlphaNum = picAlphaNum;
	}
	@Override
	protected void onDraw(Canvas canvas) {	//onDraw方法,此方法用于绘制图像,图形等
		super.onDraw(canvas);
		paint.setColor(Color.WHITE);		//设置画笔为白色
		canvas.drawRect(0, 0, Constant.SCREENWIDTH, Constant.SCREENHEIGHT, paint);
		//此处画了一个白色的全屏幕的矩形,目的是设置背景为白色,同时每次重绘时清除背景
		//进行平面贴图
		Bitmap bitmapDuke=BitmapFactory.decodeResource(ma.getResources(), R.drawable.duke);
		canvas.drawBitmap(bitmapDuke, picX, picY, paint);
		//图片渐暗效果
		if(picAlphaFlag){
			Bitmap bitmapBG=BitmapFactory.decodeResource(ma.getResources(), R.drawable.jpg1);
			paint.setAlpha(picAlphaNum);
			canvas.drawBitmap(bitmapBG, 0,0, paint);
		}
	}
	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {			//此方法为当surfaceView改变时调用,如屏幕大小改变。
	}
	@Override
	public void surfaceCreated(SurfaceHolder holder) {//此方法为在surfaceView创建时调用
		odt.start();				//启动onDraw的绘制线程
	}
	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {//此方法为在surfaceView销毁前调用
	}
}

(\src\wyf\zcl\OnDrawThread.java)

package wyf.zcl;
import android.graphics.Canvas;					//引入相关包
import android.view.SurfaceHolder;				//引入相关包
//该类的作用是时时刷新onDraw,进行画面的重绘
public class OnDrawThread extends Thread{
	MySurfaceView msv;		//得到MySurfaceView的引用
	SurfaceHolder sh;		//SurfaceHolder引用
	public OnDrawThread(MySurfaceView msv) {
		super();
		this.msv = msv;			//构造方法中,将msv引用指向调用了该类的MySurfaceView的对象
		sh=msv.getHolder();
	}
	@Override
	public void run() {
		super.run();
		Canvas canvas = null;	//Canvas的引用
		while(true){
			try{
				canvas=sh.lockCanvas(null);			//将canvas的引用指向surfaceView的canvas的对象
				synchronized(this.sh){				//绘制过程,可能带来同步方面的问题,加锁
					if(canvas!=null){
					msv.onDraw(canvas);
					}
				}
			}finally{
				try{
						if(sh!=null){
							sh.unlockCanvasAndPost(canvas);	//绘制完后解锁
						}
				}catch(Exception e){e.printStackTrace();}
			}
			try{
				Thread.sleep(Constant.ONDRAWSPEED);					//休息1秒钟
			}catch(Exception e){e.printStackTrace();}
		}
	}
}

(\src\wyf\zcl\PicRunThread.java)

package wyf.zcl;
//该类是控制duke图片运动的类
public class PicRunThread extends Thread{
	MySurfaceView msv;									//MySurfaceView的引用
	private float picX=0;			//图片x坐标
	private float picY=Constant.SCREENHEIGHT-Constant.PICHEIGHT;			//图片y坐标
	boolean yRunFlag=false;		//y方向上的运动标记,false时y=y+speed,true时y=y-speed
	int picAlphaNum=0;					//图片变暗效果中画笔的alpha值
	public PicRunThread(MySurfaceView msv) {
		super();
		this.msv = msv;			//将该线程类的引用指向调用其的MySurfaceView的对象
	}
	@Override
	public void run() {
		super.run();
		while(true){
			//控制duke图片的运动
			while(this.picX<Constant.SCREENWIDTH){			//当图片的左边完全超过屏幕的右边时,循环结束
				msv.setPicX(picX);
				msv.setPicY(picY);
				picX=picX+Constant.PICXSPEED;
				if(yRunFlag){//应该向上运动,自减
					picY=picY-Constant.PICYSPEED;
				}else{//应该向下运动,自加
					picY=picY+Constant.PICYSPEED;
				}
				if(picY<=0){									//到达屏幕上沿
					yRunFlag=false;
				}else if(picY>Constant.SCREENHEIGHT-Constant.PICHEIGHT){		//到达屏幕下沿
					yRunFlag=true;
				}
				try{
					Thread.sleep(Constant.PICRUNSPEED);
				}catch(Exception e){e.printStackTrace();}
			}
			//图片变暗效果演示
			msv.picAlphaFlag=true;							//开启图片变暗效果
			for(picAlphaNum=0;picAlphaNum<=255;picAlphaNum++){
				if(picAlphaNum==255){
					msv.picAlphaFlag=false;					//当图片变暗效果结束,标记重置
					picX=0;			//图片x坐标
					picY=Constant.SCREENHEIGHT-Constant.PICHEIGHT;			//图片y坐标
					System.out.println(msv.picAlphaFlag+"picX:"+picX+"picY:"+picY);
				}
				msv.setPicAlphaNum(picAlphaNum);
				try{
					Thread.sleep(Constant.PICALPHASPEED);
				}catch(Exception e){e.printStackTrace();}
			}
		}
	}
}

这部分代码对于我这个初学java的人来说比较吃力,但是硬着头皮看了两天,还是基本弄清了这个框架。

代码中涉及一些java的基础知识,我做了一点笔记,如下


[ extends ]:

一个类使用关键字extends继承其他类,关键字extends出现在类声明时的类名后,
extends后面跟着的是要继承的类的名称,extends实现了继承。在Java中的类只能继承一个类。




[ super ]:

B 继承 A ,B想调用A的方法,那么就可以 用super.A的方法。如果用中文解释:super就是父类的一个别名。



[ implements ]:

implements是一个类实现一个接口用的关键字,
他是用来实现接口中定义的抽象方法
。比如:people是一个接口,他里面有say这个方法。
public interface people()
{
   public say();
}
但是接口没有方法体。
只能通过一个具体的类去实现其中的方法体。
比如chinese这个类,就实现了people这个接口。
 public class chinese implements peopel{
   public say()
   {System.out.println("你好!");}
}





[ extendsimplements区别]:

extends是继承父类,只要那个类不是声明为final或者那个类定义为abstract的就能继承,
JAVA中不支持多重继承,但是可以用接口来实现,这样就要用到implements,继承只能继承一个类,
但implements可以实现多个接口,用逗号分开就行了 
比如 
class A extends B implements C,D,E








阅读更多
个人分类: Android应用开发
想对作者说点什么? 我来说一句

android SurfaceView实现人物动画

2012年09月12日 867KB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭