看完此文后就知道壁纸怎么绘制出来的,什么情况下壁纸会随着桌面滑动而移动,为什么壁纸设置后被剪裁了。
这里主要讲解静态壁纸的显示流程,不考虑动态壁纸,所以下面提到的壁纸都是指静态壁纸。壁纸即是一个壁纸服务,每换一张壁纸 ,就是将该图片写入壁纸文件,再启动一个壁纸服务读取该壁纸文件显示出来的过程。
壁纸服务实现在SystemUI里面,所以其会跟随SystemUI进程的启动而启动,实现路径在:
/frameworks/base/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
初步看看其实现
/**
* Default built-in wallpaper that simply shows a static image.
*/
@SuppressWarnings({"UnusedDeclaration"})
public class ImageWallpaper extends WallpaperService {
private static final String TAG = "ImageWallpaper";
... ... ...
@Override
public void onCreate() {
super.onCreate();
mWallpaperManager = (WallpaperManager) getSystemService(WALLPAPER_SERVICE);
... ... ...
}
... ... ...
}
可以看到该服务继承自WallpaperService.java,是不是毛孔顿开。
壁纸的加载使用的是Engine引擎,其定义在ImageWallpaper.java的内部类class DrawableEngine extends Engine {,可以看到DrawableEngine继承自Engine,从此壁纸想怎么浪就怎么浪。壁纸服务启动后开始加载资源流程如下:
class DrawableEngine extends Engine {
... ... ...
@Override
public void onCreate(SurfaceHolder surfaceHolder) {
... ... ...
updateSurfaceSize(surfaceHolder, getDefaultDisplayInfo(), false /* forDraw */);
}
... ... ...
}
见updateSurfaceSize的实现
boolean updateSurfaceSize(SurfaceHolder surfaceHolder, DisplayInfo displayInfo,boolean forDraw) {
boolean hasWallpaper = true;
//如果没有保存背景图片尺寸信息就重新载入
// Load background image dimensions, if we haven't saved them yet
if (mBackgroundWidth <= 0 || mBackgroundHeight <= 0) {
// Need to load the image to get dimensions
mWallpaperManager.forgetLoadedWallpaper();
loadWallpaper(forDraw);
if (DEBUG) {
Log.d(TAG, "Reloading, redoing updateSurfaceSize later.");
}
hasWallpaper = false;
}
// Force the wallpaper to cover the screen in both dimensions
int surfaceWidth = Math.max(displayInfo.logicalWidth, mBackgroundWidth);
int surfaceHeight = Math.max(displayInfo.logicalHeight, mBackgroundHeight);
if (FIXED_SIZED_SURFACE) {//使用固定尺寸
// Used a fixed size surface, because we are special. We can do
// this because we know the current design of window animations doesn't
// cause this to break.
surfaceHolder.setFixedSize(surfaceWidth, surfaceHeight);