转自: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:
view plaincopy to clipboardprint?
  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代码结构如下:
view plaincopy to clipboardprint?
  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就可以完成了。让我们逐个看一下这几个方法的实现。
view plaincopy to clipboardprint?
  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的代码:
view plaincopy to clipboardprint?
  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():
view plaincopy to clipboardprint?
  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的效果:

附件代码:

view plaincopy to clipboardprint?
  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. }

OPhone动态壁纸探究相关推荐

  1. CubeWallpaperSet动态壁纸探究

    随着三星 Oscar的上市,流畅的操作,华丽的界面,OPhone 2.0的不俗表现不禁让人眼前一亮.作为OPhone 2.0一个新特性,动态壁纸(Live Wallpapers)为用户带来了更炫体验. ...

  2. Android中探究抖音短视频的动态壁纸功能以及拓展功能使用

    一.前言 最近玩抖音感觉都快废了,所以我决定不玩了我要学习所以先从他的动态壁纸学起,因为整个应用中也就是动态壁纸有点好玩的技术,而且也就是抖音能做这个功能,其他的短视频或许做不了比如快手如果要做你觉得 ...

  3. android 动态壁纸

    引用:http://www.ophonesdn.com/article/show/278 http://developer.android.com/resources/samples/CubeLive ...

  4. 动态壁纸,视频特效- Android

    -- 动态壁纸 Android中模仿探究抖音短视频的动态壁纸功能以及动态壁纸的拓展功能使用- https://blog.csdn.net/jiangwei0910410003/article/deta ...

  5. win10动态壁纸怎么设置_想把我的女朋友设置为动态壁纸:看过来,教你啊

    动态壁纸,最近已经越来越受用户的欢迎.炫酷的桌面效果非常动人,让人蠢蠢欲动,但有非常多的网友都不会设置win10动态桌面.所以今天小编就把设置win10动态桌面的方法告诉大家,下面就是设置win10动 ...

  6. Android自定义动态壁纸,Android自定义动态壁纸开发详解

    看到有些手机酷炫的动态壁纸,有没有好奇过他们是如何实现的,其实我们自己也可以实现. 一.动态壁纸原理 如果你了解使用过SurfaceView的话,那么开发一款动态壁纸对你来说其实非常简单. 动态壁纸的 ...

  7. android 动态label,Android仿抖音实现动态壁纸

    一.概述: 壁纸运行在一个Android服务之中,这个服务的名字叫做WallpaperService.当用户选择了一个壁纸之后,此壁纸所对应的WallpaperService便会启动并开始进行壁纸的绘 ...

  8. 动态壁纸安卓_安卓 高清 动态 壁纸

    Hi,各位大佬好!我是此木: 昨天刚过完"2020520",今天女神要我给她换个好看的.高清的.动态的.安卓的手机壁纸,我勒个去,要求还真不高,于是乎此木埋头半小时,终于找到一款符 ...

  9. Live Wallpaper HD for Mac(天气动态壁纸软件)

    Live Wallpaper HD for Mac是Mac平台上一款具有动态壁纸.详细天气预报.模拟时钟功能的天气动态壁纸软件,Live Wallpaper HD 中文破解版包含14张高清动态手机或电 ...

最新文章

  1. PyTorch入门与代码模板
  2. numpy.argwhere 返回的为索引值的array
  3. oracle创建分区表
  4. ML之LightGBM:基于titanic数据集利用LightGBM和shap算法实现数据特征的可解释性(量化特征对模型贡献度得分)
  5. 购物场景的对话流程如何实现?
  6. 并发编程之多线程基础-守护线程与非守护线程(四)
  7. The podfile
  8. 服务降级及dubbo中的实现示例
  9. jquery 文件预览功能
  10. java中filehandler_java – 如何配置特定FileHandler的属性
  11. ctfshow-WEB-web14( 利用数据库读写功能读取网站敏感文件)
  12. 中国大学MOOC-数据结构基础习题集、08-1、Talent and Virtue
  13. GRIDVIEW中实现上移下移的存储过程
  14. Android通过webservice连接SQLServer 详细教程(数据库+服务器+客户端)
  15. 洛谷3678:简单的数学题(画柿子+杜教筛)
  16. iOS开发百度导航SDK的使用入门
  17. discourse 安装_如何使用Discourse在半天之内建立内部团队论坛
  18. golang官网可以打开了 go语言
  19. 查找Windows和MacBook序列号
  20. loadrunner在win7破解提示:Cannot save the license information because acceses to the registry is denied的解

热门文章

  1. 华中师范大学计算机学院夏令营有感
  2. 电商API接口汇总,引领企业国际化
  3. [Unity3D]Unity3D游戏开发之换装系统的实现
  4. 设置电脑通电自动开机
  5. Jx_Python基础库入门_2: 基本数据类型
  6. HTTPConnectionPool Max retries exceeded with url
  7. 【HOG原理与训练】HOG(方向梯度直方图)
  8. unityt光线透射目标
  9. MythType插入公式后出现段标志符
  10. 智能优化算法:食肉植物算法-附代码