android 动态壁纸

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

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

标签 : 动态壁纸 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.    
  3.     public Engine onCreateEngine() {  
  4.         return new TimeEngine();  
  5.     }  
  6.    
  7.     public class TimeEngine extends Engine {  
  8.         // ...more code  
  9.     }  
  10. }  
类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.   
  7. @Override  
  8. public void onDestroy() {  
  9.     super.onDestroy();  
  10.     mHandler.removeMessages(DRAW);  
  11. }  
  12.   
  13. @Override  
  14. public void onSurfaceCreated(SurfaceHolder holder) {  
  15.     super.onSurfaceCreated(holder);  
  16.     mHandler.sendEmptyMessage(DRAW);  
  17. }  
  18.   
  19. @Override  
  20. public void onSurfaceDestroyed(SurfaceHolder holder) {  
  21.     super.onSurfaceDestroyed(holder);  
  22.     mHandler.removeMessages(DRAW);  
  23. }  
在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.    
  8.             mHandler.removeMessages(DRAW);  
  9.             mHandler.sendEmptyMessageDelayed(DRAW, 50);  
  10.         }  
从上面可以看出,动态壁纸实际上就是不断刷新的静态壁纸,越华丽越流畅,CPU就消耗越大,对于现在的本来电量就不怎么地的智能机来说,耗电也是很可观的。但是偶尔向朋友们炫一下还是绝对可行的。drawTime()与drawCross()的内容可以由家自己实现,在TimeWall里,它们比较简单。drawTime()是计算下一处Time String应该移动到的坐标,以及画出这个String。drawCross()的作用是在用户触发onTouchEvent时画一个十字架。因为TimeWall比较简单,如果大家自己实现的画图比较复杂,可以另外开启一个线程来刷新UI,否则有可能主线程被阻塞掉。(代码见附件)
看看TimeWall的效果:

附件代码:
 
 

view plaincopy to clipboardprint?
  1. package com.OPhonesdn.timewall;  
  2.    
  3. import java.text.SimpleDateFormat;  
  4. import java.util.Date;  
  5.    
  6. import android.graphics.Canvas;  
  7. import android.graphics.Color;  
  8. import android.graphics.Paint;  
  9. import android.os.Handler;  
  10. import android.os.Message;  
  11. import android.service.wallpaper.WallpaperService;  
  12. import android.view.MotionEvent;  
  13. import android.view.SurfaceHolder;  
  14.    
  15. public class TimeWall extends WallpaperService {  
  16.    
  17.     public Engine onCreateEngine() {  
  18.         return new TimeEngine();  
  19.     }  
  20.    
  21.     public class TimeEngine extends Engine {  
  22.    
  23.         private final float STEP_X = 2f;  
  24.         private final float STEP_Y = 7f;  
  25.         private final float SCOPE_LEFT = 10f;  
  26.         private final float SCOPE_RIGHT = 110f;  
  27.         private final float SCOPE_TOP = 250f;  
  28.         private final float SCOPE_BOTTOM = 600f;  
  29.         private final float RADIUS = 20f;  
  30.         private final int DIRECTION_1 = 1// move to right top side  
  31.         private final int DIRECTION_2 = 2// move to right bottom side  
  32.         private final int DIRECTION_3 = 3// move to left bottom side  
  33.         private final int DIRECTION_4 = 4// move to left top side  
  34.         private final int DRAW = 1;  
  35.         private float mTouchX = -1f;  
  36.         private float mTouchY = -1f;  
  37.         private float mLocationX = 0f;  
  38.         private float mLocationY = 400f;  
  39.         private int mDirection = 1;  
  40.    
  41.         private Paint mPaint = new Paint();  
  42.         private Handler mHandler = new Handler() {  
  43.             public void handleMessage(Message msg) {  
  44.                 switch (msg.what) {  
  45.                 case DRAW:  
  46.                     drawWall();  
  47.                     break;  
  48.                 }  
  49.             }  
  50.         };  
  51.    
  52.         public TimeEngine() {  
  53.             mPaint.setColor(Color.RED);  
  54.             mPaint.setAntiAlias(true);  
  55.             mPaint.setStrokeWidth(4);  
  56.             mPaint.setStrokeCap(Paint.Cap.BUTT);  
  57.             mPaint.setStyle(Paint.Style.STROKE);  
  58.             mPaint.setTextSize(40);  
  59.         }  
  60.    
  61.         @Override  
  62.         public void onCreate(SurfaceHolder surfaceHolder) {  
  63.             super.onCreate(surfaceHolder);  
  64.             setTouchEventsEnabled(true);  
  65.         }  
  66.    
  67.         @Override  
  68.         public void onDestroy() {  
  69.             super.onDestroy();  
  70.             mHandler.removeMessages(DRAW);  
  71.         }  
  72.    
  73.         @Override  
  74.         public void onSurfaceCreated(SurfaceHolder holder) {  
  75.             super.onSurfaceCreated(holder);  
  76.             mHandler.sendEmptyMessage(DRAW);  
  77.         }  
  78.    
  79.         @Override  
  80.         public void onSurfaceDestroyed(SurfaceHolder holder) {  
  81.             super.onSurfaceDestroyed(holder);  
  82.             mHandler.removeMessages(DRAW);  
  83.         }  
  84.    
  85.         @Override  
  86.         public void onTouchEvent(MotionEvent event) {  
  87.             if (event.getAction() == MotionEvent.ACTION_MOVE  
  88.                     || event.getAction() == MotionEvent.ACTION_DOWN) {  
  89.                 mTouchX = event.getX();  
  90.                 mTouchY = event.getY();  
  91.             } else {  
  92.                 mTouchX = -1;  
  93.                 mTouchY = -1;  
  94.             }  
  95.             super.onTouchEvent(event);  
  96.         }  
  97.    
  98.         private void drawWall() {  
  99.             SurfaceHolder holder = getSurfaceHolder();  
  100.             Canvas canvas = holder.lockCanvas();  
  101.             drawTime(canvas);  
  102.             drawCross(canvas);  
  103.             holder.unlockCanvasAndPost(canvas);  
  104.    
  105.             mHandler.removeMessages(DRAW);  
  106.             mHandler.sendEmptyMessageDelayed(DRAW, 50);  
  107.         }  
  108.    
  109.         private void drawTime(Canvas c) {  
  110.             Date date = new Date(System.currentTimeMillis());  
  111.             SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  112.             String strDate = sdf.format(date);  
  113.             c.save();  
  114.             c.drawColor(0xff000000);  
  115.             c.drawText(strDate, mLocationX, mLocationY, mPaint);  
  116.             switch (mDirection) {  
  117.             case DIRECTION_1:  
  118.                 mLocationX = mLocationX + STEP_X;  
  119.                 mLocationY = mLocationY - STEP_Y;  
  120.                 if (mLocationY <= SCOPE_TOP) {  
  121.                     mDirection = DIRECTION_2;  
  122.                 }  
  123.                 break;  
  124.             case DIRECTION_2:  
  125.                 mLocationX = mLocationX + STEP_X;  
  126.                 mLocationY = mLocationY + STEP_Y;  
  127.                 if (mLocationX >= SCOPE_RIGHT) {  
  128.                     mDirection = DIRECTION_3;  
  129.                 }  
  130.                 break;  
  131.             case DIRECTION_3:  
  132.                 mLocationX = mLocationX - STEP_X;  
  133.                 mLocationY = mLocationY + STEP_Y;  
  134.                 if (mLocationY >= SCOPE_BOTTOM) {  
  135.                     mDirection = DIRECTION_4;  
  136.                 }  
  137.                 break;  
  138.             case DIRECTION_4:  
  139.                 mLocationX = mLocationX - STEP_X;  
  140.                 mLocationY = mLocationY - STEP_Y;  
  141.                 if (mLocationX <= SCOPE_LEFT) {  
  142.                     mDirection = DIRECTION_1;  
  143.                 }  
  144.                 break;  
  145.             }  
  146.             c.restore();  
  147.         }  
  148.    
  149.         private void drawCross(Canvas c) {  
  150.             if (mTouchX >= 0 && mTouchY >= 0) {  
  151.                 c.drawLine(mTouchX - RADIUS, mTouchY, mTouchX + RADIUS,  
  152.                         mTouchY, mPaint);  
  153.                 c.drawLine(mTouchX, mTouchY - RADIUS, mTouchX,  
  154.                         mTouchY + RADIUS, mPaint);  
  155.             }  
  156.         }  
  157.     }  
  158. }  
  159.    

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/548658.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第十五天实验-VLAN

一&#xff0c;创建VLAN [sw1]vlan batch 2 to 6 [sw2]vlan batch 2 to 6 [sw3]vlan batch 2 to 6 二&#xff0c;通过需求修改接口 SW1&#xff1a; [sw1]int g0/0/2 [sw1-GigabitEthernet0/0/2]port link-type access ---将接口设置为access [sw1-GigabitEthernet0/0/2]…

PHP中静态方法(static)与非静态方法的使用及区别

static关键字用来修饰属性、方法&#xff0c;称这些属性、方法为静态属性、静态方法。static关键字声明一个属性或方法是和类相关的&#xff0c;而不是和类的某个特定的实例相关&#xff0c;因此&#xff0c;这类属性或方法也称为“类属性”或“类方法”如果访问控制权限允许&a…

hcip第17天

1&#xff0c;禁用 --- 1&#xff0c;接口关闭情况下&#xff1b;2&#xff0c;接口禁用生成树协议 2&#xff0c;阻塞 --- 生成树协议激活接口后进入的第一个状态。该状态下&#xff0c;接口只能侦听BPDU&#xff0c;不能转发BPDU和业务帧&#xff0c;也不能学习MAC地址一开始…

账户配置 三: Gmail

书接上文&#xff0c;Gmail也是大家常用的邮件之一&#xff0c;在Windows Phone 7中配置Gmail非常容易。我们来看看怎样快速配置Gmail。 操作&#xff1a; 找到“设置”并点击进入选择“电子邮件和账户”选择“添加账户”选择“Google”填写“邮件地址”和“密码”并点击“登录…

[深入学习C#]LINQ查询表达式详解(1)——基本语法、使用扩展方法和Lambda表达式简化LINQ查询

此文章非原创,转载自诗人江湖老,原文地址 在Git上下载源码   在工程中我们少不了要定义类或者结构去储存数据&#xff0c;这些数据将被临时地储存在内存中&#xff0c;现在我们想要对其完成一些类似于查找、过滤等等常见的任务的时候&#xff0c;我们该如何去做呢&#xff1…

hcip第18天

链路聚合 --- 可以将多个物理接口捆绑成一个逻辑接口&#xff0c;即将N条物理链路聚合为一条逻辑链路。可以在不升级硬件的条件下&#xff0c;达到增加带宽的效果。 我们将逻辑链路&#xff0c;称为聚合链路&#xff0c;在华为设备中称为ETH-TRUNK链路&#xff08;这个技术是针…

x264编码参数大测试:08 subme与指定码率(1000Kbps)

一、测试内容 测试方法—— x264编码参数大测试&#xff1a;索引贴 http://www.cnblogs.com/zyl910/archive/2011/12/14/x264_encode_param.html 测试参数—— subme&#xff1a;9、10、11。设定子像素&#xff08;subpixel&#xff09;运动估计&#xff08;motion estimation&…

[深入学习C#]LINQ查询表达式详解(2)——查询表达式的转换

转载自诗人江湖老,原文地址 C#在执行LINQ查询表达式的时候&#xff0c;并不会指定其执行语义&#xff0c;而是将查询表达式转换为遵循查询表达式模式的方法的调用。具体而言&#xff0c;查询表达式将转换为以下名称的调用&#xff1a;Where、Select、SelectMany、Join、GroupJo…

第十八天实验-交换综合

配置思路 eth-trunk &#xff1e; 创建vlan &#xff1e; 划分vlan &#xff1e; trunk干道 &#xff1e; STP &#xff1e; SVI &#xff1e; VRRP &#xff1e; DHCP 一&#xff0c;配置eth-trunk SW&#xff11;&#xff1a; [sw1]int Eth-Trunk 0 ---创建…

[深入学习C#]匿名函数、委托和Lambda表达式

转载自诗人江湖老,原文地址 匿名函数&#xff08;Anonymous Function&#xff09;是表示“内联”方法定义的表达式。匿名函数本身及其内部没有值或者类型&#xff0c;但是可以转换为兼容的委托或者表达式树类型(了解详情)。匿名函数转换的计算取决于转换的目标类型&#xff1a;…

HCIA第九节课作业

子网划分&#xff1a; 如何去合理的分配地址 总共需要多少个网段&#xff1f; 14个网段 环回接口8个6个 192.168.1.0/14 借4位 192.168.1.0/28 192.168.1.16/28 192.168.1.32/28 192.168.1.48/28 可用地址数量是多少?14个地址 子网划分第多少位的时候,只有两个可…

如何下载防盗链的歌曲?

初音&#xff0c;大家都很熟悉了。它是YAHAMA&#xff08;雅马哈&#xff0c;就是生产电子琴的那个公司&#xff09;推出的音乐编辑软件vocaloid的一款产品。 1月27号&#xff08;春节放假回来的前一天&#xff09;就要推出vocaloid 3啦&#xff01;&#xff01; 很喜欢IA的《鸟…

SQL Server大量数据秒级插入/新增/删除

转载自诗人江湖老,原文地址 /// <summary>/// 快速保存数据&#xff0c;自动识别insert和update/// </summary>/// <param name"_sourceTable">需要保存的源数据表</param>/// <param name"_sqlCon">数据库连接</param&g…

在当前主机添加两块网卡,将两块网卡绑定实现网卡冗余操作。

编辑虚拟网络接口配置文件,指定网卡IP 1. change the /etc/sysconfig/network-scripts/ifcfg-bond0 configuration. # cat ifcfg-bond0 DEVICEbond0 BOOTPROTOstatic IPADDR172.24.80.168 NETMASK255.255.255.0 BROADCAST172.24.80.250 ONBOOTyes TYPEEthernet # 不…

如何发布.Net MVC 网站项目(攻略集锦)

转载自诗人江湖老&#xff0c;原文地址 参考文献既然是攻略&#xff0c;就必然有参考文献&#xff0c;放在文章开头&#xff0c;以示敬意&#xff01; 1.MVC项目发布步骤 2.未能从程序集加载“System.ServiceModel.Activation.HttpModule” 3. Win7 IIS 另一个程序正在使用此…

ssh建立原理 及配置两台主机的远程连接实现免密登陆

一、SSH是什么&#xff1f;具体的实现有哪些&#xff1f; SSH是一种协议标准 SSH是用在安全远程登录以及其它安全网络服务 二、SSH原理&#xff1a; SSH为Secure Shell的缩写&#xff0c;默认端口22&#xff0c;由IETF的网络小组&#xff08;Network Working Group&…

ssh-scan处理手记

登陆一台Linux RedHat As4的服务器&#xff0c;发现有很多网络连接&#xff0c;为本机去连接其他服务器的22端口。再一看进程&#xff0c;好多ssh-scan的进程。估计是密码设得太简单&#xff0c;被人家黑了。处理思路&#xff1a;找到ssh-scan进程的相应程序文件&#xff0c;删…

常用 SQL Server 规范集锦

原文地址 常见的字段类型选择   &#xff11;.字符类型建议采用varchar/nvarchar数据类型   &#xff12;.金额货币建议采用money数据类型   &#xff13;.科学计数建议采用numeric数据类型   &#xff14;.自增长标识建议采用bigint数据类型 (数据量一大&#xff…

Linux服务器搭建----Web服务器(apache)

WWW的介绍 万维网&#xff08;亦作“Web”、“WWW”、“W3”&#xff0c;英文全称为“World Wide Web”&#xff09;&#xff0c;是一个由许多互相链接的超文本组成的系统&#xff0c;通过互联网访问。在这个系统中&#xff0c;每个有用的事物&#xff0c;称为一样“资源”&…

Pa interface issue——PA_EXCEED_ROUND_LIMIT

最近处理一个PA_TRANSACTION_INTERFACE_ALL的Error Error_code:PA_EXCEED_ROUND_LIMIT 原因是PA_EXCEED_ROUND_LIMIT is null or too small for cost*invoice_rate - cost*actual_rate. 就是说limit的value为空或者不满足金额*当前汇率与金额*录入时汇率的差额。 问题的难点在于…