surfacedestroyed的简单介绍

http://www.itjxue.com  2023-02-10 10:51  来源:未知  点击次数: 

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;

}

}

}

(责任编辑:IT教学网)

更多

推荐java认证文章