`
java-mans
  • 浏览: 11391122 次
文章分类
社区版块
存档分类
最新评论

Android Launcher开发之动态壁纸(LiveWallPaper)气泡流动效果

 
阅读更多

最近在研究Laucher应用,今天写了一下四组件中的壁纸(WallPaper),关于静态壁纸的实现,比较简单,在此就不再描述. 参考了系统源代码之后,我自己做了一个简单的动态壁纸:气泡流动效果. 图案比较简单,但基本原理可在此例子上加以扩展,比如3D动画效果,复杂的触摸改变动画事件,有兴趣的朋友可以试一试.


大概效果如下,最开始得时候,会从四个角落的方向浮出四个气泡,然后以一定的路线移动,当移出屏幕时重新开始以新的坐标浮出,以此实现了一个简单的气泡浮动的效果:









实现的思路 :

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)的方法,这里虽然实现的代码较少,但效率较低,画面仍不够流畅.


不过本人精力有限,因此在此提供了代码,希望有兴趣的朋友可以将其完善,或者给出具体的解决方案,共同讨论








分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics