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"/>

  • 相关阅读:
    7.21 高博教育 数组 内存
    【基础扎实】Python操作Excel三模块
    PAT 甲级 1012 The Best Rank
    PAT 甲级 1011  World Cup Betting
    PAT 甲级 1010 Radix
    链式线性表——实验及提升训练
    循环程序设计能力自测
    链表应用能力自测
    PAT 甲级 1009 Product of Polynomials
    1008 Elevator (20分)
  • 原文地址:https://www.cnblogs.com/jiww/p/5647726.html
Copyright © 2011-2022 走看看