Android 动态壁纸引擎试刀学习(初识安卓引擎)

时间:2022-02-28 18:37:44
原创作品,允许转载,转载时请务必以超链接形式标明文章  原始出处 、作者信息和本声明。否则将追究法律责任。 http://mzh3344258.blog.51cto.com/1823534/806560

 动态壁纸蛮好玩的,也没接触过,看官方有就拿了学习下,是小马第一次接触引擎Engine,激动兴奋...效果做出来了,就放博客里,记录笔记,吼吼,跟大家交流学习, 废话不多说了,先看效果,再看源码,之后小马会把安卓动态壁纸那个水波纹也写在博客里,供大家交流学习,今天的效果如下图所示,因为手机开机后就要加载图片,所以小马就直接从开机启动完成后讲了,看图...

未开锁时立方体形式一:

Android 动态壁纸引擎试刀学习(初识安卓引擎)

开锁时立方体形式一与二:

Android 动态壁纸引擎试刀学习(初识安卓引擎)

Android 动态壁纸引擎试刀学习(初识安卓引擎)

简单的绘制效果,因为立方体都是下面这些图(由三角形拼成的)拼的,所以此处贴下这个效果图,效果制作的代码我放在形式一注释里面了,大家可以试下的,就是这个效果,临时引用的:

Android 动态壁纸引擎试刀学习(初识安卓引擎)

工程结构如下图所示:

Android 动态壁纸引擎试刀学习(初识安卓引擎)

      因为形式一与形式二只是绘制点不一样,两个类都一样,防止篇幅过长(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, -400400, -400, -400); 
  234.             drawLine(c, 400, -400, -400400400, -400); 
  235.             drawLine(c, 400400, -400, -400400, -400); 
  236.             drawLine(c, -400400, -400, -400, -400, -400); 
  237.  
  238.             drawLine(c, -400, -400400400, -400400); 
  239.             drawLine(c, 400, -400400400400400); 
  240.             drawLine(c, 400400400, -400400400); 
  241.             drawLine(c, -400400400, -400, -400400); 
  242.  
  243.             drawLine(c, -400, -400400, -400, -400, -400); 
  244.             drawLine(c, 400, -400400400, -400, -400); 
  245.             drawLine(c, 400400400400400, -400); 
  246.             drawLine(c, -400400400, -400400, -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.     } 

配置文件代码如下:

   
   
  
  
  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="@android:style/Theme.Light.WallpaperSettings" 
  44.             android:exported="true"> 
  45.         </activity> 
  46.  
  47.     </application> 
  48.  
  49. </manifest> 

      最后,看不懂小马注释的,可以自己修改下里面的点试下,看是什么效果就知道了,呵呵,小马也是第一次接触引擎这个东西,大牛多指点下,期待...因为不知道从哪开始学这些东西,就学习了下官方的,可以的话,神人多多赐教,小马一定感激的...谢谢,小DEMO源码我放附件里了,跟小马一样的菜菜可以下下来学习学习,嘿嘿,,加油加油!

本文出自 “酷_莫名简单、KNothing” 博客,请务必保留此出处http://mzh3344258.blog.51cto.com/1823534/806560