【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 SurfaceViewimplements 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类构造器方法的对象,本例为MyActivitythis.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;}@Overrideprotected 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);}}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {//此方法为当surfaceView改变时调用,如屏幕大小改变。}@Overridepublic void surfaceCreated(SurfaceHolder holder) {//此方法为在surfaceView创建时调用odt.start();//启动onDraw的绘制线程}@Overridepublic 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();}@Overridepublic 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-speedint picAlphaNum=0;//图片变暗效果中画笔的alpha值public PicRunThread(MySurfaceView msv) {super();this.msv = msv;//将该线程类的引用指向调用其的MySurfaceView的对象}@Overridepublic 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("你好!");}
}
[ extends和implements区别]:
extends是继承父类,只要那个类不是声明为final或者那个类定义为abstract的就能继承,JAVA中不支持多重继承,但是可以用接口来实现,这样就要用到implements,继承只能继承一个类,但implements可以实现多个接口,用逗号分开就行了 比如 class A extends B implements C,D,E
更多相关文章
- Android中bindService基本使用方法概述
- Unity 编辑器环境下不能正确加载Android Assetbundle 中的 Shade
- Android调用系统相机和相册,解决图片方向问题,压缩图片
- Android 控件之ImageSwitcher图片切换器