Android Launcher開發之動態壁紙(LiveWallPaper)氣泡流動效果

openkk 12年前發布 | 42K 次閱讀 Android Android開發 移動開發

最近在研究Laucher應用,今天寫了一下四組件中的壁紙(WallPaper),關于靜態壁紙的實現,比較簡單,在此就不再描述. 參考了系統源代碼之后,我自己做了一個簡單的動態壁紙:氣泡流動效果. 圖案比較簡單,但基本原理可在此例子上加以擴展,比如3D動畫效果,復雜的觸摸改變動畫事件,有興趣的朋友可以試一試.

 

大概效果如下,最開始得時候,會從四個角落的方向浮出四個氣泡,然后以一定的路線移動,當移出屏幕時重新開始以新的坐標浮出,以此實現了一個簡單的氣泡浮動的效果:

 

Android Launcher開發之動態壁紙(LiveWallPaper)氣泡流動效果

 

Android Launcher開發之動態壁紙(LiveWallPaper)氣泡流動效果

 

 

 

Android Launcher開發之動態壁紙(LiveWallPaper)氣泡流動效果

 

 

 

實現的思路 :

1、新建一個Android工程 ,注意,對于Live Wallpaper來說傳統的布局文件是不需要的。

2、在res下面新建一個xml文件夾 然后新建一個livewallpaper.xml 內容如下:

<?xml version="1.0" encoding="utf-8"?>
<wallpaper xmlns:android="http://schemas.android.com/apk/res/android" android:thumbnail="@drawable/icon"/>

注意: 這里的android:thumbnail值得是你這個動態壁紙的小圖標 會在你選著動態壁紙的時候出現,也可以不寫此屬性

 

3. 實現動態壁紙是不需要使用Activity, 創建LiveWallpaper類,讓其繼承WallpaperService:

實現 onCreateEngine()方法,返回自己實現的Engine類

 在Engine類中的onCreate()方法中進行調用繪制圖形的drawFrame()方法

 定義四個圓形的起始坐標,每次調用drawFrame()時改變圓形的坐標,通過mHandler.postDelayed(drawTarget, 100);方法,進行重新繪制圖形,更新UI

 

具體代碼如下:

 

1.AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="org.crazyit.desktop"
      android:versionCode="1"
      android:versionName="1.0">
    <application
        android:icon="@drawable/icon"
        android:label="@string/app_name">
        <!-- 配置實時壁紙Service -->
        <service android:label="@string/app_name"
            android:name=".LiveWallpaper"
            android:permission="android.permission.BIND_WALLPAPER">
            <!-- 為實時壁紙配置intent-filter -->
            <intent-filter>
                <action  android:name="android.service.wallpaper.WallpaperService" />
            </intent-filter>
            <!-- 為實時壁紙配置meta-data -->
            <meta-data android:name="android.service.wallpaper"
                android:resource="@xml/livewallpaper" />
        </service>
    </application>
</manifest> 

2. 壁紙的xml文件: livewallpaper.xml

<?xml version="1.0" encoding="utf-8"?>
<wallpaper xmlns:android="http://schemas.android.com/apk/res/android" android:thumbnail="@drawable/icon"/>

3. 實現動態壁紙的LiveWallpaper類:

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;
/**
 * 
 * @author Tian
 *
 */
public class LiveWallpaper extends WallpaperService
{
    // 實現WallpaperService必須實現的抽象方法
    public Engine onCreateEngine()
    {
        // 返回自定義的Engine
        return new MyEngine();
    }

    class MyEngine extends Engine
    {
        // 記錄程序界面是否可見
        private boolean mVisible;
        // 記錄當前當前用戶動作事件的發生位置
        private float mTouchX = -1;
        private float mTouchY = -1;
        // 記錄當前圓圈的繪制位置

        //左上角坐標
        private float cx1 = 15;
        private float cy1 = 20;

        //右下角坐標
        private float cx2 = 300;
        private float cy2 = 380;

        //右上角坐標
        private float cx3 = 300;
        private float cy3 = 20;

        //左下角坐標
        private float cx4 = 15;
        private float cy4 = 380;

        // 定義畫筆
        private Paint mPaint = new Paint();
        // 定義一個Handler
        Handler mHandler = new Handler();
        // 定義一個周期性執行的任務
        private final Runnable drawTarget = new Runnable()
        {
            public void run()
            {
                // 動態地繪制圖形
                drawFrame();
            }
        };

        @Override
        public void onCreate(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);
            }
        }

        public void onOffsetsChanged(float xOffset, float yOffset, float xStep,
            float yStep, int xPixels, int yPixels)
        {
            drawFrame();
        }


        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
            {
                // 對畫布加鎖
                c = holder.lockCanvas();
                if (c != null)
                {
                    c.save();
                    // 繪制背景色
                    c.drawColor(0xff000000);
                    // 在觸碰點繪制圓圈
                    drawTouchPoint(c);

                    // 繪制圓圈
                    c.drawCircle(cx1, cy1, 80, mPaint);
                    c.drawCircle(cx2, cy2, 40, mPaint);
                    c.drawCircle(cx3, cy3, 50, mPaint);
                    c.drawCircle(cx4, cy4, 60, mPaint);
                    c.restore();
                }
            }
            finally
            {
                if (c != null)
                    holder.unlockCanvasAndPost(c);
            }
            mHandler.removeCallbacks(drawTarget);
            // 調度下一次重繪
            if (mVisible)
            {
                cx1 += 6;
                cy1 += 8;
                // 如果cx1、cy1移出屏幕后從左上角重新開始
                if (cx1 > 320)
                    cx1 = 15;
                if (cy1 > 400)
                    cy1 = 20;


                cx2 -= 6;
                cy2 -= 8;
                // 如果cx2、cy2移出屏幕后從右下角重新開始
                if (cx2 <15)
                    cx2 = 300;
                if (cy2 <20)
                    cy2 = 380;


                cx3 -= 6;
                cy3 += 8;
                // 如果cx3、cy3移出屏幕后從右上角重新開始
                if (cx3 <0)
                    cx3 = 300;
                if (cy3 >400)
                    cy3 = 20;


                cx4 += 6;
                cy4 -= 8;
                // 如果cx4、cy4移出屏幕后從左下角重新開始
                if (cx4 >320)
                    cx4 = 15;
                if (cy4 <0)
                    cy4 = 380;

                // 指定0.1秒后重新執行mDrawCube一次
                mHandler.postDelayed(drawTarget, 100);
            }
        }

        // 在屏幕觸碰點繪制圓圈
        private void drawTouchPoint(Canvas c)
        {
            if (mTouchX >= 0 && mTouchY >= 0)
            {
                c.drawCircle(mTouchX, mTouchY, 40, mPaint);
            }
        }
    }
}

 

這樣,就基本實現了一個動態壁紙:氣泡浮動的效果.

 

不過這只是一個入門的小例子,如果想達到商用效果,還有很多方面需要進行優化:

1. 繪制更加復雜的圖形

2. 使用3D Animation動畫效果

3. 色彩方面需要豐富起來

4. 更新UI的方法我使用了handler的postDelay(runnable,millsecond)的方法,這里雖然實現的代碼較少,但效率較低,畫面仍不夠流暢.


轉自:http://blog.csdn.net/t12x3456/article/details/7857741

 本文由用戶 openkk 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!