zoukankan      html  css  js  c++  java
  • 开发实时壁纸(Live Wallpapers)

    所谓实时壁纸,就是指手机桌面不再是简单的图片,而是运行中的动画,这个动画是由程序实时绘制的,因此被称为实时壁纸。

    为了开发实时壁纸,Android提供了WallpaperService基类,实时壁纸的实现类需要继承该基类,在Android应用中开发实时壁纸的步骤如下:

    1、开发一个子类继承WallpaperService基类。

    2、继承WallpaperService基类时必须重写onCreateEngine()方法,该方法返回WallpaperService.Engine子类对象。

    3、开发者需要实现WallpaperService.Engine子类,并重写其中的public  void  onVisibilityChanged(boolean  visible)、public  void  onOffsetsChanged()方法。不仅如此,由于WallpaperService.Engine子类采用了与SurfaceView相同的绘图机制,因此还可选择性地重写在SurfaceHolder.Callback中的三个方法。重写这些方法时可通过SurfaceHolder动态地绘制图形。

    下面的Service类就代表了实时壁纸服务,程序代码如下:

    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.os.Handler;
    import android.service.wallpaper.WallpaperService;
    import android.view.MotionEvent;
    import android.view.SurfaceHolder;

    public class LiveWallPaper extends WallpaperService{
      //实现WallpaperService必须实现的抽象方法
      @Override
      public Engine onCreateEngine() {
        // 返回自定义的Engine
        return new MyEngine();
      }
      class MyEngine extends Engine{
        //记录程序界面是否可见
        private boolean mVisible;
        //记录当前用户动作事件的发生位置
        private float mTouchX = -1;
        private float mTouchY = -1;
        //记录当前圆圈的绘制位置
        private float cx = 15;
        private float cy = 20;
        //定义画笔
        private Paint mPaint = new Paint();
        //定义一个Handler
        Handler mHandler = new Handler();
        //定义一个周期性执行的任务
        private final Runnable drawTarget = new Runnable() {

          @Override
          public void run() {
            drawFrame();
          }
        };
        public void onCreate(android.view.SurfaceHolder surfaceHolder) {
          super.onCreate(surfaceHolder);
          //初始化画笔
          mPaint.setColor(0xffffffff);
          mPaint.setAntiAlias(true);
          mPaint.setStrokeWidth(2);
          mPaint.setStrokeCap(Paint.Cap.ROUND);
          mPaint.setStyle(Paint.Style.STROKE);
          //设置处理触摸事件
          setTouchEventsEnabled(true);
        };
        @Override
        public void onDestroy() {
          super.onDestroy();
          //删除回调
          mHandler.removeCallbacks(drawTarget);
        }
        @Override
        public void onVisibilityChanged(boolean visible) {
          mVisible = visible;
          //当界面可见时,执行drawFrame()方法
          if(visible){
            //动态地绘制图形
            drawFrame();
          }else{
            //如果界面不可见,删除回调
            mHandler.removeCallbacks(drawTarget);
          }
        }
        @Override
        public void onOffsetsChanged(float xOffset, float yOffset,
                float xOffsetStep, float yOffsetStep, int xPixelOffset,
                int yPixelOffset) {
          drawFrame();
        }
        // //当屏幕大小改变时调用该方法
        // @Override
        // public void onSurfaceChanged(SurfaceHolder holder, int format,
        //              int width, int height) {
        //   super.onSurfaceChanged(holder, format, width, height);
        //    drawFrame();
        // }
        // @Override
        // public void onSurfaceCreated(SurfaceHolder holder) {
        //    super.onSurfaceCreated(holder);
        // }
        // @Override
        // public void onSurfaceDestroyed(SurfaceHolder holder) {
        //    super.onSurfaceDestroyed(holder);
        //     mVisible = false;
        //    mHandler.removeCallbacks(drawTarget);
        // }
        @Override
        public void onTouchEvent(MotionEvent event) {
          // 如果检测到滑动操作
          if(event.getAction() == MotionEvent.ACTION_MOVE){
            mTouchX = event.getX();
            mTouchY = event.getY();
          }else{
            mTouchX = -1;
            mTouchY = -1;
          }
          super.onTouchEvent(event);
        }
        //定义绘制图形的工具方法
        private void drawFrame(){
          //获取该壁纸的SurfaceHolder
          final SurfaceHolder holder = getSurfaceHolder();
          Canvas c = null;
          try {
            //获取该壁纸的SurfaceHolder
            c = holder.lockCanvas();
            if(c != null){
              c.save();
              //绘制背景色
              c.drawColor(0xff000000);
              //在触碰点绘制圆圈
              drawTouchPoint(c);
              //绘制圆圈
              c.drawCircle(cx, cy, 80, mPaint);
              c.restore();
            }
          } catch (Exception e) {
            e.printStackTrace();
          }finally{
            if(c != null){
              holder.unlockCanvasAndPost(c);
            }
          }
          mHandler.removeCallbacks(drawTarget);
          //调度下一次重绘
          if(mVisible){
            cx += 15;
            cy += 20;
            //如果cx、cy移除屏幕,从左上角重新开始
            if(cx > 320){
              cx = 15;
            }
            if(cy > 400){
              cy = 20;
            }
            //指定0.1秒后重新执行mDrawCube一次
            mHandler.postDelayed(drawTarget, 100);
          }

        }
        //在屏幕触碰点绘制圆圈
        private void drawTouchPoint(Canvas c){
          if(mTouchX >= 0 && mTouchY >= 0){
            c.drawCircle(mTouchX, mTouchY, 40, mPaint);
          }
        }
      }

    }

    上面的程序中粗体字代码就是实现实时壁纸Service的关键代码,这两段粗体字代码重写了WallpaperService.Engine的onVisibilityChanged、onOffsetsChanged方法,并指定当桌面显示时调用drawFrame()方法进行绘制,drawFrame()方法绘制完成后通过Handler对象指定0.1秒后重绘。

    上面的程序中被注释的代码是可有可无地,如果程序需要桌面的Surface改变事件提供响应,则可以考虑重写被注释代码。

    定义了该Service类之后,接下来还需要在AndroidManifest.xml文件中配置该Service,配置实时壁纸Service与配置普通Service存在小小的区别。它需要指定如下两项:

    1、指定运行实时壁纸需要android.permission.BIND_WALLPAPER权限。

    2、为实时壁纸指定meta-data配置。

    在AndroidManifest.xml文件中配置实时壁纸,也就是需要增加如下配置片段:

    <!-- 配置实时壁纸Service -->
    <service android:name=".LiveWallPaper"
      android:label="@string/app_name"
      android:permission="android.permission.BIND_WALLPAPER"
      >
      <!-- 为实时壁纸配置intent-filter -->

      <intent-filter >
        <action android:name="android.service.wallpaper.WallPapreService"/>
      </intent-filter>
      <!-- 为实时壁纸配置meta-filter -->

      <meta-data
        android:name="android.service.wallpaper"
        android:resource="@xml/livewallpaper"
      />
    </service>

    上面的配置文件中粗体字配置部分就是配置实时壁纸的关键代码,上面的配置文件中指定了实时壁纸的meta-data放在@xml/livewallpaper中定义,因此程序还需要zairesxml目录下增加一个livewallpaper.xml文件,该代码如下:

    <?xml version="1.0" encoding="utf-8"?>
    <wallpaper xmls:android="http://schemas.android.com/apk/res/android"/>

  • 相关阅读:
    mysql分区表批量添加/删除range按天分区(int类型)
    mysql分区表批量添加/删除range按天分区(datetime类型)
    使用obd离线安装oceanbase
    mysqldump导出数据自增属性丢失案例
    Docker启动镜像并设置开机自启
    Docker启动mysql与elasticsearch以及nginx的命令
    Redis学习--从节点过期键清理策略
    Redis学习--渐进式rehash实现原理
    Redis学习--主节点过期键清理策略
    Redis学习--慢日志信息
  • 原文地址:https://www.cnblogs.com/jiww/p/5647726.html
Copyright © 2011-2022 走看看