Android 动态壁纸引擎试刀学习(初识安卓引擎)
3638 点击·0 回帖
![]() | ![]() | |
![]() | 动态壁纸蛮好玩的,也没接触过,看官方有就拿了学习下,是小马第一次接触引擎Engine,激动兴奋...效果做出来了,就放博客里,记录笔记,吼吼,跟大家交流学习, 废话不多说了,先看效果,再看源码,之后小马会把安卓动态壁纸那个水波纹也写在博客里,供大家交流学习,今天的效果如下图所示,因为手机开机后就要加载图片,所以小马就直接从开机启动完成后讲了,看图... 未开锁时立方体形式一: ![]() 开锁时立方体形式一与二: ![]() ![]() 简单的绘制效果,因为立方体都是下面这些图(由三角形拼成的)拼的,所以此处贴下这个效果图,效果制作的代码我放在形式一注释里面了,大家可以试下的,就是这个效果,临时的: ![]() 工程结构如下图所示: ![]() 因为形式一与形式二只是绘制点不一样,两个类都一样,防止篇幅过长(51有限制,超过80000字符就挂了,我已经超过了,这是第二边写了,所以形式二代码就不贴了),小马就直接贴形式一的代码与配置文件代码,详细的如有朋友要学习的话,下载下DEMO学习就是,小马基本的注释都加了,因为也在学习阶段,如有地方不足的,希望大家直接留言,批评指出,小马肯定感谢... 立方体形式一控制类代码: 1. package xiaoma.cube1; 2. 3. import Android.graphics.Canvas; 4. import Android.graphics.Paint; 5. import Android.os.Handler; 6. import Android.os.SystemClock; 7. import Android.service.wallpaper.WallpaperService; 8. import Android.view.MotionEvent; 9. import Android.view.SurfaceHolder; 10. 11. /** 12. * @Title: CubeWallpaper1.java 13. * @Package cube1 14. * @Description: 初识Android动态壁纸引擎 15. * @author XiaoMa 16. */ 17. 18. /* 19. * 因为小马没接触过引擎,也无从下手学习,今天就拿官方的例子来试试刀了, 20. * 吼吼,刚开始不知道,看了下代码,里面有讲到WallPaperService 21. * 查询这个服务可以查到与之相关联的类与方法,如下面官方文档中讲的,大家 22. * 英语不好也可以用工具看个大概,英语不好的朋友记得多用工具学习下,小马 23. * 英语也不咋的.... 24. * A wallpaper service is responsible for showing a live wallpaper behind 25. * applications that would like to sit on top of it. This service object itself 26. * does very little -- its only purpose is to generate instances of 27. * WallpaperService.Engine as needed. Implementing a wallpaper thus involves 28. * subclassing from this, subclassing an Engine implementation, and implementing 29. * onCreateEngine() to return a new instance of your engine 30. * 上面讲的大体是:一个类必须是WallpaperService引擎类的子类,而且里面必须重写 31. * onCreateEngine这个方法,要仔细看的话小马也看不懂英文,照着例子,看官方文档, 32. * 多猜多用工具查就行了,小马英语烂的可以让你吐血...我能看懂,你肯定能看懂 33. */ 34. public class CubeWallpaper1 extends WallpaperService { 35. 36. /*常用的都是这样的,用一个handler来动态的去刷新UI,对吧?猜的,看下面代码到底是不是*/ 37. private final Handler mHandler = new Handler(); 38. 39. /** 40. * 这个方法与Activity里面的一样,当这个类的服务被第一次创建时 41. * 调用,也就是说,这个方法只调用一次.. 42. */ 43. @Override 44. public void onCreate() { 45. super.onCreate(); 46. } 47. 48. /** 49. * 与上面反的,销毁时调用,这个猜下, 50. * 不懂了查文档 51. */ 52. @Override 53. public void onDestroy() { 54. super.onDestroy(); 55. } 56. 57. /** 58. * 这个方法在类注释中写明了 59. * implementing onCreateEngine() to return a new instance of your engine 60. * 必须实现这个方法来返回我们自己定义引擎的一个实例 61. */ 62. @Override 63. public Engine onCreateEngine() { 64. return new CubeEngine(); 65. } 66. 67. 68. /** 69. * 70. * @Title: CubeWallpaper1.java 71. * @Package cube1 72. * @Description: 自定义引擎类 73. * @author XiaoMa 74. */ 75. class CubeEngine extends Engine { 76. 77. private final Paint mPaint = new Paint(); 78. private float mOffset; 79. /*用户触摸位置*/ 80. private float mTouchX = -1; 81. private float mTouchY = -1; 82. private long mStartTime; 83. 84. /*屏幕中心坐标,记下,是中心不是原心(0,0)*/ 85. private float mCenterX; 86. private float mCenterY; 87. 88. private final Runnable mDrawCube = new Runnable() { 89. public void run() { 90. drawFrame(); 91. } 92. }; 93. private boolean mVisible; 94. 95. CubeEngine() { 96. 97. /*下面这几行就为了在屏幕中画立方体的线条而做准备*/ 98. final Paint paint = mPaint; 99. paint.setColor(0xffffffff);//画笔颜色 100. paint.setAntiAlias(true);//抗锯齿 101. paint.setStrokeWidth(2);//线条粗细,猜的,不知道对不对 102. paint.setStrokeCap(Paint.Cap.ROUND); 103. paint.setStyle(Paint.Style.STROKE); 104. //系统启动完之后,开始绘制壁纸的时间,这个时间里面包含有系统睡眠时间 105. mStartTime = SystemClock.elapsedRealtime(); 106. } 107. 108. /** 109. * 大家发现这个onCreate与Activity的方法有什么不同了吧? 110. * 老规矩的,还是在初始化壁纸引擎的时候调用这个方法,并设置触 111. * 屏事件为可用 112. */ 113. @Override 114. public void onCreate(SurfaceHolder surfaceHolder) { 115. super.onCreate(surfaceHolder); 116. setTouchEventsEnabled(true); 117. } 118. 119. @Override 120. public void onDestroy() { 121. super.onDestroy(); 122. mHandler.removeCallbacks(mDrawCube); 123. } 124. 125. /** 126. * 系统壁纸状态改变时会调用这个方法,如: 127. * 壁纸由隐藏转换为显示状态时会调用这个方法 128. */ 129. @Override 130. public void onVisibilityChanged(boolean visible) { 131. mVisible = visible; 132. /*下面这个判断好玩,就是说,如果屏幕壁纸状态转为显式时重新绘制壁纸,否则黑屏幕,隐藏就可以*/ 133. if (visible) { 134. drawFrame(); 135. } else { 136. mHandler.removeCallbacks(mDrawCube); 137. } 138. } 139. 140. @Override 141. public void onSurfaceChanged(SurfaceHolder holder, int format, 142. int width, int height) { 143. super.onSurfaceChanged(holder, format, width, height); 144. //下面是来保存屏幕显示立方体的,也就是你能看到的正面图的中心位置 145. mCenterX = width / 2.0f; 146. mCenterY = height / 2.0f; 147. drawFrame(); 148. } 149. 150. /** 151. * 下面两个方法是为了方便调用SurfaceHolder交互来重写的 152. */ 153. @Override 154. public void onSurfaceCreated(SurfaceHolder holder) { 155. super.onSurfaceCreated(holder); 156. } 157. 158. @Override 159. public void onSurfaceDestroyed(SurfaceHolder holder) { 160. super.onSurfaceDestroyed(holder); 161. mVisible = false; 162. mHandler.removeCallbacks(mDrawCube); 163. } 164. 165. /** 166. * 当手动壁纸时根据偏移量重绘壁纸 167. */ 168. @Override 169. public void onOffsetsChanged(float xOffset, float yOffset, float xStep, 170. float yStep, int xPixels, int yPixels) { 171. mOffset = xOffset; 172. drawFrame(); 173. } 174. 175. /* 176. * 在这个地方保存触摸的位置,我们会在绘制壁纸的时候使用触摸值 177. */ 178. @Override 179. public void onTouchEvent(MotionEvent event) { 180. if (event.getAction() == MotionEvent.ACTION_MOVE) { 181. mTouchX = event.getX(); 182. mTouchY = event.getY(); 183. } else { 184. mTouchX = -1; 185. mTouchY = -1; 186. } 187. super.onTouchEvent(event); 188. } 189. 190. /* 191. * 绘制立方体方法实现 192. */ 193. void drawFrame() { 194. final SurfaceHolder holder = getSurfaceHolder(); 195. 196. Canvas c = null; 197. try { 198. c = holder.lockCanvas(); 199. if (c != null) { 200. drawCube(c); 201. drawTouchPoint(c); 202. } 203. } finally { 204. if (c != null) 205. holder.unlockCanvasAndPost(c); 206. } 207. 208. // 在指定时间里重绘制,这个地方大家可以看效果图,如果你拖动过快的话,立方体 209. //每个顶点之间会有一个短暂的未连接延迟,就是在这个地方使用了延迟来绘制的 210. mHandler.removeCallbacks(mDrawCube); 211. if (mVisible) { 212. mHandler.postDelayed(mDrawCube, 1000 / 25); 213. } 214. } 215. 216. /* 217. * 这个地方是以立方体某个顶点为起始端,绘制三条线 218. * 一堆数字,看着好晕 219. * 在这小马顺便贴在这个DEMO里面用到的基本的绘制,如下: 220. * graphics.Canvas有四种画矩形的方法。 221. canvas.drawRect(new RectF(10, 10, 300, 100), paint); 222. canvas.drawRect(10, 150, 300, 200, paint); 223. canvas.drawRect(new Rect(10, 250, 300, 300), paint); 224. 第四种:画圆角的矩形 225. canvas.drawRoundRect(new RectF(10, 350, 300, 450), 10, 10, paint); 226. 第二个和第三个参数为圆角的宽高。 227. 有兴趣的朋友可以改下下面这些东西 228. */ 229. void drawCube(Canvas c) { 230. c.save(); 231. c.translate(mCenterX, mCenterY); 232. c.drawColor(0xff000000); 233. drawLine(c, -400, -400, -400, 400, -400, -400); 234. drawLine(c, 400, -400, -400, 400, 400, -400); 235. drawLine(c, 400, 400, -400, -400, 400, -400); 236. drawLine(c, -400, 400, -400, -400, -400, -400); 237. 238. drawLine(c, -400, -400, 400, 400, -400, 400); 239. drawLine(c, 400, -400, 400, 400, 400, 400); 240. drawLine(c, 400, 400, 400, -400, 400, 400); 241. drawLine(c, -400, 400, 400, -400, -400, 400); 242. 243. drawLine(c, -400, -400, 400, -400, -400, -400); 244. drawLine(c, 400, -400, 400, 400, -400, -400); 245. drawLine(c, 400, 400, 400, 400, 400, -400); 246. drawLine(c, -400, 400, 400, -400, 400, -400); 247. c.restore(); 248. } 249. 250. /* 251. * 在屏幕中绘制三维空间的线 252. */ 253. void drawLine(Canvas c, int x1, int y1, int z1, int x2, int y2, int z2) { 254. /* 255. *因为大家都知道,壁纸是手机启动完成之后就已经开始绘制的,一般取时间什么的 256. *我们都用Timer System.currentTimeMillis() Calendar来取 257. *这个地方取系统级启动时间等的,记住这个类,SystemClock,方法自己查 258. */ 259. long now = SystemClock.elapsedRealtime(); 260. /*取得三维坐标轴的旋转值*/ 261. float xrot = ((float) (now - mStartTime)) / 1000; 262. float yrot = (0.5f - mOffset) * 2.0f; 263. float zrot = 0; 264. 265. 266. // rotation around X-axis ??? 267. float newy1 = (float) (Math.sin(xrot) * z1 + Math.cos(xrot) * y1); 268. float newy2 = (float) (Math.sin(xrot) * z2 + Math.cos(xrot) * y2); 269. float newz1 = (float) (Math.cos(xrot) * z1 - Math.sin(xrot) * y1); 270. float newz2 = (float) (Math.cos(xrot) * z2 - Math.sin(xrot) * y2); 271. 272. // rotation around Y-axis ??? 273. float newx1 = (float) (Math.sin(yrot) * newz1 + Math.cos(yrot) * x1); 274. float newx2 = (float) (Math.sin(yrot) * newz2 + Math.cos(yrot) * x2); 275. newz1 = (float) (Math.cos(yrot) * newz1 - Math.sin(yrot) * x1); 276. newz2 = (float) (Math.cos(yrot) * newz2 - Math.sin(yrot) * x2); 277. 278. // 3D-to-2D projection ??? 279. float startX = newx1 / (4 - newz1 / 400); 280. float startY = newy1 / (4 - newz1 / 400); 281. float stopX = newx2 / (4 - newz2 / 400); 282. float stopY = newy2 / (4 - newz2 / 400); 283. 284. c.drawLine(startX, startY, stopX, stopY, mPaint); 285. } 286. 287. /* 288. * 按位屏幕手动时绘制一个白色的圈 289. */ 290. void drawTouchPoint(Canvas c) { 291. if (mTouchX >= 0 ;; mTouchY >= 0) { 292. c.drawCircle(mTouchX, mTouchY, 80, mPaint); 293. } 294. } 295. 296. } 297. } 配置文件代码如下: 1. <?xml version="1.0" encoding="utf-8"?> 2. <manifest xmlns:Android="http://schemas.Android.com/apk/res/Android" 3. package="xiaoma.cube1" 4. Android:versionCode="1" 5. Android:versionName="1.0" > 6. 7. <uses-sdk Android:minSdkVersion="7" /> 8. <!-- 小马试的,如果下面uses-feature两名句话不加的话会报 9. ClassNotFoundException 异常的哦,所以大家务必加上 10. --> 11. <uses-feature Android:name="Android.software.live_wallpaper" /> 12. <uses-feature Android:name="Android.software.live_wallpaper" /> 13. 14. <application 15. Android:label="@string/wallpapers" 16. Android:icon="@drawable/ic_launcher"> 17. 18. <!-- 立方体形式一 --> 19. <service 20. Android:label="@string/wallpaper_cube1" 21. Android:name=".CubeWallpaper1" 22. Android:permission="Android.permission.BIND_WALLPAPER"> 23. <intent-filter> 24. <action Android:name="Android.service.wallpaper.WallpaperService" /> 25. </intent-filter> 26. <meta-data Android:name="Android.service.wallpaper" Android:resource="@xml/cube1" /> 27. </service> 28. 29. <!-- 立方体形式二 --> 30. <service 31. Android:label="@string/wallpaper_cube2" 32. Android:name=".CubeWallpaper2" 33. Android:permission="Android.permission.BIND_WALLPAPER"> 34. <intent-filter> 35. <action Android:name="Android.service.wallpaper.WallpaperService" /> 36. </intent-filter> 37. <meta-data Android:name="Android.service.wallpaper" Android:resource="@xml/cube2" /> 38. </service> 39. <!-- 立方体形式二偏好控制类 --> 40. <activity 41. Android:label="@string/cube2_settings" 42. Android:name=".CubeWallpaper2Settings" 43. Android:theme="@Androidtyle/Theme.Light.WallpaperSettings" 44. Android:exported="true"> 45. </activity> 46. 47. </application> 48. 49. </manifest> 最后,看不懂小马注释的,可以自己修改下里面的点试下,看是什么效果就知道了,呵呵,小马也是第一次接触引擎这个东西,大牛多指点下,期待...因为不知道从哪开始学这些东西,就学习了下官方的,可以的话,神人多多赐教,小马一定感激的...谢谢,小DEMO源码我放附件里了,跟小马一样的菜菜可以下下来学习学习,嘿嘿,,加油加油 | |
![]() | ![]() |