surfacedestroyed的简单介绍
surfaceDestroyed什么时候执行
1、SurfaceView与MediaPlayer配合使用:[html] view plain copymediaPlayer.setDisplay(surfaceview.getHolder());//这一步是关键,制定用于显示视频的SurfaceView对象(通过setDisplay()) 2、维护SurfaceView:通过sufaceView.Callback接口实现,需要实现其三个方法:void surfaceDestroyed(SurfaceHolder holder):当SurfaceHolder被销毁的时候回调。void surfaceCreated(SurfaceHolder holder):当SurfaceHolder被创建的时候回调。void surfaceChange(SurfaceHolder holder):当SurfaceHolder的尺寸发生变化的时候被回调。3、通过MediaPlayer类的Play()与Pause()方法实现视频的暂停与播放。4、对进度条的布局优化:

动态桌面运行原理
:原理
动态壁纸为:在手机上点击 Menu→Wallpapers→Live wallpapers→然后打开自己的程序。建个最简单的动态壁纸的步骤如下:
1.在rex/xml中新建一个.xml.其中注册一个wallpaper.假设这个名字为ab.xml(下文要用到,可随意设置,没要求)
最简单的就是写 这一句,这样的话打开动态壁纸就会出现只出现一个按钮(左图),一般我们不这样做,要像右图这样子。
Android 动态壁纸原理 及 例子 Android 动态壁纸原理 及 例子
若动态壁纸"设置..."(Setting...)你想连接Activity,也在这里指定,比如:
android:settingsActivity="com.birbeck.wallpaperslideshow.SettingsActivity" (这个一般是继承了PreferenceActivity类的Activity。就是首选项模式的类),要设置了这个属性,就会如有图所示了。
Android 动态壁纸原理 及 例子
如上截图是手机上的动态壁纸列表,你也可以通过android:description=“XXX”来设置描述,通过anroid:thumbnail="XX"来设置该动态壁纸的图片。
2.接下来要在manifest中注册一个service。
XXX
在这个servier中要指定你继承WallpaperService类的路径,指定1中设置的xml,设置广播,设置允许权限等。比如:
通过android:name="com.bn.ex12f.Sample12_6_WallPaper"指定继承WallpaperService的类 ,
通过android:permission="android.permission.BIND_WALLPAPER"是让该service有能设置为壁纸的权限,没有的话该壁纸只能被预览。
这一种还必须设置一个,用来监听Android系统发出的动态壁纸的广播。
3、怎样实现WallpaperService?
WallpaperService与其他的service唯一的不同就是,你必须要增加一个方法onCreateEngine(),它会返回一个WallpaperService.Engine,这个engine才是负责绘制壁纸以及响应与用户交互事件的核心部件。这个service代码结构如下:
view plaincopy to clipboardprint?
public class TimeWall extends WallpaperService {
public Engine onCreateEngine() {
return new TimeEngine();
}
public class TimeEngine extends Engine {
// ...more code
}
}
在这个方法里只需返回一个Engine的子类对象就可以了。所以重头戏,写动态壁纸程序的主要工作量就是实现Engine的子类。
类TimeEngine才是处理壁纸的核心类,我们会在类TimeEngine中加上自己的逻辑以完成壁纸的绘制、变化以及销毁。Engine的生命周期与大多数OPhone应用程序组件,比如activity类似,都是从onCreate()开始,在销毁时调用onDestory()方法。不同的是WallpaperService会提供一个surface用来绘制壁纸,所以在生命周期中多一个onSurfaceCreated与onSurfaceDestroyed的过程。下面是一个最简生命周期:
也就是说只要我们实现上面四个方法,一个基本的LiveWallpaper就可以完成了。
4.实现Engine的子类
简而言之,该类的作用就是让你去实现动态壁纸的具体代码。以上三点可认为是格式化的一些东西。这个类不需要强制继承任何方法,现在简述一下一般要重写的方法的功能。
public void onCreate(SurfaceHolder surfaceHolder){...}
public void onDestroy(){...}这俩方法就不说明了
public void onVisibilityChanged(boolean visible)
{
if(visible)//如果可见
{
...
}
else//如果不可见
{
...
}
}该方法作用是当前动态壁纸可见时要画图。重写这个方法一般如以上格式所示。
public void onSurfaceCreated(SurfaceHolder holder) //重写onSurfaceCreated方法
{
super.onSurfaceCreated(holder);//调用父类对应方法
}该方法是应用程序第一次创建时要调用。可在这个方法里调用父类对应方法。该方法执行完毕后系统会立即调用onSurfaceChanged方法(如下)。若在这里调用父类对应方法,那么就在onSurfaceChanged中实现主要功能。
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
...
}该方法有两个用处。1.若动态壁纸要随着横屏竖屏而切换可在这里写。2.想和用户交互的话,比如用户滑动屏幕时,点击屏幕时等。3.注意:onSurfaceCreated调用之后会立即调用该方法。
opengl es怎么实现纹理变化
(0)在类的成员函数里,定义一个int textureId,作为纹理的id;
(1)在onsurfacecreated相关初始化的函数里,创建一张纹理
1.1 glGenTexture申请一个id
1.2 bind texture
1.3 glTexImage()分配一张空纹理
1.4 set texture parameter 设置纹理相关参数
(2)在onDrawFrame等回调函数里
2.1 bind texture帮顶纹理
2.2 glTexSubImage更新纹理,用你每帧截取的画面
2.3 绘制
(3)在onsurfacedestroyed相关函数,释放资源。
给你写段伪代码~~(0)在类的成员函数里,定义一个int textureId,作为纹理的id;(1)在onsurfacecreated相关初始化的函数里,创建一张纹理1.1 glGenTexture申请一个id1.2 bind texture1.3 glTexImage()分配一张空纹理1.4 set texture parameter 设置纹理相关参数(2)在onDrawFrame等回调函数里2.1 bind texture帮顶纹理2.2 glTexSubImage更新纹理,用你每帧截取的画面2.3 绘制(3)在onsurfacedestroyed相关函数,释放资源。
仅供参考。
surfaceDestroyed什么时候被调用
大家都知道surface是surfaceview的一个专门用于画图的接口,所以当surfaceview的对象销毁时,surface一定也销毁,这时surfaceDestroyed一定会调用。
有两个继承surfaceview的类分别是 svA和svB这连个类分别定义了各自的对象AView和BView。假设现在activity设置的是AView这个对象,也就是说现在用AView的surface呢。如果这时在activity执行一下代码:
setContentView(Bview);
这时,Aview中的surfaceDestroyed就会被调用,因为现在Bview的surface要接管Aview中的surface,Aview的surface就会销毁,这时必然要调用A的surfaceDestroyed函数。
android想要画一个抛物线,怎么实现
效果图中,抛物线的动画即是由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] view plaincopy
t1 = Math.sqrt(2 * height * 1.0d / GRAVITY);
[java] view plain copy
t1 = Math.sqrt(2 * height * 1.0d / GRAVITY);
第一次与X轴碰撞后上升至最高点的耗时t2与高度 N%*height会有:
[java] view plaincopy
t2 = Math.sqrt((1 - WASTAGE) * 2 * height * 1.0d / GRAVITY);
[java] view plain copy
t2 = Math.sqrt((1 - WASTAGE) * 2 * height * 1.0d / GRAVITY);
那么总的动画时间为(t1 + t2 + t2),则水平位移速度有(width为X轴总位移):
[java] view plaincopy
velocity = width * 1.0d / (t1 + 2 * t2);
[java] view plain copy
velocity = width * 1.0d / (t1 + 2 * t2);
则根据时间计算图片的实时坐标有:
PhysicalTool.comput()
[java] view plaincopy
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;
}
[java] view plain copy
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] view plaincopy
surfaceCreated()//通知Surface已被创建,可以在此处启动动画线程
surfaceChanged()//通知Surface已改变
surfaceDestroyed()//通知Surface已被销毁,可以在此处终止动画线程
[java] view plain copy
surfaceCreated()//通知Surface已被创建,可以在此处启动动画线程
surfaceChanged()//通知Surface已改变
surfaceDestroyed()//通知Surface已被销毁,可以在此处终止动画线程
SurfaceView使用有一个原则,即该界面操作必须在surfaceCreated之后及surfaceDestroyed之前。该回调的监听通过SurfaceHolder设置。代码如下:
[java] view plaincopy
//于SurfaceView类中,该类实现SurfaceHolder.Callback接口,如本例中的ParabolaView
SurfaceHolder holder = getHolder();
holder.addCallback(this);
[java] view plain copy
//于SurfaceView类中,该类实现SurfaceHolder.Callback接口,如本例中的ParabolaView
SurfaceHolder holder = getHolder();
holder.addCallback(this);
示例代码中,通过启动DrawThread调用handleThread()实现对SurfaceView的刷新。
刷新界面首先需要执行holder.lockCanvas()锁定Canvas并获得Canvas实例,然后进行界面更新操作,最后结束锁定Canvas,提交界面更改,至Surface最终显示在屏幕上。
代码如下:
[java] view plaincopy
canvas = holder.lockCanvas();
… … … …
… … … …
canvas.drawBitmap(bitmap, x, y, paint);
holder.unlockCanvasAndPost(canvas);
[java] view plain copy
canvas = holder.lockCanvas();
… … … …
… … … …
canvas.drawBitmap(bitmap, x, y, paint);
holder.unlockCanvasAndPost(canvas);
本例中,需要清除屏幕脏区域,出于简便的做法,是将整个SurfaceView背景重复地设置为透明,代码为:
[java] view plaincopy
canvas.drawColor(Color.TRANSPARENT, android.graphics.PorterDuff.Mode.CLEAR);
[java] view plain copy
canvas.drawColor(Color.TRANSPARENT, android.graphics.PorterDuff.Mode.CLEAR);
对于SurfaceView的操作,下面这个链接讲述得更详细,更易理解,推荐去看下:
Android开发之SurfaceView
惯例,Java代码如下,XML请自行实现
本文由Sodino所有,转载请注明出处:
[java] view plaincopy
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);
txtNumber = (TextView) findViewById(R.id.txtNumber);
}
public void onClick(View v) {
if (v == btnStartAnimation) {
LogOut.out(this, "isShowMovie:" + parabolaView.isShowMovie());
if (parabolaView.isShowMovie() == false) {
number++;
enableRefresh = true;
parabolaView.setIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon));
// 设置起始Y轴高度和终止X轴位移
parabolaView.setParams(200, ((ViewGroup) txtNumber.getParent()).getLeft());
parabolaView.showMovie();
}
}
}
public void onParabolaStart(ParabolaView view) {
}
public void onParabolaEnd(ParabolaView view) {
handler.sendEmptyMessage(REFRESH_TEXTVIEW);
}
public boolean handleMessage(Message msg) {
switch (msg.what) {
case REFRESH_TEXTVIEW:
if (txtNumber.getVisibility() != View.VISIBLE) {
txtNumber.setVisibility(View.VISIBLE);
}
RotateAnimation anim = new RotateAnimation(txtNumber.getWidth() 1, txtNumber.getHeight() 1,
RotateAnimation.ROTATE_INCREASE);
anim.setInterpolatedTimeListener(this);
txtNumber.startAnimation(anim);
break;
}
return false;
}
@Override
public void interpolatedTime(float interpolatedTime) {
// 监听到翻转进度过半时,更新txtNumber显示内容。
if (enableRefresh interpolatedTime 0.5f) {
txtNumber.setText(Integer.toString(number));
// Log.d("ANDROID_LAB", "setNumber:" + number);
enableRefresh = false;
}
}
}