当前位置:操作系统 > 安卓/Android >>

[Android] SurfaceView使用实例

同样,先上效果图如下:

 


效果图中,抛物线的动画即是由SurfaceView实现的。底部栏中的文字翻转详情相关帖子:
[Android] 文字翻转动画的实现
需求:
1.实现抛物线动画
   1.1 设计物理模型,能够根据时间变量计算出某个时刻图片的X/Y坐标。
   1.2 将图片高频率(相比于UI线程的缓慢而言)刷新到界面中。这儿需要实现将脏界面清屏及刷新操作。
2.文字翻转动画(已解决,见上面的帖子链接)

下面来逐一解决所提出的问题。

-----------------------------------------------------------------------------
分隔线内容与Android无关,请慎读,勿拍砖。谢啦

 


1.1 设计物理模型,如果大家还记得初中物理时,这并不难。自己写的草稿图见下:

 

可以有:图片要从高度为H的位置下落,并且第一次与X轴碰撞时会出现能量损失,至原来的N%。并且我们需要图片的最终落点离起始位置在X轴上的位移为L,默认存在重力加速度g。
详细的物理分析见上图啦,下面只说代码中如何实现,相关代码在PhysicalTool.java。
第一次下落过程所耗时t1与高度height会有如下关系:


[java]
t1 = Math.sqrt(2 * height * 1.0d / GRAVITY); 

第一次与X轴碰撞后上升至最高点的耗时t2与高度 N%*height会有:

[java] 
t2 = Math.sqrt((1 - WASTAGE) * 2 * height * 1.0d / GRAVITY); 

那么总的动画时间为(t1 + t2 + t2),则水平位移速度有(width为X轴总位移):

[java] 
velocity = width * 1.0d / (t1 + 2 * t2); 

则根据时间计算图片的实时坐标有:
PhysicalTool.comput()

[java] 
double used = (System.currentTimeMillis() - startTime) * 1.0d / 1000; 
x = velocity * used; 
if (0 <= used && used < t1) { 
        y = height - 0.5d * GRAVITY * used * used; 
} else if (t1 <= used && used < (t1 + t2)) { 
        double tmp = t1 + t2 - used; 
        y = (1 - WASTAGE) * height - 0.5d * GRAVITY * tmp * tmp; 
} else if ((t1 + t2) <= used && used < (t1 + 2 * t2)) { 
        double tmp = used - t1 - t2; 
        y = (1 - WASTAGE) * height - 0.5d * GRAVITY * tmp * tmp; 

Android无关内容结束了。
----------------------------------------------------------------------------------------

1.2 SurfaceView刷新界面
        SurfaceView是一个特殊的UI组件,特殊在于它能够使用非UI线程刷新界面。至于为何具有此特殊性,将在另一个帖子"SurfaceView 相关知识笔记"中讨论,该帖子将讲述SurfaceView、Surface、ViewRoot、Window Manager/Window、Canvas等之间的关系。
       
        使用SurfaceView需要自定义组件继承该类,并实现SurfaceHolder.Callback,该回调提供了三个方法:

[java] 
surfaceCreated()//通知Surface已被创建,可以在此处启动动画线程 
surfaceChanged()//通知Surface已改变 
surfaceDestroyed()//通知Surface已被销毁,可以在此处终止动画线程 

SurfaceView使用有一个原则,即该界面操作必须在surfaceCreated之后及surfaceDestroyed之前。该回调的监听通过SurfaceHolder设置。代码如下:
[java] 
//于SurfaceView类中,该类实现SurfaceHolder.Callback接口,如本例中的ParabolaView 
SurfaceHolder holder = getHolder(); 
holder.addCallback(this); 

示例代码中,通过启动DrawThread调用handleThread()实现对SurfaceView的刷新。
        刷新界面首先需要执行holder.lockCanvas()锁定Canvas并获得Canvas实例,然后进行界面更新操作,最后结束锁定Canvas,提交界面更改,至Surface最终显示在屏幕上。
        代码如下:
[java] 
canvas = holder.lockCanvas(); 
… … … …  
… … … …  
canvas.drawBitmap(bitmap, x, y, paint); 
holder.unlockCanvasAndPost(canvas); 


本例中,需要清除屏幕脏区域,出于简便的做法,是将整个SurfaceView背景重复地设置为透明,代码为:

[java] 
canvas.drawColor(Color.TRANSPARENT, android.graphics.PorterDuff.Mode.CLEAR); 

对于SurfaceView的操作,下面这个链接讲述得更详细,更易理解,推荐去看下:
Android开发之SurfaceView
惯例,Java代码如下,XML请自行实现
本文由Sodino所有,转载请注明出处:http://blog.csdn.net/sodino/article/details/7704084


[java] 
ActSurfaceView.java 
 
package lab.sodino.surfaceview; 
 
import lab.sodino.surfaceview.RotateAnimation.InterpolatedTimeListener; 
import android.app.Activity; 
import android.graphics.BitmapFactory; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Handler.Callback; 
import android.os.Message; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.view.ViewGroup; 
import android.widget.Button; 
import android.widget.TextView; 
 
public class ActSurfaceView extends Activity implements OnClickListener, ParabolaView.ParabolaListener, Callback, 
                InterpolatedTimeListener { 
        public static final int REFRESH_TEXTVIEW = 1; 
        private Button btnStartAnimation; 
        /** 动画界面。 */ 
        private ParabolaView parabolaView; 
        /** 购物车处显示购物数量的TextView。 */ 
        private TextView txtNumber; 
        /** 购物车中的数量。 */ 
        private int number; 
        private Handler handler; 
        /** TextNumber是否允许显示最新的数字。 */ 
        private boolean enableRefresh; 
 
        public void onCreate(Bundle savedInstanceState) { 
                super.onCreate(savedInstanceState); 
                setContentView(R.layout.main); 
 
                handler = new Handler(this); 
 
                number = 0; 
 
                btnStartAnimation = (Button) findViewById(R.id.btnStartAnim); 
                btnStartAnimation.setOnClickListener(this); 
 
                parabolaView = (ParabolaView) findViewById(R.id.surfaceView); 
                parabolaView.setParabolaListener(this); 
 
         

补充:移动开发 , Android ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,