引用: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. 全屏
  3. Android(安卓)Material Design之CoordinatorLayout
  4. Android(安卓)打开浏览器的几种方法
  5. android onTouch()与onTouchEvent()的区别
  6. Android(安卓)JNI介绍
  7. 详解 Android(安卓)的 Activity 组件
  8. Android进程与线程基本知识
  9. Unity调用Android配置方法

随机推荐

  1. 关于android LinearLayout的比例布局
  2. Gridview的stretchMode详解附自动宽度
  3. Android进阶——Android事件分发机制之di
  4. android设置头像
  5. Android系统自带样式(@android:style/)
  6. Gridview的stretchMode详解附自动宽度
  7. Android系统自带样式(@android:style/)
  8. android TextView实现跑马灯效果
  9. [置顶] Android(Lollipop/5.0) Material
  10. android中系统自带主题集锦