Launcher3实现一屏的图标位置细节

本文详细分析了Launcher3代码中实现一屏显示所有应用的逻辑,关键在于调整添加应用的位置。通过修改`findSpaceForItem`方法,确保新应用被放置在第一屏而非第二屏。博客指出原有代码中对于首选屏幕的处理可能导致问题,并提供了修正后的代码片段,以避免在没有抽屉功能的情况下,系统应用始终占据第一屏。通过对代码逐行解释,帮助开发者理解如何寻找和设置应用图标的空间,从而自定义启动器布局。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        Launcher3代码的实现一屏的,前面几个步骤网上已经有很多了,就是加一个标志,然后在   LauncherModel加载数据的地方使用verifyApplications()方法,里面

if  (LauncherAppState.isDisableAllApps()) {

   verifyApplications(); }

然后在这个方法里面使用到了addAndBindAddedWorkspaceItems(context , added)

把第二屏的icon,其实是除了系统的Icon第二屏幕的,比如你安装的,第一次安装的都在第二屏,然后把后去到第二屏的数据,然后显示到第一屏,也就是桌面第一页。还有一些步骤都是可以看到的,包括一些安装后的处理代码

         现在的重点是,发现有时候第一屏永远(已经没有抽屉了)就是系统应用,第二屏才是安装的应用。关键代码就在下面:

         

Pair<Long, int[]> findSpaceForItem(
            Context context,
            ArrayList<Long> workspaceScreens,
            ArrayList<Long> addedWorkspaceScreensFinal,
            int spanX, int spanY) {
        LongSparseArray<ArrayList<ItemInfo>> screenItems = new LongSparseArray<>();

        // Use sBgItemsIdMap as all the items are already loaded.
        assertWorkspaceLoaded();
        synchronized (sBgLock) {
            for (ItemInfo info : sBgItemsIdMap) {
                if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
                    ArrayList<ItemInfo> items = screenItems.get(info.screenId);
                    if (items == null) {
                        items = new ArrayList<>();
                        screenItems.put(info.screenId, items);
                    }
                    items.add(info);
                }
            }
        }
//        ItemInfo itemInfo = new ItemInfo();
//        itemInfo.cellX=0;
//        itemInfo.cellY = 0;
//        itemInfo.spanX = 5;
//        itemInfo.spanY = 1;
//        if(screenItems.get(0)!=null){
//            screenItems.get(0).add(itemInfo);
//        }else {
//            ArrayList<ItemInfo> list = new ArrayList<>();
//            list.add(itemInfo);
//            screenItems.put(0, list);
//        }
//        CellLayout cl = LauncherAppState.getInstance().launcher.getWorkspace().getScreenWithId(0);



        for(int i =0;i<screenItems.size();i++){

            if(screenItems.get(i)!=null) {

                for (int j = 0; j < screenItems.get(i).size(); j++) {

                    Log.i("addFolderItem","screenItems:"+"screenId:"+i+"--"+screenItems.get(i).get(j).title+"--"+screenItems.get(i).get(j).cellX+"--"+screenItems.get(i).get(j).cellY+"--"+screenItems.get(i).get(j).spanX+"--"+screenItems.get(i).get(j).spanY);

                }
            }

        }

        for(int s =0 ;s<workspaceScreens.size();s++){

            Log.i("addFolderItem",""+workspaceScreens.get(s));
        }

        // Find appropriate space for the item.
        long screenId = 0;
        int[] cordinates = new int[2];
        boolean found = false;



//        // First check the preferred screen.
//        int preferredScreenIndex = workspaceScreens.isEmpty() ? 0 : 1;
//        if (preferredScreenIndex < screenCount) {
//            screenId = workspaceScreens.get(preferredScreenIndex);
//            found = findNextAvailableIconSpaceInScreen(
//                    screenItems.get(screenId), cordinates, spanX, spanY);
//        }

//        Log.i("addFolderItem","screenId:"+screenId+"preferredScreenIndex:"+preferredScreenIndex);
//        Log.i("addFolderItem","found:"+found);
//        Log.i("addFolderItem","cordinates:"+"x:"+cordinates[0]+"y"+cordinates[1]);

        for(int i=0;i<workspaceScreens.size();i++){
            Log.i("addFolderItem","workspaceScreens"+workspaceScreens.get(i));
        }
        if(workspaceScreens.size() == 0){
            workspaceScreens.add(0L);
        }
        int screenCount = workspaceScreens.size();
        if (!found) {
            // Search on any of the screens starting from the first screen.
            for (int screen = 0; screen < screenCount; screen++) {
//                screenId = workspaceScreens.get(screen);
                if (findNextAvailableIconSpaceInScreen(
                        screenItems.get(screen), cordinates, spanX, spanY)) {
                    // We found a space for it
                    found = true;
                    screenId = screen;
                    Log.i("addFolderItem","found1:"+found+"screenId:"+screenId);
                    break;
                }
            }
        }

        if (!found) {
            // Still no position found. Add a new screen to the en
            // d.
            screenId = LauncherSettings.Settings.call(context.getContentResolver(),
                    LauncherSettings.Settings.METHOD_NEW_SCREEN_ID)
                    .getLong(LauncherSettings.Settings.EXTRA_VALUE);

            // Save the screen id for binding in the workspace
            workspaceScreens.add(screenId);
            addedWorkspaceScreensFinal.add(screenId);

            // If we still can't find an empty space, then God help us all!!!
            if (!findNextAvailableIconSpaceInScreen(
                    screenItems.get(screenId), cordinates, spanX, spanY)) {
                throw new RuntimeException("Can't find space to add the item");
            }
            Log.i("addFolderItem","found2:"+found+"screenId:"+screenId);
        }
        Log.i("addFolderItem","cordinatesEnd:"+"x:"+cordinates[0]+"y"+cordinates[1]+"screenId:"+screenId);
        return Pair.create(screenId, cordinates);
    }

以上代码就是在改变方法后,把第二层获取到的放在第一屏,这个是关键方法,去寻找空余的位置。

首先会获取系统的应用,然后看系统在哪一屏,然后再根据获取的要显示的Icon,来确定新的Icon也就是第二屏的位置,这个方法用来寻找位置,然后保存到数据库。

首先如果没有一个screen,然后我就会主动添加一屏,然后去掉了 preferredScreenIndex的相关代码,因为这个是为了实现抽屉的代码,然后从screen开始找空余位置。做项目的时候一直出现的问题就是因为系统以前的代码是有preferredScreenIndex这一段代码,而且找不到,走第二个寻找的时候是从screen为1开始的,所以就坑了。

       通过逐层分析代码,找到这个位置,记下来,防止以后有人用Launcher3方便解决问题

     

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值