Android Launcher 动态icon【时钟】【日历】

主要要的逻辑就是想办法替换掉应用icon的drawable,然后通过自定义drawable的方式来实现动态Icon。

直接贴代码吧,没什么难的。


首先在IconCache.java 中的修改


    private static class CacheEntry {
        public Bitmap icon;
        public CharSequence title;
        public CharSequence contentDescription;
        public IconScript script;//icon的脚本
    }

    public IconScript getScript(Intent intent, UserHandleCompat user){
    	synchronized (mCache) {
    		 ComponentName component = intent.getComponent();
             if (component == null) {
                 return null;
             }
            LauncherActivityInfoCompat launcherActInfo = mLauncherApps.resolveActivity(intent, user);
            CacheEntry entry = cacheLocked(component, launcherActInfo, null, user, true, -1);
            return entry.script;
        }
    }

private CacheEntry cacheLocked(ComponentName componentName, LauncherActivityInfoCompat info,
            HashMap labelCache, UserHandleCompat user,
            boolean usePackageIcon, int unreadNum) {
		……
 	    if(componentName.getPackageName().equals("com.android.deskclock"))
            	entry.script = new ClockScript();
            if(componentName.getPackageName().equals("com.android.calendar"))
            	entry.script = new CalendarScript();
    
        return entry;
}


ShortcutInfo.java

    public IconScript getScript(IconCache iconCache){
    	return iconCache.getScript(promisedIntent != null ? promisedIntent : intent, user);
    }

BubbleTextView.java

public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache,
            boolean setDefaultPadding, boolean promiseStateChanged) {
……
 mScript = info.getScript(iconCache);
……
}


    @Override
    public void setCompoundDrawables(Drawable left, Drawable top,
            Drawable right, Drawable bottom) {
        if(top != null){
            if(mScript != null){
                top = mScript;
                mScript.setBounds(top.getBounds());
                if(!mScript.isRuning)
                mScript.run(this);
            }
        }

        super.setCompoundDrawables(left, top, right, bottom);
    }


public class IconScript extends Drawable{
	public boolean isRuning = false;
	public FastBitmapDrawable mFastBitmapDrawable = null;
	protected Paint mPaint = new Paint();
	
	public IconScript(){
		mPaint.setAntiAlias(true); 
		mPaint.setFilterBitmap(true);
	}
	
	public void draw(Canvas canvas){
		if(mFastBitmapDrawable != null){
			canvas.drawBitmap(mFastBitmapDrawable.getBitmap(), null, getBounds(),mPaint);//画底图
		}
	}
	
	/**
	 * 运行脚本
	 * @param view
	 */
	public void run(View view){
		isRuning = true;
	}
	
	/**
	 * 停止脚本
	 * (未调用,暂留入口)
	 */
	public void onStop(){
		isRuning = false;
	}
	
	/**
	 * 暂停脚本
	 * (未调用,暂留入口)
	 */
	public void onPause(){
		isRuning = false;
	}
	
	/**
	 * 恢复脚本
	 * (未调用,暂留入口)
	 */
	public void onResume(){
		isRuning = true;
	}

	@Override
	public int getOpacity() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public void setAlpha(int arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setColorFilter(ColorFilter arg0) {
		// TODO Auto-generated method stub
		
	}
	
    @Override
    public int getIntrinsicWidth() {
        int width = getBounds().width();
        if (width == 0) {
            width = mFastBitmapDrawable.getBitmap().getWidth();
        }
        return width;
    }

    @Override
    public int getIntrinsicHeight() {
        int height = getBounds().height();
        if (height == 0) {
            height = mFastBitmapDrawable.getBitmap().getHeight();
        }
        return height;
    }

    @Override
    public int getMinimumWidth() {
        return getBounds().width();
    }

    @Override
    public int getMinimumHeight() {
        return getBounds().height();
    }
    
    @Override
    public void setFilterBitmap(boolean filterBitmap) {
        mPaint.setFilterBitmap(filterBitmap);
        mPaint.setAntiAlias(filterBitmap);
    }
	
	public void setFastBitmapDrawable(FastBitmapDrawable drawable){
		mFastBitmapDrawable = drawable;
	}
	
	public FastBitmapDrawable setFastBitmapDrawable(){
		return mFastBitmapDrawable;
	}
}


 * 实现桌面时钟Icon动态显示。
 * 2015.4.1
 * @author gholl
 *
 */
public class ClockScript extends IconScript {
	Rect mRect = null;
	/**
	 * 效果展示目标View
	 */
	private View mView;
	/**
	 * 通知系统更新视图现成
	 */
	private ClockThread mClockThread = null;
	/**
	 * 当前是否显示在屏幕上
	 */
	private boolean mIsShowInScreen = false;
	
	public ClockScript(){
		super();
	}
	public void run(View view) {
		mView = view;
		mRect = getBounds();
		if(mClockThread == null){
			mClockThread = new ClockThread();
			mClockThread.start();
		}
	}
	
	@Override
	public void onPause() {
		mClockThread.pauseRun();
		super.onPause();
	}
	
	@Override
	public void onResume() {
		mClockThread.resumeRun();
		super.onResume();
	}
	
	@Override
	public void onStop() {
		mClockThread.stopRun();
		super.onStop();
	}
	

	@Override
	public void draw(Canvas canvas) {
		super.draw(canvas);
		mIsShowInScreen = true;
//		mPaint.setColor(Color.WHITE);
//		canvas.drawCircle(mRect.centerX(), mRect.centerY(), mRect.height()/2, mPaint);
//		mPaint.setColor(Color.BLACK);
//		canvas.drawLine(mRect.centerX(), 0, mRect.centerX(), 10, mPaint);
//		canvas.drawLine(mRect.centerX(), mRect.height(), mRect.centerX(), mRect.height()-10, mPaint);
//		canvas.drawLine(mRect.left, mRect.centerY(), mRect.left + 10, mRect.centerY(), mPaint);
//		canvas.drawLine(mRect.right, mRect.centerY(), mRect.right-10, mRect.centerY(), mPaint);
		drawIndicator(canvas,mRect.centerX(),mRect.centerY(),mPaint);
//		mPaint.setColor(Color.MAGENTA);
		canvas.drawCircle(mRect.centerX(), mRect.centerY(), 3, mPaint);
		
		if(mClockThread.wait){
			mClockThread.resumeRun();
		}
	}
	/**
	 * 画指针
	 * @param canvas
	 * @param centerX
	 * @param centerY
	 * @param p
	 */
	private void drawIndicator(Canvas canvas,int centerX,int centerY,Paint p){
		
		Time t=new Time();
		t.setToNow();
		p.setStrokeWidth(2);
		p.setColor(Color.BLACK);
		//时针
		canvas.drawLine(centerX, centerY, 
				(int)(centerX + (mRect.width()/2-35) * Math.cos((t.hour+(float)t.minute/60) * (Math.PI / 6) - Math.PI / 2)), 
				(int)(centerY + (mRect.width()/2-35) * Math.sin((t.hour+(float)t.minute/60) * (Math.PI / 6) - Math.PI / 2)), p);
		canvas.drawLine(centerX, centerY, 
				(int)(centerX + (mRect.width()/2-50) * Math.cos((t.hour+(float)t.minute/60) * (Math.PI / 6) + Math.PI / 2)), 
				(int)(centerY + (mRect.width()/2-50) * Math.sin((t.hour+(float)t.minute/60) * (Math.PI / 6) + Math.PI / 2)), p);
//		p.setColor(Color.GREEN);
		//分针
		canvas.drawLine(centerX, centerY,
				(int)(centerX + (mRect.width()/2-27) * Math.cos(t.minute * (Math.PI / 30) - Math.PI / 2)),
				(int)(centerY + (mRect.width()/2-27) * Math.sin(t.minute * (Math.PI / 30) - Math.PI / 2)),p);
		canvas.drawLine(centerX, centerY,
				(int)(centerX + (mRect.width()/2-48) * Math.cos(t.minute * (Math.PI / 30) + Math.PI / 2)),
				(int)(centerY + (mRect.width()/2-48) * Math.sin(t.minute * (Math.PI / 30) + Math.PI / 2)),p);
		p.setColor(Color.RED);
		//秒针
		canvas.drawLine(centerX, centerY,
				(int)(centerX + (mRect.width()/2-24) * Math.cos(t.second * (Math.PI / 30) - Math.PI / 2)),
				(int)(centerY + (mRect.width()/2-24) * Math.sin(t.second * (Math.PI / 30) - Math.PI / 2)),p);
		p.setStrokeWidth(3);
		canvas.drawLine(centerX, centerY,
				(int)(centerX + (mRect.width()/2-45) * Math.cos(t.second * (Math.PI / 30) + Math.PI/2)),
				(int)(centerY + (mRect.width()/2-45) * Math.sin(t.second * (Math.PI / 30) + Math.PI/2)),p);

	}
	
	class ClockThread extends Thread {
		int times = 0;
		boolean running = true;

		public boolean wait = false;

		public void stopRun() {
			running = false;
			synchronized (this) {
				this.notify();
			}
		};

		public void pauseRun() {
			this.wait = true;
			synchronized (this) {
				this.notify();
			}
		}

		public void resumeRun() {
			this.wait = false;
			synchronized (this) {
				this.notify();
			}
		}

		public void run() {
			while (running) {
				synchronized (mView) {
					mView.postInvalidate();
				}
				
				if(!mIsShowInScreen){
					pauseRun();
				}
				mIsShowInScreen = false;
				try {
					Thread.sleep(500);
				} catch (Exception e) {
					System.out.println(e);
				}
				
				synchronized (this) {
					if (wait) {
						try {
							wait();
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}
			}
		}
	}

}


/**
 * 实现桌面日历Icon动态显示。
 * @author gholl
 *
 */
public class CalendarScript extends IconScript {
	private float mDensity = 1.5f;
	Time mTime = new Time();
	Context mContext;
	public CalendarScript() {
		super();
		mContext = LauncherApplication.CONTEXT;
	}

	@Override
	public void draw(Canvas canvas) {
		super.draw(canvas);
		mTime.setToNow();
		canvas.drawBitmap(getRes(mTime.monthDay), null, getBounds(), mPaint);
	}

	@Override
	public void run(final View view) {

		IntentFilter filter = new IntentFilter();
		filter.addAction(Intent.ACTION_DATE_CHANGED);
		filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
		view.getContext().registerReceiver(new BroadcastReceiver() {
			@Override
			public void onReceive(Context arg0, Intent arg1) {
				view.postInvalidate();
			}
		}, filter);

		super.run(view);
	}
	
	private Bitmap getRes(int monthDay){
		int res = mContext.getResources().getIdentifier("ic_launcher_calendar_" + monthDay, "drawable", mContext.getPackageName());
		BitmapDrawable bitmapDrawable = (BitmapDrawable)mContext.getResources().getDrawable(res);
		return bitmapDrawable.getBitmap();
	}

}



 
 

你可能感兴趣的:(Android)