Android Launcher 时钟、日历图标随时间动态变更

转载自:http://blog.csdn.net/pinsengjixuhezhou/article/details/45890569

注:这篇文章 主要内容和思路还是转自上面链接中博主的文章,我在实际使用过程中根据自己的需求有些调整。


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

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


首先在IconCache.java 中的修改


[java]  view plain  copy
 
  1. private static class CacheEntry {  
  2.         public Bitmap icon;  
  3.         public CharSequence title;  
  4.         public CharSequence contentDescription;  
  5.         public IconScript script;//icon的脚本  
  6.     }  

[java]  view plain  copy
  1. public IconScript getScript(Intent intent, UserHandleCompat user){  
  2.     synchronized (mCache) {  
  3.          ComponentName component = intent.getComponent();  
  4.          if (component == null) {  
  5.              return null;  
  6.          }  
  7.         LauncherActivityInfoCompat launcherActInfo = mLauncherApps.resolveActivity(intent, user);  
  8.         CacheEntry entry = cacheLocked(component, launcherActInfo, null, user, true, -1);  
  9.         return entry.script;  
  10.     }  
  11. }  

[java]  view plain  copy
  1. private CacheEntry cacheLocked(ComponentName componentName, LauncherActivityInfoCompat info,  
  2.             HashMap<Object, CharSequence> labelCache, UserHandleCompat user,  
  3.             boolean usePackageIcon, int unreadNum) {  
  4.           ……  
  5.        if(componentName.getPackageName().equals("com.android.deskclock"))  
  6.                 entry.script = new ClockScript();  
  7.         if(componentName.getPackageName().equals("com.android.calendar"))  
  8.                 entry.script = new CalendarScript();  
  9.       
  10.         return entry;  
  11. }  


ShortcutInfo.java

[java]  view plain  copy
  1. public IconScript getScript(IconCache iconCache){  
  2.     return iconCache.getScript(promisedIntent != null ? promisedIntent : intent, user);  
  3. }  

BubbleTextView.java

[java]  view plain  copy
  1. public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache,  
  2.             boolean setDefaultPadding, boolean promiseStateChanged) {  
  3. ……  
  4.  mScript = info.getScript(iconCache);  
  5. ……  
  6. }  

	@Override
	public void setCompoundDrawables(Drawable left, Drawable top,
			Drawable right, Drawable bottom) {
		// TODO Auto-generated method stub
	    if(top != null){  
	        if(mScript != null){  
	            top = mScript;
				Rect rect = new Rect();
				rect.set(0, 0, LauncherAppState.getInstance().getInvariantDeviceProfile().iconBitmapSize, 
						LauncherAppState.getInstance().getInvariantDeviceProfile().iconBitmapSize);
	            mScript.setBounds(rect);  
	            if(!mScript.isRuning){
	            	mScript.run(this);  
	            } 
	            	
	        }  
	    } 
		
		super.setCompoundDrawables(left, top, right, bottom);
	}
    

[java]  view plain  copy
  1. public class IconScript extends Drawable{  
  2.     public boolean isRuning = false;  
  3.     public FastBitmapDrawable mFastBitmapDrawable = null;  
  4.     protected Paint mPaint = new Paint();  
  5.       
  6.     public IconScript(){  
  7.         mPaint.setAntiAlias(true);   
  8.         mPaint.setFilterBitmap(true);  
  9.     }  
  10.       
  11.     public void draw(Canvas canvas){  
  12.         if(mFastBitmapDrawable != null){  
  13.             canvas.drawBitmap(mFastBitmapDrawable.getBitmap(), null, getBounds(),mPaint);//画底图  
  14.         }  
  15.     }  
  16.       
  17.     /** 
  18.      * 运行脚本 
  19.      * @param view 
  20.      */  
  21.     public void run(View view){  
  22.         isRuning = true;  
  23.     }  
  24.       
  25.     /** 
  26.      * 停止脚本 
  27.      * (未调用,暂留入口) 
  28.      */  
  29.     public void onStop(){  
  30.         isRuning = false;  
  31.     }  
  32.       
  33.     /** 
  34.      * 暂停脚本 
  35.      * (未调用,暂留入口) 
  36.      */  
  37.     public void onPause(){  
  38.         isRuning = false;  
  39.     }  
  40.       
  41.     /** 
  42.      * 恢复脚本 
  43.      * (未调用,暂留入口) 
  44.      */  
  45.     public void onResume(){  
  46.         isRuning = true;  
  47.     }  
  48.   
  49.     @Override  
  50.     public int getOpacity() {  
  51.         // TODO Auto-generated method stub  
  52.         return 0;  
  53.     }  
  54.   
  55.     @Override  
  56.     public void setAlpha(int arg0) {  
  57.         // TODO Auto-generated method stub  
  58.           
  59.     }  
  60.   
  61.     @Override  
  62.     public void setColorFilter(ColorFilter arg0) {  
  63.         // TODO Auto-generated method stub  
  64.           
  65.     }  
  66.       
  67.     @Override  
  68.     public int getIntrinsicWidth() {  
  69.         int width = getBounds().width();  
  70.         if (width == 0) {  
  71.             width = mFastBitmapDrawable.getBitmap().getWidth();  
  72.         }  
  73.         return width;  
  74.     }  
  75.   
  76.     @Override  
  77.     public int getIntrinsicHeight() {  
  78.         int height = getBounds().height();  
  79.         if (height == 0) {  
  80.             height = mFastBitmapDrawable.getBitmap().getHeight();  
  81.         }  
  82.         return height;  
  83.     }  
  84.   
  85.     @Override  
  86.     public int getMinimumWidth() {  
  87.         return getBounds().width();  
  88.     }  
  89.   
  90.     @Override  
  91.     public int getMinimumHeight() {  
  92.         return getBounds().height();  
  93.     }  
  94.       
  95.     @Override  
  96.     public void setFilterBitmap(boolean filterBitmap) {  
  97.         mPaint.setFilterBitmap(filterBitmap);  
  98.         mPaint.setAntiAlias(filterBitmap);  
  99.     }  
  100.       
  101.     public void setFastBitmapDrawable(FastBitmapDrawable drawable){  
  102.         mFastBitmapDrawable = drawable;  
  103.     }  
  104.       
  105.     public FastBitmapDrawable setFastBitmapDrawable(){  
  106.         return mFastBitmapDrawable;  
  107.     }  
  108. }  
</pre><pre code_snippet_id="1674198" snippet_file_name="blog_20160506_3_9573334" name="code" class="java">/** 
 * dynamic calendar Icon
 * 
 */  
public class CalendarScript extends IconScript {
    Time    mTime     = new Time();  
	Rect    mSrcRect  = new Rect();  
	Rect    mDestRect = new Rect();  
    Context mContext;  
    public CalendarScript() {  
        super();  
        mContext = LauncherAppState.getInstance().getContext();
    }  
  
    @Override  
    public void draw(Canvas canvas) {  
        super.draw(canvas);  
        mTime.setToNow();  
//        canvas.drawBitmap(getRes(mTime.monthDay), null, getBounds(), mPaint);  
		Bitmap calendarBackground = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.calendar);
		Bitmap dayOfMonthRes      = getCalendarDataRes(mTime.monthDay);
		Bitmap dayOfWeekRes       = getCalendarWeekDayRes(mTime.weekDay);
		int width  = LauncherAppState.getInstance().getInvariantDeviceProfile().iconBitmapSize;
		int height = width;
		mDestRect.set(0, 0, width, height);
		mSrcRect.set(0, 0, calendarBackground.getWidth(), calendarBackground.getHeight());
		
		canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG));
		canvas.drawBitmap(calendarBackground, mSrcRect, mDestRect, null);
		canvas.drawBitmap(dayOfMonthRes, (width - dayOfMonthRes.getWidth()) / 2 , (height - dayOfMonthRes.getHeight()) / 2 + 10, null);
		canvas.drawBitmap(dayOfWeekRes, (width - dayOfWeekRes.getWidth()) / 2, dayOfWeekRes.getHeight(), null);
		
		canvas.save(Canvas.ALL_SAVE_FLAG);
		canvas.restore();
    }  
  
    @Override  
    public void run(final View view) {  
  
        IntentFilter filter = new IntentFilter();  
        filter.addAction(Intent.ACTION_DATE_CHANGED);  
        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); 
        filter.addAction("android.intent.action.TIME_SET");
        view.getContext().registerReceiver(new BroadcastReceiver() {  
            @Override  
            public void onReceive(Context arg0, Intent arg1) {  
                view.postInvalidate();  
            }  
        }, filter);  
  
        super.run(view);  
    }  
      
	 private Bitmap getCalendarDataRes(int monthDay){  
	        int res = mContext.getResources().getIdentifier("calendar_data_" + monthDay, "drawable", mContext.getPackageName());  
	        BitmapDrawable bitmapDrawable = (BitmapDrawable)mContext.getResources().getDrawable(res);  
	        return bitmapDrawable.getBitmap();  
	}  
	 private Bitmap getCalendarWeekDayRes(int weekDay){  
	        int res = mContext.getResources().getIdentifier("calendar_week_" + weekDay, "drawable", mContext.getPackageName());  
	        BitmapDrawable bitmapDrawable = (BitmapDrawable)mContext.getResources().getDrawable(res);  
	        return bitmapDrawable.getBitmap();  
	}
}


/** 
 * dynamic Clock Icon
 * 
 */  
public class ClockScript extends IconScript {
	Rect    mSrcRect  = new Rect();  
	Rect    mDestRect = new Rect();  
	private int     mIconSize;
	private Context mContext; 
	private Time    mTime;
	private Bitmap  mSecond, mMinute, mHour, mBackground; 
	private int     mHiegtOffset, mWidthOffset;
    /** 
     * Results show target View 
     */  
    private View mView;  
    /** 
     * notify System to invalidate 
     */  
    private ClockThread mClockThread = null;  
    /** 
     * is showen on the screen now 
     */  
    private boolean mIsShowInScreen = false;  
      
    public ClockScript(){  
        super();  
        mContext  = LauncherAppState.getInstance().getContext();
        mIconSize = LauncherAppState.getInstance().getInvariantDeviceProfile().iconBitmapSize;
    }  
    public void run(View view) {  
        mView       = view;  
        mTime       = new Time();
        mBackground = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.launcher_theme_ic_app_clock_bg);//getBounds();  
        mSecond     = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.launcher_theme_ic_app_clock_second_draw_by_pic);
        mMinute     = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.launcher_theme_ic_app_clock_minute_draw_by_pic);
        mHour       = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.launcher_theme_ic_app_clock_hour_draw_by_pic);
        mDestRect.set(0, 0, mIconSize, mIconSize);
        mSrcRect.set(0, 0, mBackground.getWidth(), mBackground.getHeight());
        mHiegtOffset = (mIconSize - mBackground.getHeight()) / 2;
        mWidthOffset = (mIconSize - mSecond.getWidth()) / 2;
        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);  
//      mPaint.setColor(Color.MAGENTA);  
//        canvas.drawCircle(mRect.centerX(), mRect.centerY(), 3, mPaint);  
          
        if(mClockThread.wait){  
            mClockThread.resumeRun();  
        }  
    }  
    /** 
     * draw Indicator 
     * @param canvas 
     * @param centerX 
     * @param centerY 
     * @param p 
     */  
    private void drawIndicator(Canvas canvas){  
          
        mTime.setToNow();  
//        p.setStrokeWidth(2);  
//        p.setColor(Color.BLACK);  

        float hourAngle = (float)mTime.hour  / 12 * 360 + (float)mTime.minute / 60 * (360 / 12);
        float minAngle  = (float)mTime.minute / 60 * 360;  
        float secAngle  = (float)mTime.second / 60 * 360; 
        
        
        
        canvas.save();
        canvas.drawBitmap(mBackground, mSrcRect, mDestRect, null);
        
        canvas.restore(); 
        canvas.save();
        canvas.rotate(hourAngle, mIconSize / 2, mIconSize / 2);
        canvas.drawBitmap(mHour, mWidthOffset, mHiegtOffset, null);
        
        canvas.restore(); 
        canvas.save();
        canvas.rotate(minAngle, mIconSize / 2, mIconSize / 2);
        canvas.drawBitmap(mMinute, mWidthOffset, mHiegtOffset, null);
        
        canvas.restore(); 
        canvas.save();
        canvas.rotate(secAngle, mIconSize / 2, mIconSize / 2);
        canvas.drawBitmap(mSecond, mWidthOffset, mHiegtOffset, null);
        
        canvas.restore(); 
        
//        canvas.drawLine(centerX, centerY,   
//                (int)(centerX + (mRect.width()/2-35) * Math.cos((mTime.hour+(float)mTime.minute/60) * (Math.PI / 6) - Math.PI / 2)),   
//                (int)(centerY + (mRect.width()/2-35) * Math.sin((mTime.hour+(float)mTime.minute/60) * (Math.PI / 6) - Math.PI / 2)), p);  
//        canvas.drawLine(centerX, centerY,   
//                (int)(centerX + (mRect.width()/2-50) * Math.cos((mTime.hour+(float)mTime.minute/60) * (Math.PI / 6) + Math.PI / 2)),   
//                (int)(centerY + (mRect.width()/2-50) * Math.sin((mTime.hour+(float)mTime.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(mTime.minute * (Math.PI / 30) - Math.PI / 2)),  
//                (int)(centerY + (mRect.width()/2-27) * Math.sin(mTime.minute * (Math.PI / 30) - Math.PI / 2)),p);  
//        canvas.drawLine(centerX, centerY,  
//                (int)(centerX + (mRect.width()/2-48) * Math.cos(mTime.minute * (Math.PI / 30) + Math.PI / 2)),  
//                (int)(centerY + (mRect.width()/2-48) * Math.sin(mTime.minute * (Math.PI / 30) + Math.PI / 2)),p);  
////        p.setColor(Color.RED);  
//        //秒针  
//        canvas.drawLine(centerX, centerY,  
//                (int)(centerX + (mRect.width()/2-24) * Math.cos(mTime.second * (Math.PI / 30) - Math.PI / 2)),  
//                (int)(centerY + (mRect.width()/2-24) * Math.sin(mTime.second * (Math.PI / 30) - Math.PI / 2)),p);  
////        p.setStrokeWidth(3);  
//        canvas.drawLine(centerX, centerY,  
//                (int)(centerX + (mRect.width()/2-45) * Math.cos(mTime.second * (Math.PI / 30) + Math.PI/2)),  
//                (int)(centerY + (mRect.width()/2-45) * Math.sin(mTime.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();  
                        }  
                    }  
                }  
            }  
        }  
    }  
  
}



你可能感兴趣的:(Android Launcher 时钟、日历图标随时间动态变更)