Android安卓动态墙纸编程

来源:互联网 发布:adobe bs软件 编辑:程序博客网 时间:2024/05/17 02:05

安卓从2.1开始支持动态墙纸编程,英文名字叫live wallpaper 。自己编写的动态壁纸必须从WallpaperService类派生,并且在重载其方法onCreateEngine里实现自己的动态效果。其代码如下,SimpleWallpaperEngine是我们基于Engine类派生的类:

public Engine onCreateEngine() {

       return new SimpleWallpaperEngine();

}

上面retun返回的代码就是我们用Engine类的派生类创建的对象,其实现过程使用surfaceview更新。所以要学习动态墙纸编程,最好是已经熟练的掌握了surfaceview使用技巧。在Engine类里,有很多方法,我们需要重载以下三个方法,

1.创建壁纸

public void onCreate(SurfaceHoldersurfaceHolder){...}

2.释放壁纸

public void onDestroy(){...}

3.VisibilityChanged是用来设置当前动态壁纸可见时显示动画。当其不可见时,壁纸会停止运行,不显示动画,代码如下:

@Overridepublic void onVisibilityChanged(boolean visible) {canDraw = visible;if (visible) {drawDroid(); // 自己的绘屏函数} else {handler.removeCallbacks(drawRequest); // 不可见时,移除回调}}

drawDroid是我写的一个简单的根据随机数画线的函数,代码如下:

private void drawDroid() {final SurfaceHolder holder = getSurfaceHolder();Canvas canvas = null;try {canvas = holder.lockCanvas();if (canvas != null) {paint.setColor(Color.BLUE);paint.setStrokeWidth(10);paint.setStyle(Style.STROKE);nx = (int) (rand.nextFloat() * virtualWidth);ny = (int) (rand.nextFloat() * virtualHeight);m_path.lineTo(nx, ny);canvas.drawPath(m_path, paint);}} finally {if (canvas != null) {holder.unlockCanvasAndPost(canvas);}}handler.removeCallbacks(drawRequest);if (canDraw) {handler.postDelayed(drawRequest, 33);}}

由于动画是使用surfacewive实现的,所以我们也要重载surfacewive的方法:

1.  建立

onSurfaceCreated

2.  释放

onSurfaceDestroyed

3.  大小变化,横竖屏操作,与用户交互时修改

onSurfaceChanged

如果需要添加用户交互,需要重载

public voidonTouchEvent(MotionEvent event)


surfacewive使用线程更新屏幕,我们可以使用Runnable接口创建一个线程,把我们的绘画函数放进去,并把他添加到窗口handler回调里,代码如下:

private final Runnable drawRequest = new Runnable() {@Overridepublic void run() {try {Thread.sleep(1000);drawDroid();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}};


完整的代码如下“:

package com.androidbook.simplelivewallpaper;import java.util.Random;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.graphics.Paint.Style;import android.os.Handler;import android.service.wallpaper.WallpaperService;import android.view.MotionEvent;import android.view.SurfaceHolder;public class SimpleDroidWallpaper extends WallpaperService {// private static final String DEBUG_TAG = "SimpleDroidWallpaper";private final Handler handler = new Handler();@Overridepublic Engine onCreateEngine() {return new SimpleWallpaperEngine();}class SimpleWallpaperEngine extends WallpaperService.Engine {boolean canDraw = true;private int virtualHeight;private int virtualWidth;Paint paint = new Paint();Path m_path = new Path();volatile int ox = 0, oy = 0, nx = 100, ny = 200;final Random rand = new Random();private final Runnable drawRequest = new Runnable() {@Overridepublic void run() {try {Thread.sleep(1000);drawDroid();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}};public SimpleWallpaperEngine() {m_path.lineTo(ox, oy);}@Overridepublic void onCreate(SurfaceHolder surfaceHolder) {super.onCreate(surfaceHolder);// When touch is enable, all MotionEvents are passed, even those// handled by other widgetssetTouchEventsEnabled(true);virtualHeight = getDesiredMinimumHeight();virtualWidth = getDesiredMinimumWidth();}@Overridepublic void onDestroy() {super.onDestroy();handler.removeCallbacks(drawRequest);}@Overridepublic void onVisibilityChanged(boolean visible) {canDraw = visible;if (visible) {drawDroid(); // 自己的绘屏函数} else {handler.removeCallbacks(drawRequest); // 不可见时,移除回调}}@Overridepublic void onOffsetsChanged(float xOffset, float yOffset,float xOffsetStep, float yOffsetStep, int xPixelOffset,int yPixelOffset) {super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep,xPixelOffset, yPixelOffset);}@Overridepublic void onSurfaceCreated(SurfaceHolder holder) {super.onSurfaceCreated(holder);}@Overridepublic void onSurfaceChanged(SurfaceHolder holder, int format,int width, int height) {super.onSurfaceChanged(holder, format, width, height);drawDroid();}@Overridepublic void onSurfaceDestroyed(SurfaceHolder holder) {super.onSurfaceDestroyed(holder);canDraw = false;handler.removeCallbacks(drawRequest);}private void drawDroid() {final SurfaceHolder holder = getSurfaceHolder();Canvas canvas = null;try {canvas = holder.lockCanvas();if (canvas != null) {paint.setColor(Color.BLUE);paint.setStrokeWidth(10);paint.setStyle(Style.STROKE);nx = (int) (rand.nextFloat() * virtualWidth);ny = (int) (rand.nextFloat() * virtualHeight);m_path.lineTo(nx, ny);canvas.drawPath(m_path, paint);}} finally {if (canvas != null) {holder.unlockCanvasAndPost(canvas);}}handler.removeCallbacks(drawRequest);if (canDraw) {handler.postDelayed(drawRequest, 33);}}@Overridepublic void onTouchEvent(MotionEvent event) {/* 添加触屏效果 */super.onTouchEvent(event);}}}

完整的XML文件如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.androidbook.simplelivewallpaper"
    android:versionCode="1"
    android:versionName="1.0">
    <application
        android:icon="@drawable/icon"
        android:label="@string/app_name"
        android:debuggable="true">
        <activity
            android:name=".SimpleLiveWallpaperMenuActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action
                    android:name="android.intent.action.MAIN" />
                <category
                    android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service
            android:label="@string/wallpaper_name"
            android:name="SimpleDroidWallpaper"
            android:permission="android.permission.BIND_WALLPAPER">
            <intent-filter>
                <action
                    android:name="android.service.wallpaper.WallpaperService" />
            </intent-filter>
            <meta-data
                android:name="android.service.wallpaper"
                android:resource="@xml/droid_wallpaper" />
        </service>
    </application>
    <uses-sdk
        android:minSdkVersion="7"
        android:targetSdkVersion="8" />
    <uses-feature
        android:name="android.software.live_wallpaper" />
</manifest>

其实我们这里创建的墙纸不需要Activity类,只是一种服务,是被墙纸管理程序调用的,所以对于eclipse生成的工程,你可以去掉XML中有关Activity窗口的声明,同时资源文件里你也可以去掉layout\main.xml文件和源代码文件夹里的Activit文件。当然,我们的墙纸如果支持自定义设置,那你也是需要Activit,那时你需要定义一个Activit供墙纸设置程序调用,以修改自定义墙纸默认设置。需要注意的是,设置文件需要在我们在/res/文件夹中新建一个名为xml的文件夹,名为livewallpaper.xml,内容为如下:

<?xml version="1.0" encoding="utf-8"?><wallpaper xmlns:android="http://schemas.android.com/apk/res/android"android:settingsActivity="ca.jvsh.livewallpaper.LiveWallpaperSettings"android:thumbnail="@drawable/icon"/>

然后把设置的值引入到你自己的墙纸类中调用。墙纸设置类一般会派生于PreferenceActivity,以在作用户操作后保存设置内容!



原创粉丝点击