• 周四. 4 月 23rd, 2026

物嫩软件资讯网

软件资讯来物嫩

OPhone动态壁纸探究

admin@wunen

4 月 25, 2025

转自:http://www.ophonesdn.com/article/show/278

OPhone动态壁纸探究

OPhone平台开发,2010-08-06 14:50:47

标签:

动态壁纸


Live


Wallpapers


时间壁纸


TimeWall

随着三星Oscar的上市,流畅的操作,华丽的界面,OPhone 2.0的不俗表现不禁让人眼前一亮。作为OPhone 2.0一个新特性,动态壁纸(Live Wallpapers)为用户带来了更炫体验。本文主要通过一个完整的时间壁纸(TimeWall)为大家介绍如何开发 Live Wallpapers。还没开发环境?赶紧去下载OPhone SDK 2.0吧!



1、 Live Wallpapers是什么?


oscar上有一个动态壁纸叫“天空草地”,用过一段时间,可以发现,随着时间的变化,壁纸的天空就会由蓝蓝青天变成繁星满天。看看效果:
为什么壁纸还有这么神奇的变化,这中间到底是什么在起作用?其实,一个
Live Wallpaper就是一个apk!也就是说,动态壁纸的实质是一个apk在后台不断地重绘壁纸,所以我们可以让小草长高,小鸟飞翔。
来看一下我们
TimeWall的AndoridManifest.xml:
  1. <?xml version=

    “1.0”

    encoding=

    “utf-8”

    ?>
  2. <manifest xmlns:android=

    “http://schemas.android.com/apk/res/android”

  3. package

    =

    “com.oms.LiveWall”

    android:versionCode=

    “1”
  4. android:versionName=

    “1.0”

    >
  5. <application android:icon=

    “@drawable/icon”

    android:label=

    “@string/app_name”

    >
  6. <service android:label=

    “@string/app_name”

    android:name=

    “.TimeWall”
  7. android:permission=

    “android.permission.BIND_WALLPAPER”

    >
  8. <intent-filter>
  9. <action android:name=

    “android.service.wallpaper.WallpaperService”

    />
  10. </intent-filter>
  11. <meta-data android:name=

    “android.service.wallpaper”
  12. android:resource=

    “@xml/alive_wall”

    />
  13. </service>
  14. </application>
  15. <uses-sdk android:minSdkVersion=

    “7”

    />
  16. </manifest>
原来如此简单,动态壁纸仅仅有一个
service就够了。其中
android:permission

=”android.permission.BIND_WALLPAPER”
是让该
service有能设置为壁纸的权限,没有的话该壁纸只能被预览。
<uses-sdk
android:minSdkVersion=

“7”

/>
告诉我们,如果你想开发一个
live wallpaper,必须是OPhone 2.0或者更高的版本。当然这也需要手机硬件的支持。

2、怎样实现WallpaperService?
WallpaperService与其他的
service唯一的不同就是,你必须要增加一个方法onCreateEngine(),它会返回一个WallpaperService.Engine,这个engine才是负责绘制壁纸以及响应与用户交互事件的核心部件。这个service代码结构如下:

  1. public


    class

    TimeWall

    extends

    WallpaperService {

  2. public

    Engine onCreateEngine() {

  3. return


    new

    TimeEngine();
  4. }

  5. public


    class

    TimeEngine

    extends

    Engine {

  6. // …more code
  7. }
  8. }
类TimeEngine才是处理壁纸的核心类,我们会在类TimeEngine中加上自己的逻辑以完成壁纸的绘制、变化以及销毁。Engine的生命周期与大多数OPhone应用程序组件,比如activity类似,都是从onCreate()开始,在销毁时调用onDestory()方法。不同的是WallpaperService会提供一个surface用来绘制壁纸,所以在生命周期中多一个onSurfaceCreated与onSurfaceDestroyed的过程。下面是一个最简生命周期:
也就是说只要我们实现上面四个方法,一个基本的LiveWallpaper就可以完成了。让我们逐个看一下这几个方法的实现。

  1. @Override

  2. public


    void

    onCreate(SurfaceHolder surfaceHolder) {

  3. super

    .onCreate(surfaceHolder);
  4. setTouchEventsEnabled(

    true

    );
  5. }

  6. @Override

  7. public


    void

    onDestroy() {

  8. super

    .onDestroy();
  9. mHandler.removeMessages(DRAW);
  10. }

  11. @Override

  12. public


    void

    onSurfaceCreated(SurfaceHolder holder) {

  13. super

    .onSurfaceCreated(holder);
  14. mHandler.sendEmptyMessage(DRAW);
  15. }

  16. @Override

  17. public


    void

    onSurfaceDestroyed(SurfaceHolder holder) {

  18. super

    .onSurfaceDestroyed(holder);
  19. mHandler.removeMessages(DRAW);
  20. }

onCreate方法里,我们
setTouchEventsEnabled(

true

);
作用是使壁纸能响应
touch event,默认是false。TimeWall会在用户点击屏幕的时候画一个十字架,所以我们需要设置其为true。
可以看到我们在这四个方法里面做的事情非常简单,就是在
create时候发一个message,执行画面的绘制,在destory时remove这个消息。看一下mHandler的代码:

  1. private

    Handler mHandler =

    new

    Handler() {

  2. public


    void

    handleMessage(Message msg) {

  3. switch

    (msg.what) {

  4. case

    DRAW:
  5. drawWall();

  6. break

    ;
  7. }
  8. }
  9. };
方法
drawWall():

  1. private


    void

    drawWall() {
  2. SurfaceHolder holder = getSurfaceHolder();
  3. Canvas canvas = holder.lockCanvas();
  4. drawTime(canvas);
  5. drawCross(canvas);
  6. holder.unlockCanvasAndPost(canvas);
  7. mHandler.removeMessages(DRAW);
  8. mHandler.sendEmptyMessageDelayed(DRAW,

    50

    );
  9. }
从上面可以看出,动态壁纸实际上就是不断刷新的静态壁纸,越华丽越流畅,
CPU就消耗越大,对于现在的本来电量就不怎么地的智能机来说,耗电也是很可观的。但是偶尔向朋友们炫一下还是绝对可行的。drawTime()与drawCross()的内容可以由家自己实现,在TimeWall里,它们比较简单。drawTime()是计算下一处Time String应该移动到的坐标,以及画出这个String。drawCross()的作用是在用户触发onTouchEvent时画一个十字架。因为TimeWall比较简单,如果大家自己实现的画图比较复杂,可以另外开启一个线程来刷新UI,否则有可能主线程被阻塞掉。(代码见附件)
看看TimeWall的效果:

附件代码:


  1. package

    com.OPhonesdn.timewall;

  2. import

    java.text.SimpleDateFormat;

  3. import

    java.util.Date;

  4. import

    android.graphics.Canvas;

  5. import

    android.graphics.Color;

  6. import

    android.graphics.Paint;

  7. import

    android.os.Handler;

  8. import

    android.os.Message;

  9. import

    android.service.wallpaper.WallpaperService;

  10. import

    android.view.MotionEvent;

  11. import

    android.view.SurfaceHolder;

  12. public


    class

    TimeWall

    extends

    WallpaperService {

  13. public

    Engine onCreateEngine() {

  14. return


    new

    TimeEngine();
  15. }

  16. public


    class

    TimeEngine

    extends

    Engine {

  17. private


    final


    float

    STEP_X = 2f;

  18. private


    final


    float

    STEP_Y = 7f;

  19. private


    final


    float

    SCOPE_LEFT = 10f;

  20. private


    final


    float

    SCOPE_RIGHT = 110f;

  21. private


    final


    float

    SCOPE_TOP = 250f;

  22. private


    final


    float

    SCOPE_BOTTOM = 600f;

  23. private


    final


    float

    RADIUS = 20f;

  24. private


    final


    int

    DIRECTION_1 =

    1

    ;

    // move to right top side

  25. private


    final


    int

    DIRECTION_2 =

    2

    ;

    // move to right bottom side

  26. private


    final


    int

    DIRECTION_3 =

    3

    ;

    // move to left bottom side

  27. private


    final


    int

    DIRECTION_4 =

    4

    ;

    // move to left top side

  28. private


    final


    int

    DRAW =

    1

    ;

  29. private


    float

    mTouchX = -1f;

  30. private


    float

    mTouchY = -1f;

  31. private


    float

    mLocationX = 0f;

  32. private


    float

    mLocationY = 400f;

  33. private


    int

    mDirection =

    1

    ;

  34. private

    Paint mPaint =

    new

    Paint();

  35. private

    Handler mHandler =

    new

    Handler() {

  36. public


    void

    handleMessage(Message msg) {

  37. switch

    (msg.what) {

  38. case

    DRAW:
  39. drawWall();

  40. break

    ;
  41. }
  42. }
  43. };

  44. public

    TimeEngine() {
  45. mPaint.setColor(Color.RED);
  46. mPaint.setAntiAlias(

    true

    );
  47. mPaint.setStrokeWidth(

    4

    );
  48. mPaint.setStrokeCap(Paint.Cap.BUTT);
  49. mPaint.setStyle(Paint.Style.STROKE);
  50. mPaint.setTextSize(

    40

    );
  51. }

  52. @Override

  53. public


    void

    onCreate(SurfaceHolder surfaceHolder) {

  54. super

    .onCreate(surfaceHolder);
  55. setTouchEventsEnabled(

    true

    );
  56. }

  57. @Override

  58. public


    void

    onDestroy() {

  59. super

    .onDestroy();
  60. mHandler.removeMessages(DRAW);
  61. }

  62. @Override

  63. public


    void

    onSurfaceCreated(SurfaceHolder holder) {

  64. super

    .onSurfaceCreated(holder);
  65. mHandler.sendEmptyMessage(DRAW);
  66. }

  67. @Override

  68. public


    void

    onSurfaceDestroyed(SurfaceHolder holder) {

  69. super

    .onSurfaceDestroyed(holder);
  70. mHandler.removeMessages(DRAW);
  71. }

  72. @Override

  73. public


    void

    onTouchEvent(MotionEvent event) {

  74. if

    (event.getAction() == MotionEvent.ACTION_MOVE
  75. || event.getAction() == MotionEvent.ACTION_DOWN) {
  76. mTouchX = event.getX();
  77. mTouchY = event.getY();
  78. }

    else

    {
  79. mTouchX = –

    1

    ;
  80. mTouchY = –

    1

    ;
  81. }

  82. super

    .onTouchEvent(event);
  83. }

  84. private


    void

    drawWall() {
  85. SurfaceHolder holder = getSurfaceHolder();
  86. Canvas canvas = holder.lockCanvas();
  87. drawTime(canvas);
  88. drawCross(canvas);
  89. holder.unlockCanvasAndPost(canvas);
  90. mHandler.removeMessages(DRAW);
  91. mHandler.sendEmptyMessageDelayed(DRAW,

    50

    );
  92. }

  93. private


    void

    drawTime(Canvas c) {
  94. Date date =

    new

    Date(System.currentTimeMillis());
  95. SimpleDateFormat sdf =

    new

    SimpleDateFormat(

    “yyyy-MM-dd HH:mm:ss”

    );
  96. String strDate = sdf.format(date);
  97. c.save();
  98. c.drawColor(

    0xff000000

    );
  99. c.drawText(strDate, mLocationX, mLocationY, mPaint);

  100. switch

    (mDirection) {

  101. case

    DIRECTION_1:
  102. mLocationX = mLocationX + STEP_X;
  103. mLocationY = mLocationY – STEP_Y;

  104. if

    (mLocationY <= SCOPE_TOP) {
  105. mDirection = DIRECTION_2;
  106. }

  107. break

    ;

  108. case

    DIRECTION_2:
  109. mLocationX = mLocationX + STEP_X;
  110. mLocationY = mLocationY + STEP_Y;

  111. if

    (mLocationX >= SCOPE_RIGHT) {
  112. mDirection = DIRECTION_3;
  113. }

  114. break

    ;

  115. case

    DIRECTION_3:
  116. mLocationX = mLocationX – STEP_X;
  117. mLocationY = mLocationY + STEP_Y;

  118. if

    (mLocationY >= SCOPE_BOTTOM) {
  119. mDirection = DIRECTION_4;
  120. }

  121. break

    ;

  122. case

    DIRECTION_4:
  123. mLocationX = mLocationX – STEP_X;
  124. mLocationY = mLocationY – STEP_Y;

  125. if

    (mLocationX <= SCOPE_LEFT) {
  126. mDirection = DIRECTION_1;
  127. }

  128. break

    ;
  129. }
  130. c.restore();
  131. }

  132. private


    void

    drawCross(Canvas c) {

  133. if

    (mTouchX >=

    0

    && mTouchY >=

    0

    ) {
  134. c.drawLine(mTouchX – RADIUS, mTouchY, mTouchX + RADIUS,
  135. mTouchY, mPaint);
  136. c.drawLine(mTouchX, mTouchY – RADIUS, mTouchX,
  137. mTouchY + RADIUS, mPaint);
  138. }
  139. }
  140. }
  141. }

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注