Android 壁纸

原创
2017/03/13 22:23
阅读数 66

一、获取桌面壁纸:

    常用方法:

/**
 * 获取桌面壁纸
 */
public Bitmap getWallpaperBitmap(Context context){
  // 获取壁纸管理器  
  WallpaperManager wallpaperManager = WallpaperManager .getInstance(mContext);  
  // 获取当前壁纸  
  Drawable wallpaperDrawable = wallpaperManager.getDrawable();  
  // 将Drawable,转成Bitmap  
  Bitmap bm = ((BitmapDrawable) wallpaperDrawable).getBitmap(); 
  return bm;
} 

二、添加壁纸:

    用系统自带的方法添加壁纸:

/**
 * 列出所有Action含有Android.intent.action.SET_WALLPAPER的应用
 */
public void openWallparerApp(Context context){
	//调用系统自带壁纸选择功能,ACTION_SET_WALLPAPER为选择的时候使用的过滤条件  
	Intent chooseIntent = new Intent(Intent.ACTION_SET_WALLPAPER);  
	//启动系统选择应用  
	Intent intent = new Intent(Intent.ACTION_CHOOSER);  
	intent.putExtra(Intent.EXTRA_INTENT, chooseIntent);  
	intent.putExtra(Intent.EXTRA_TITLE, "选择壁纸");  
	startActivity(intent);  
}
也可以用下面的方法:
public void openWallparerApp(Context context){
	Intent chooseIntent = new Intent(Intent.ACTION_SET_WALLPAPER);  
	startActivity(Intent.createChooser(chooseIntent, "选择壁纸")); 
}

    选择更换壁纸

/**
 * 选择更换壁纸:使用Broadcast机制来通知壁纸已经更换。
 * 当选择了一张壁纸后,系统会发出一个Broadcast,
 * 同时选择的壁纸会被缓存在整个应用程序的上下文中,
 * 不仅仅可以在桌面上更换,也可以在图片显示应用中更换。
 * 在这里可以直接通过Application.getWallpaper();获取最新的壁纸
 */
class WallpaperIntentReceiver extends BroadcastReceiver{  
  
	private Application application;  
	//WeakReference使得WallpaperIntentReceiver不会因为Launcher的引用而被推迟注销掉  
	private WeakReference<UorderLauncher> rLauncher;  

	public WallpaperIntentReceiver(Application application, UorderLauncher launcher) {  
		this.application = application;  
		this.rLauncher = new WeakReference<UorderLauncher>(launcher);  
	}  
  
	public void setLauncher(UorderLauncher l){  
		this.rLauncher = new WeakReference<UorderLauncher>(l);  
	}  
  
	@Override  
	public void onReceive(Context context, Intent intent) {  
		Log.v(TAG, "更换了壁纸");  
		/** 
		 * 从ApplicationContext获取壁纸 
		 */  
		final Drawable lDrawable = application.getWallpaper();  
		if(lDrawable instanceof BitmapDrawable){  
			Log.v(TAG, "壁纸是BitmapDrawable类型的");  
			mWallpaper = ((BitmapDrawable)lDrawable).getBitmap();  
			  
		}else{  
			throw new IllegalStateException("The wallpaper must be a BitmapDrawable object");  
		}  
  
		/** 
		 * 如果此时Launcher是活动的,未被锁定,则加载新的Wallpaper 
		 */  
		if(rLauncher != null){  
			final UorderLauncher launcher = rLauncher.get();  
			if(launcher != null){  
				launcher.loadWallpaper();  
			}  
		}  
	}  
}  

    注册:

private void registerIntentReceivers(){  
    if(mWallpaperReceiver == null){  
        mWallpaperReceiver = new WallpaperIntentReceiver(getApplication(), this);  
        /** 
         * 注册的时候,指定IntentFilter,这样改BroadcastReciver就是接收壁纸更换的Broadcast的了 
         */  
        IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);  
        getApplication().registerReceiver(mWallpaperReceiver, filter);  
    }else{  
        mWallpaperReceiver.setLauncher(this);  
    }  
}  

    加载壁纸,需要重新绘制界面:

/** 
 * 这里加载壁纸,需要重新绘制界面 
 * @param wallpaper 
 */  
public void loadWallpaper(Bitmap wallpaper) {  
    wallpaperLoaded = true;  
    mWallpaper = wallpaper;  
    //要求重新绘制界面  
    requestLayout();  
    invalidate();  
}  

    这个方法仅仅要求重新绘制布局,那么,我们就知道,在绘制的方法中,应该会对壁纸进行相关的绘制。在dispatchDraw中,有对壁纸的处理,

/** 
 * 壁纸本身可能并没有整个workspace那么宽 
 * 所以,屏幕滑动的时候,壁纸向右边滑动的距离需要根据mWallpaperOffset做相应的调整 
 */  
float x = getScrollX()*mWallpaperOffset;  
//这里啥个意思,TODO:  
Log.v(TAG, "getRight-getLeft="+getRight()+"-"+getLeft()+"="+(getRight()-getLeft()));  
  
/** 
 * getRight()-getLeft()=手机屏幕的宽度 
 */  
if(x<getRight()-getLeft()-mWallpaperWidth){  
    //当壁纸宽度小于屏幕宽度的时候,才会出现小于的情况  
    //这种情况就固定  
    //但是在获得用户选择的壁纸的时候,我们对其作了大小调整,所以,这里基本不会出现这种情况  
    x = getRight()-getLeft()-mWallpaperWidth;  
}  
  
float y = (getBottom()-getTop()-mWallpaperHeight)/2;  
  
Log.v(TAG, "开始画壁纸:x,y分别为:"+x+","+y);  
//canvas.drawColor(Color.BLACK);  
if(mWallpaper!=null){  
    Log.v(TAG, "开始画壁纸");  
    canvas.drawBitmap(mWallpaper, x, y, mPaint);  
    //invalidate();  
}   

    通过canvas.drawBitmap(mWallpaper, x, y, mPaint);绘制了壁纸,这里关键的是x,y的计算,桌面可以横向滑动的,那么每次滑动后重新绘制的时候,这个x的值是在变化的,通过代码我们可以发现,其中有一个变量mWallpaperOffset,查找这个变量,在onMeasure中,对该变量进行了赋值:

//加载壁纸  
if(wallpaperLoaded){  
    wallpaperLoaded = false;  
    mWallpaper = BitmapUtils.centerToFit(mWallpaper, width, height, getContext());  
    mWallpaperWidth = mWallpaper.getWidth();  
    mWallpaperHeight = mWallpaper.getHeight();  
    Log.v(TAG, "测量壁纸大小:"+mWallpaperWidth+","+mWallpaperHeight);  
}  
  
final int wallpaperWidth = mWallpaperWidth;  
//计算Wallpaper每次随着屏幕滑动移动的距离  
if(wallpaperWidth > width){  
    /** 
     * 计算壁纸滑动的速率 
     * 壁纸可以滑动的距离是count*width-wallpaperWidth 
     * 屏幕可以滑动的距离是(count-1)*width 
     * 这样,一除就是壁纸相对于屏幕滑动的速率了 
     */  
    //mWallpaperOffset = wallpaperWidth/(count*(float)width);  
    mWallpaperOffset = (count*width-wallpaperWidth)/((count-1)*(float)width);  
}else {  
    mWallpaperOffset = 1.0f;  
}  
  
Log.v(TAG, "wallpaper的offset:"+mWallpaperOffset);  

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部