Android图标上显示数字

Android图标上显示数字或加上数字的功能,直到Android4.4也没有实现。所以要修改系统的应用launcher来实现该效果。


之前你可能要参考其他一些博客或资料,对launcher的架构有一个相当的了解。这里不再作过多的分析。


找到src/com/android/launcher2/PagedViewIcon.java

这个类是用于显示所有应用列表里的一个图标,就是TextView然后使用setCompoundDrawablesWithIntrinsicBounds()方法加上icon

图标icon取自ApplicationInfo(注意了这个ApplicationInfo类是在launcher里自定义的,不是SDK提供的ApplicationInfo),对其进行修改,增加一个backupIcon属性用于备份Icon以便以后恢复成原来的状态。

至于加上数字就是在canvas上画个圆和写上数字,如果要有更好的效果就自己画吧。

   public void applyFromApplicationInfo(ApplicationInfo info, boolean scaleUp,
            HolographicOutlineHelper holoOutlineHelper) {
        mHolographicOutlineHelper = holoOutlineHelper;
        mIcon = info.iconBitmap;
        
        //modify --start--
        Boolean isExistCount = false;
        Boolean isRestore = false;
        String count = null;
        for(Map<String,String> map : LauncherApplication.countIconList){
            if(map.get("pkgName").equals( info.componentName.getPackageName() )){
                count = map.get("count");
                if(count.equals("0")){
                    isRestore = true;
                }else {
                    isExistCount = true;
                }
                if(info.backupIcon == null){
                    info.backupIcon = mIcon.copy(Bitmap.Config.ARGB_8888, true);
                }
                break;
            }
        }
        
        if(isExistCount){
            setCompoundDrawablesWithIntrinsicBounds(null, generatorNumIcon(count), null, null);
        }else if(isRestore){
            setCompoundDrawablesWithIntrinsicBounds(null, restoreIcon(info.backupIcon), null, null);
        }
        else{
            setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null);
        }
        //old:setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null);
        //modify --end--
        
        setText(info.title);
        setTag(info);
    }
    
    //modify --start--
    private Drawable restoreIcon(Bitmap b) {
        Drawable mDrawable = new FastBitmapDrawable(b);
        Canvas canvas = new Canvas(mIcon);
        canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR); //清空画布
        mDrawable.draw(canvas); //画原图
        return mDrawable;
    }

    private Drawable generatorNumIcon(String count){
        final int X = mIcon.getWidth() - 18;
        final int Y = 18;
        Drawable mDrawable = new FastBitmapDrawable(mIcon);
        Canvas canvas = new Canvas(mIcon);
        
        Paint bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        bgPaint.setColor(Color.RED);
        canvas.drawCircle( X+5, Y-5, 12, bgPaint);
        
        //启用抗锯齿和使用设备的文本字距  
        Paint countPaint = new Paint(Paint.ANTI_ALIAS_FLAG|Paint.DEV_KERN_TEXT_FLAG);  
        countPaint.setColor(Color.WHITE);  
        countPaint.setTextSize(15f);  
        //countPaint.setTypeface(Typeface.DEFAULT_BOLD);
        int c = Integer.parseInt(count);
        if(c>99){
            canvas.drawText("99", X-3 , Y, countPaint);
        }else if(c>9){
            canvas.drawText(count, X-3 , Y, countPaint);
        }else{
            canvas.drawText(count, X+1 , Y, countPaint);
        }
        
        mDrawable.draw(canvas);
        return mDrawable;
    }
    //modify --end--

其他应用通过广播来通知修改数字。

新建一个类用于接收广播,当有广播来时将数据保存到LauncherApplication里,并且刷新页面。

public class CountIconReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        
        String pkgName = intent.getStringExtra("pkgName");
        if(pkgName == null){
            Log.e("CountIconReceiver","pkgName=null");
            return;
        }
        String count = String.valueOf(intent.getIntExtra("count", 0));
        
        for(int i = 0; i < LauncherApplication.countIconList.size(); i++)
        {
            HashMap<String,String> tempMap = (HashMap<String, String>) LauncherApplication.countIconList.get(i);
            if(tempMap.get("pkgName").equals(pkgName)){
                tempMap.put("count", count);
                Log.d("CountIconReceiver","Receiver exist pkgName:"+pkgName+" count:"+count);
                update();
                return;
            }
        }
        Map<String,String> map = new HashMap<String,String>();
        map.put("pkgName",pkgName);
        map.put("count",count);
        LauncherApplication.countIconList.add(map);
        Log.d("MXY-L","Receiver pkgName:"+pkgName+" count:"+count);
        update();
    }

    private void update() {
        AppsCustomizePagedView mPagedView = LauncherApplication.mWeakReference.get();
        if(mPagedView != null){
            mPagedView.updatePackages();
        }
    }
}


    在AndroidManifest.xml添加广播接受
        <receiver android:name="com.android.broadcast.CountIconReceiver">
            <intent-filter >
                <action android:name="com.android.launcher.COUNT_ICON"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </receiver>


在src/com/android/launcher2/LauncherApplication.java类加上以下属性。AppsCustomizePagedView就是我们PageViewIcon的容器。

    public static ArrayList< Map<String,String> > countIconList = new ArrayList< Map<String,String> >();
    public static WeakReference<AppsCustomizePagedView> mWeakReference;

在src/com/android/launcher2/Launcher.java类里的onCreate()的最后将AppsCustomizePagedView的对象保存起来。


LauncherApplication.mWeakReference = new WeakReference<AppsCustomizePagedView>(mAppsCustomizeContent);


功能就这样实现完成,使用adb命令测试结果

adb shell am broadcast -a com.android.launcher.COUNT_ICON --es pkgName "com.android.mms" --ei count 11


效果如下:

因为我们修改了Icon里的bitmap,之后包括创建快捷方式和文件夹里的图标都会跟着变化。

如果需要还原只要发送0就好了

adb shell am broadcast -a com.android.launcher.COUNT_ICON --es pkgName "com.android.mms" --ei count 0

 


思考:

如果要实现更细致的要求,比如不在文件夹里显示数字,那么你就不能直接改ApplicationInfo里的Icon,你可能要将在快捷方式的图标BubbleTextView和应用列表的图标PageViewIcon分开修改。但在快捷方式的容器里Workspace里没有很好的刷新方法。这也是我误打误撞直接修改Icon的原因,这样子代码修改也比较少,不会有严重的不同步的问题。





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值