引用:http://www.ophonesdn.com/article/show/278

http://developer.android.com/resources/samples/CubeLiveWallpaper/src/com/example/android/livecubes/cube1/CubeWallpaper1.html

标签 :动态壁纸LiveWallpapers时间壁纸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: view plain copy to clipboard print ?
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <manifestxmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.oms.LiveWall"android:versionCode="1"
  4. android:versionName="1.0">
  5. <applicationandroid:icon="@drawable/icon"android:label="@string/app_name">
  6. <serviceandroid:label="@string/app_name"android:name=".TimeWall"
  7. android:permission="android.permission.BIND_WALLPAPER">
  8. <intent-filter>
  9. <actionandroid:name="android.service.wallpaper.WallpaperService"/>
  10. </intent-filter>
  11. <meta-dataandroid:name="android.service.wallpaper"
  12. android:resource="@xml/alive_wall"/>
  13. </service>
  14. </application>
  15. <uses-sdkandroid: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代码结构如下: view plain copy to clipboard print ?
  1. publicclassTimeWallextendsWallpaperService{
  2. publicEngineonCreateEngine(){
  3. returnnewTimeEngine();
  4. }
  5. publicclassTimeEngineextendsEngine{
  6. //...morecode
  7. }
  8. }
类TimeEngine才是处理壁纸的核心类,我们会在类TimeEngine中加上自己的逻辑以完成壁纸的绘制、变化以及销毁。Engine的生命周期与大多数OPhone应用程序组件,比如activity类似,都是从onCreate()开始,在销毁时调用onDestory()方法。不同的是WallpaperService会提供一个surface用来绘制壁纸,所以在生命周期中多一个onSurfaceCreated与onSurfaceDestroyed的过程。下面是一个最简生命周期: 也就是说只要我们实现上面四个方法,一个基本的LiveWallpaper就可以完成了。让我们逐个看一下这几个方法的实现。 view plain copy to clipboard print ?
  1. @Override
  2. publicvoidonCreate(SurfaceHoldersurfaceHolder){
  3. super.onCreate(surfaceHolder);
  4. setTouchEventsEnabled(true);
  5. }
  6. @Override
  7. publicvoidonDestroy(){
  8. super.onDestroy();
  9. mHandler.removeMessages(DRAW);
  10. }
  11. @Override
  12. publicvoidonSurfaceCreated(SurfaceHolderholder){
  13. super.onSurfaceCreated(holder);
  14. mHandler.sendEmptyMessage(DRAW);
  15. }
  16. @Override
  17. publicvoidonSurfaceDestroyed(SurfaceHolderholder){
  18. super.onSurfaceDestroyed(holder);
  19. mHandler.removeMessages(DRAW);
  20. }
onCreate方法里,我们 setTouchEventsEnabled( true); 作用是使壁纸能响应 touch event,默认是false。TimeWall会在用户点击屏幕的时候画一个十字架,所以我们需要设置其为true。 可以看到我们在这四个方法里面做的事情非常简单,就是在 create时候发一个message,执行画面的绘制,在destory时remove这个消息。看一下mHandler的代码: view plain copy to clipboard print ?
  1. privateHandlermHandler=newHandler(){
  2. publicvoidhandleMessage(Messagemsg){
  3. switch(msg.what){
  4. caseDRAW:
  5. drawWall();
  6. break;
  7. }
  8. }
  9. };
方法 drawWall(): view plain copy to clipboard print ?
  1. privatevoiddrawWall(){
  2. SurfaceHolderholder=getSurfaceHolder();
  3. Canvascanvas=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的效果:

附件代码:

view plain copy to clipboard print ?
  1. packagecom.OPhonesdn.timewall;
  2. importjava.text.SimpleDateFormat;
  3. importjava.util.Date;
  4. importandroid.graphics.Canvas;
  5. importandroid.graphics.Color;
  6. importandroid.graphics.Paint;
  7. importandroid.os.Handler;
  8. importandroid.os.Message;
  9. importandroid.service.wallpaper.WallpaperService;
  10. importandroid.view.MotionEvent;
  11. importandroid.view.SurfaceHolder;
  12. publicclassTimeWallextendsWallpaperService{
  13. publicEngineonCreateEngine(){
  14. returnnewTimeEngine();
  15. }
  16. publicclassTimeEngineextendsEngine{
  17. privatefinalfloatSTEP_X=2f;
  18. privatefinalfloatSTEP_Y=7f;
  19. privatefinalfloatSCOPE_LEFT=10f;
  20. privatefinalfloatSCOPE_RIGHT=110f;
  21. privatefinalfloatSCOPE_TOP=250f;
  22. privatefinalfloatSCOPE_BOTTOM=600f;
  23. privatefinalfloatRADIUS=20f;
  24. privatefinalintDIRECTION_1=1;//movetorighttopside
  25. privatefinalintDIRECTION_2=2;//movetorightbottomside
  26. privatefinalintDIRECTION_3=3;//movetoleftbottomside
  27. privatefinalintDIRECTION_4=4;//movetolefttopside
  28. privatefinalintDRAW=1;
  29. privatefloatmTouchX=-1f;
  30. privatefloatmTouchY=-1f;
  31. privatefloatmLocationX=0f;
  32. privatefloatmLocationY=400f;
  33. privateintmDirection=1;
  34. privatePaintmPaint=newPaint();
  35. privateHandlermHandler=newHandler(){
  36. publicvoidhandleMessage(Messagemsg){
  37. switch(msg.what){
  38. caseDRAW:
  39. drawWall();
  40. break;
  41. }
  42. }
  43. };
  44. publicTimeEngine(){
  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. publicvoidonCreate(SurfaceHoldersurfaceHolder){
  54. super.onCreate(surfaceHolder);
  55. setTouchEventsEnabled(true);
  56. }
  57. @Override
  58. publicvoidonDestroy(){
  59. super.onDestroy();
  60. mHandler.removeMessages(DRAW);
  61. }
  62. @Override
  63. publicvoidonSurfaceCreated(SurfaceHolderholder){
  64. super.onSurfaceCreated(holder);
  65. mHandler.sendEmptyMessage(DRAW);
  66. }
  67. @Override
  68. publicvoidonSurfaceDestroyed(SurfaceHolderholder){
  69. super.onSurfaceDestroyed(holder);
  70. mHandler.removeMessages(DRAW);
  71. }
  72. @Override
  73. publicvoidonTouchEvent(MotionEventevent){
  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. privatevoiddrawWall(){
  85. SurfaceHolderholder=getSurfaceHolder();
  86. Canvascanvas=holder.lockCanvas();
  87. drawTime(canvas);
  88. drawCross(canvas);
  89. holder.unlockCanvasAndPost(canvas);
  90. mHandler.removeMessages(DRAW);
  91. mHandler.sendEmptyMessageDelayed(DRAW,50);
  92. }
  93. privatevoiddrawTime(Canvasc){
  94. Datedate=newDate(System.currentTimeMillis());
  95. SimpleDateFormatsdf=newSimpleDateFormat("yyyy-MM-ddHH:mm:ss");
  96. StringstrDate=sdf.format(date);
  97. c.save();
  98. c.drawColor(0xff000000);
  99. c.drawText(strDate,mLocationX,mLocationY,mPaint);
  100. switch(mDirection){
  101. caseDIRECTION_1:
  102. mLocationX=mLocationX+STEP_X;
  103. mLocationY=mLocationY-STEP_Y;
  104. if(mLocationY<=SCOPE_TOP){
  105. mDirection=DIRECTION_2;
  106. }
  107. break;
  108. caseDIRECTION_2:
  109. mLocationX=mLocationX+STEP_X;
  110. mLocationY=mLocationY+STEP_Y;
  111. if(mLocationX>=SCOPE_RIGHT){
  112. mDirection=DIRECTION_3;
  113. }
  114. break;
  115. caseDIRECTION_3:
  116. mLocationX=mLocationX-STEP_X;
  117. mLocationY=mLocationY+STEP_Y;
  118. if(mLocationY>=SCOPE_BOTTOM){
  119. mDirection=DIRECTION_4;
  120. }
  121. break;
  122. caseDIRECTION_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. privatevoiddrawCross(Canvasc){
  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. }

更多相关文章

  1. android中的spinner动态加载内容
  2. Android 打开浏览器的几种方法
  3. Unity调用Android配置方法
  4. Android 滑动手势侦测方法介绍
  5. Android 动态logo bootanimation.zip 制作
  6. 安卓selector使用方法
  7. 应用界面主题Theme使用方法
  8. Android 使用html做UI的方法---js与java的相互调用

随机推荐

  1. 布局 遗忘 整理
  2. Android:res之selector背景选择器
  3. Android(安卓)Tutorial(3)Android(安卓)M
  4. Gradle sync failed: Could not GET 'htt
  5. android 加载图片到gallery
  6. 可点击价格走势图-贝塞尔曲线
  7. android布局属性详解
  8. android预定义样式简述
  9. Cordova 3.x 源码分析(6) -- cordova.js本
  10. Android(安卓)Home's favorite.xml