Android安卓动态墙纸编程

原创 2012年03月29日 16:19:53

安卓从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是用来设置当前动态壁纸可见时显示动画。当其不可见时,壁纸会停止运行,不显示动画,代码如下:

@Override
		public 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() {
			@Override
			public void run() {
				try {
					Thread.sleep(1000);
					drawDroid();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.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();

	@Override
	public 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() {
			@Override
			public void run() {
				try {
					Thread.sleep(1000);
					drawDroid();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		};

		public SimpleWallpaperEngine() {
			m_path.lineTo(ox, oy);
		}

		@Override
		public void onCreate(SurfaceHolder surfaceHolder) {
			super.onCreate(surfaceHolder);
			// When touch is enable, all MotionEvents are passed, even those
			// handled by other widgets
			setTouchEventsEnabled(true);
			virtualHeight = getDesiredMinimumHeight();
			virtualWidth = getDesiredMinimumWidth();
		}

		@Override
		public void onDestroy() {
			super.onDestroy();
			handler.removeCallbacks(drawRequest);
		}

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

		@Override
		public void onOffsetsChanged(float xOffset, float yOffset,
				float xOffsetStep, float yOffsetStep, int xPixelOffset,
				int yPixelOffset) {
			super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep,
					xPixelOffset, yPixelOffset);
		}

		@Override
		public void onSurfaceCreated(SurfaceHolder holder) {
			super.onSurfaceCreated(holder);
		}

		@Override
		public void onSurfaceChanged(SurfaceHolder holder, int format,
				int width, int height) {
			super.onSurfaceChanged(holder, format, width, height);

			drawDroid();
		}

		@Override
		public 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);
			}
		}

		@Override
		public 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,以在作用户操作后保存设置内容!



Android动态壁纸开发

res/xml/cube1.xml
  • pmtoam
  • pmtoam
  • 2013年11月26日 17:09
  • 1767

Android开发--动态图片的显示

本篇博客主要讲述了在java中显示动图的两种方式,分别是GifImageView和GifView,具体的使用方式见博客内容,有什么问题可评论中提出。...
  • weixin_39066666
  • weixin_39066666
  • 2017年06月07日 09:31
  • 431

Android开发中无处不在的设计模式——动态代理模式

继续更新设计模式系列,写这个模式的主要原因是最近看到了动态代理的代码。 先来回顾一下前5个模式: - Android开发中无处不在的设计模式——单例模式 - Android开发中无处不在的设...
  • sbsujjbcy
  • sbsujjbcy
  • 2016年01月21日 11:37
  • 7400

android 自定义View 动态绘制曲线图

1、定义视图类: package com.view; import java.util.ArrayList; import java.util.HashMap; import java.util....
  • jurken
  • jurken
  • 2014年12月12日 16:46
  • 1792

Android使用addView动态添加组件

在项目开发中,我们经常需要进行动态添加组件,其中可添加的部分有两项:布局和组件  其中,添加的布局主要有RelativeLayout型(相对布局)的和LinearLayout(线性布局)       ...
  • suwu150
  • suwu150
  • 2016年05月08日 22:51
  • 10177

Android7.0&8.0 默认壁纸修改

1.拷贝自定义壁纸 默认壁纸是default_wallpaper,在/frameworks/base/core/res下面。找到所以的default_wallpaper所在的地方,然后把我们自己的...
  • Aaron121314
  • Aaron121314
  • 2017年07月11日 16:29
  • 1929

android之socket编程实例

注意点:注册访问的网络权限;android中UI线程不能有访问网络的操作,否则会报android.os.NetworkOnMainThreadException的异常 客户端 packa...
  • x605940745
  • x605940745
  • 2013年11月28日 10:23
  • 130941

Android插件化学习之路(一)之动态加载综述

前段时间,公司项目完成了插件化的开发,自己也因此学习了很多Android插件化的知识,于是想把这些内容记录下来,本次带来Android插件化的第一篇:动态加载综述Android插件化学习之路(一)之动...
  • u012124438
  • u012124438
  • 2016年11月19日 21:58
  • 2845

Android开发学习之路--网络编程之初体验

一般手机都是需要上网的,一般我们的浏览器就是个webview。这里简单实现下下功能,先编写Android的layout布局: ...
  • eastmoon502136
  • eastmoon502136
  • 2016年02月19日 21:15
  • 7175

Android 6.0: 动态权限管理的解决方案

Android 6.0版本(Api 23)推出了很多新的特性, 大幅提升了用户体验, 同时也为程序员带来新的负担. 动态权限管理就是这样, 一方面让用户更加容易的控制自己的隐私, 一方面需要重新适配应...
  • u012515223
  • u012515223
  • 2016年01月26日 14:45
  • 39767
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android安卓动态墙纸编程
举报原因:
原因补充:

(最多只允许输入30个字)