zoukankan      html  css  js  c++  java
  • android 动态壁纸

    转自网络。。         没有找到原作者。。。

    OPhone动态壁纸探究

    OPhone平台开发, 2010-08-06 14:50:47

    标签 : 动态壁纸 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?
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.oms.LiveWall" android:versionCode="1"
    android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
    <service android:label="@string/app_name" android:name=".TimeWall"
    android:permission="android.permission.BIND_WALLPAPER">
    <intent-filter>
    <action android:name="android.service.wallpaper.WallpaperService" />
    </intent-filter>
    <meta-data android:name="android.service.wallpaper"
    android:resource="@xml/alive_wall" />
    </service>
    </application>
    <uses-sdk android:minSdkVersion="7" />
    </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?
    public class TimeWall extends WallpaperService {

    public Engine onCreateEngine() {
    return new TimeEngine();
    }

    public class TimeEngine extends Engine {
    // ...more code
    }
    }

    类TimeEngine才是处理壁纸的核心类,我们会在类TimeEngine中加上自己的逻辑以完成壁纸的绘制、变化以及销毁。Engine的生命周期与大多数OPhone应用程序组件,比如activity类似,都是从onCreate()开始,在销毁时调用onDestory()方法。不同的是WallpaperService会提供一个surface用来绘制壁纸,所以在生命周期中多一个onSurfaceCreated与onSurfaceDestroyed的过程。下面是一个最简生命周期:

    也就是说只要我们实现上面四个方法,一个基本的LiveWallpaper就可以完成了。让我们逐个看一下这几个方法的实现。
    view plaincopy to clipboardprint?
    @Override
    public void onCreate(SurfaceHolder surfaceHolder) {
    super.onCreate(surfaceHolder);
    setTouchEventsEnabled(true);
    }

    @Override
    public void onDestroy() {
    super.onDestroy();
    mHandler.removeMessages(DRAW);
    }

    @Override
    public void onSurfaceCreated(SurfaceHolder holder) {
    super.onSurfaceCreated(holder);
    mHandler.sendEmptyMessage(DRAW);
    }

    @Override
    public void onSurfaceDestroyed(SurfaceHolder holder) {
    super.onSurfaceDestroyed(holder);
    mHandler.removeMessages(DRAW);
    }

    在onCreate方法里,我们
    setTouchEventsEnabled(true);

    作用是使壁纸能响应touch event,默认是false。TimeWall会在用户点击屏幕的时候画一个十字架,所以我们需要设置其为true。

    可以看到我们在这四个方法里面做的事情非常简单,就是在create时候发一个message,执行画面的绘制,在destory时remove这个消息。看一下mHandler的代码:

    view plaincopy to clipboardprint?
    private Handler mHandler = new Handler() {
    public void handleMessage(Message msg) {
    switch (msg.what) {
    case DRAW:
    drawWall();
    break;
    }
    }
    };
    方法drawWall():

    view plaincopy to clipboardprint?
    private void drawWall() {
    SurfaceHolder holder = getSurfaceHolder();
    Canvas canvas = holder.lockCanvas();
    drawTime(canvas);
    drawCross(canvas);
    holder.unlockCanvasAndPost(canvas);

    mHandler.removeMessages(DRAW);
    mHandler.sendEmptyMessageDelayed(DRAW, 50);
    }

    从上面可以看出,动态壁纸实际上就是不断刷新的静态壁纸,越华丽越流畅,CPU就消耗越大,对于现在的本来电量就不怎么地的智能机来说,耗电也是很可观的。但是偶尔向朋友们炫一下还是绝对可行的。drawTime()与drawCross()的内容可以由家自己实现,在TimeWall里,它们比较简单。drawTime()是计算下一处Time String应该移动到的坐标,以及画出这个String。drawCross()的作用是在用户触发onTouchEvent时画一个十字架。因为TimeWall比较简单,如果大家自己实现的画图比较复杂,可以另外开启一个线程来刷新UI,否则有可能主线程被阻塞掉。(代码见附件)

    看看TimeWall的效果:


    附件代码:

    view plaincopy to clipboardprint?
    package com.OPhonesdn.timewall;

    import java.text.SimpleDateFormat;
    import java.util.Date;

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

    public class TimeWall extends WallpaperService {

    public Engine onCreateEngine() {
    return new TimeEngine();
    }

    public class TimeEngine extends Engine {

    private final float STEP_X = 2f;
    private final float STEP_Y = 7f;
    private final float SCOPE_LEFT = 10f;
    private final float SCOPE_RIGHT = 110f;
    private final float SCOPE_TOP = 250f;
    private final float SCOPE_BOTTOM = 600f;
    private final float RADIUS = 20f;
    private final int DIRECTION_1 = 1; // move to right top side
    private final int DIRECTION_2 = 2; // move to right bottom side
    private final int DIRECTION_3 = 3; // move to left bottom side
    private final int DIRECTION_4 = 4; // move to left top side
    private final int DRAW = 1;
    private float mTouchX = -1f;
    private float mTouchY = -1f;
    private float mLocationX = 0f;
    private float mLocationY = 400f;
    private int mDirection = 1;

    private Paint mPaint = new Paint();
    private Handler mHandler = new Handler() {
    public void handleMessage(Message msg) {
    switch (msg.what) {
    case DRAW:
    drawWall();
    break;
    }
    }
    };

    public TimeEngine() {
    mPaint.setColor(Color.RED);
    mPaint.setAntiAlias(true);
    mPaint.setStrokeWidth(4);
    mPaint.setStrokeCap(Paint.Cap.BUTT);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setTextSize(40);
    }

    @Override
    public void onCreate(SurfaceHolder surfaceHolder) {
    super.onCreate(surfaceHolder);
    setTouchEventsEnabled(true);
    }

    @Override
    public void onDestroy() {
    super.onDestroy();
    mHandler.removeMessages(DRAW);
    }

    @Override
    public void onSurfaceCreated(SurfaceHolder holder) {
    super.onSurfaceCreated(holder);
    mHandler.sendEmptyMessage(DRAW);
    }

    @Override
    public void onSurfaceDestroyed(SurfaceHolder holder) {
    super.onSurfaceDestroyed(holder);
    mHandler.removeMessages(DRAW);
    }

    @Override
    public void onTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_MOVE
    || event.getAction() == MotionEvent.ACTION_DOWN) {
    mTouchX = event.getX();
    mTouchY = event.getY();
    } else {
    mTouchX = -1;
    mTouchY = -1;
    }
    super.onTouchEvent(event);
    }

    private void drawWall() {
    SurfaceHolder holder = getSurfaceHolder();
    Canvas canvas = holder.lockCanvas();
    drawTime(canvas);
    drawCross(canvas);
    holder.unlockCanvasAndPost(canvas);

    mHandler.removeMessages(DRAW);
    mHandler.sendEmptyMessageDelayed(DRAW, 50);
    }

    private void drawTime(Canvas c) {
    Date date = new Date(System.currentTimeMillis());
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String strDate = sdf.format(date);
    c.save();
    c.drawColor(0xff000000);
    c.drawText(strDate, mLocationX, mLocationY, mPaint);
    switch (mDirection) {
    case DIRECTION_1:
    mLocationX = mLocationX + STEP_X;
    mLocationY = mLocationY - STEP_Y;
    if (mLocationY <= SCOPE_TOP) {
    mDirection = DIRECTION_2;
    }
    break;
    case DIRECTION_2:
    mLocationX = mLocationX + STEP_X;
    mLocationY = mLocationY + STEP_Y;
    if (mLocationX >= SCOPE_RIGHT) {
    mDirection = DIRECTION_3;
    }
    break;
    case DIRECTION_3:
    mLocationX = mLocationX - STEP_X;
    mLocationY = mLocationY + STEP_Y;
    if (mLocationY >= SCOPE_BOTTOM) {
    mDirection = DIRECTION_4;
    }
    break;
    case DIRECTION_4:
    mLocationX = mLocationX - STEP_X;
    mLocationY = mLocationY - STEP_Y;
    if (mLocationX <= SCOPE_LEFT) {
    mDirection = DIRECTION_1;
    }
    break;
    }
    c.restore();
    }

    private void drawCross(Canvas c) {
    if (mTouchX >= 0 && mTouchY >= 0) {
    c.drawLine(mTouchX - RADIUS, mTouchY, mTouchX + RADIUS,
    mTouchY, mPaint);
    c.drawLine(mTouchX, mTouchY - RADIUS, mTouchX,
    mTouchY + RADIUS, mPaint);
    }
    }
    }
    }

  • 相关阅读:
    《网络》:关于计算机网络的必备常识【无序】(不定时更新)
    《网络》:设置三个密码:通过console口连接设备,进入特权模式,登录Telnet
    《网络》:交换机基本配置命令
    启动eclipse时出现“Failed to load the JNI shared library jvm.dll”错误及解决
    java之servlet小记
    Nokia大事录
    Android之HandlerThread
    Android进程间的通信之AIDL
    Android进程间的通信之Messenger
    Loaders
  • 原文地址:https://www.cnblogs.com/zhenbeiju/p/2316004.html
Copyright © 2011-2022 走看看