首页 > 其他分享 >Android14———Launcher去除抽屉模式的实现,将所有app显示在桌面上

Android14———Launcher去除抽屉模式的实现,将所有app显示在桌面上

时间:2024-10-19 13:21:31浏览次数:8  
标签:Launcher app Android14 item ArrayList new dropTarget final

1、首先需要增加一个标志flag,通过true或者false进行是否去除抽屉模式的表达。

FeatureFlags.java
public static final boolean REMOVE_DRAWER = true; 

2、将allApp显示到桌面Workspace上

LoaderTask.java

先导包:

import android.util.Pair;
import java.util.function.Supplier;
import com.android.launcher3.model.ItemInstallQueue;

再在run方法中加入条件判断语句,进行控制。

			if(FeatureFlags.REMOVE_DRAWER){
				verifyApplications(); 
			}

注意代码放在的位置,如下图所示:

在这里插入图片描述

最后增加一个verifyApplications方法进行将allapp的一个显示的操作。

	public void verifyApplications(){
		final Context context = mApp.getContext();
		ArrayList<Pair<ItemInfo, Object>> installQueue = new ArrayList<>();
		List<UserHandle> profiles = mUserManager.getUserProfiles();
		
		for (UserHandle user : profiles) {
            final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null, user);
            ArrayList<ItemInstallQueue.PendingInstallShortcutInfo> added = new ArrayList<ItemInstallQueue.PendingInstallShortcutInfo>();
            synchronized (this) {
                for (LauncherActivityInfo app : apps) {
                    ItemInstallQueue.PendingInstallShortcutInfo pendingInstallShortcutInfo = new ItemInstallQueue.PendingInstallShortcutInfo(app.getComponentName().getPackageName(), user);
					Log.d("mlb","11111:"+app.getComponentName().getPackageName()+"user:"+user);
					added.add(pendingInstallShortcutInfo);
                    installQueue.add(pendingInstallShortcutInfo.getItemInfo(context));
                }
            }
            if (!added.isEmpty()) {
                mApp.getModel().addAndBindAddedWorkspaceItems(installQueue);
            }
        }
		
	}

咳咳,下面我用AI解释一下上面的代码哈:
这段代码定义了一个名为 verifyApplications 的方法,它的作用是验证或刷新启动器(Launcher)中的应用程序列表,并将新的快捷方式添加到启动器的工作区。以下是对这个方法的逐行解释:

  1. public void verifyApplications(){}

    • 定义了一个公共方法 verifyApplications,该方法没有接收任何参数,也不返回任何值。
  2. final Context context = mApp.getContext();

    • 获取与启动器应用相关的 Context 对象。mApp 可能是一个全局变量,代表启动器应用的实例。
  3. ArrayList<Pair<ItemInfo, Object>> installQueue = new ArrayList<>();

    • 创建一个 ArrayList,用于存储待安装的快捷方式信息。Pair 类型的 installQueue 存储了 ItemInfo 和一个关联的 Object
  4. List<UserHandle> profiles = mUserManager.getUserProfiles();

    • 获取当前设备上所有用户配置文件的列表。mUserManager 是一个全局变量,代表设备的用户管理服务。
  5. for (UserHandle user : profiles) {

    • 遍历所有用户配置文件。
  6. final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null, user);

    • 对于每个用户,获取该用户可以启动的所有活动(应用)的列表。mLauncherApps 是一个全局变量,代表启动器应用的 LauncherApps 服务。
  7. ArrayList<ItemInstallQueue.PendingInstallShortcutInfo> added = new ArrayList<>();

    • 创建一个 ArrayList,用于存储本次添加的快捷方式信息。
  8. synchronized (this) {

    • 使用 synchronized 关键字来确保以下代码块在同一时间只能被一个线程执行,这是为了防止多线程环境下的数据不一致问题。
  9. for (LauncherActivityInfo app : apps) {

    • 遍历所有应用。
  10. ItemInstallQueue.PendingInstallShortcutInfo pendingInstallShortcutInfo = new ItemInstallQueue.PendingInstallShortcutInfo(app.getComponentName().getPackageName(), user);

    • 为每个应用创建一个 PendingInstallShortcutInfo 对象,它包含了应用的包名和用户信息。
  11. Log.d("mlb","11111:"+app.getComponentName().getPackageName()+"user:"+user);

    • 输出一条调试日志,显示应用的包名和用户信息。
  12. added.add(pendingInstallShortcutInfo);

    • 将新创建的 PendingInstallShortcutInfo 对象添加到 added 列表中。
  13. installQueue.add(pendingInstallShortcutInfo.getItemInfo(context));

    • PendingInstallShortcutInfo 对象转换为 ItemInfo 对象,并添加到 installQueue 列表中。
  14. }

    • 结束 for 循环。
  15. if (!added.isEmpty()) {

    • 检查 added 列表是否不为空。
  16. mApp.getModel().addAndBindAddedWorkspaceItems(installQueue);

    • 如果 added 列表不为空,调用 mAppgetModel 方法来获取启动器的模型,并使用 addAndBindAddedWorkspaceItems 方法将 installQueue 中的快捷方式添加到启动器的工作空间,并绑定它们。
  17. }

    • 结束 if 代码块。
  18. }

    • 结束 synchronized 代码块。
  19. }

    • 结束 for 循环。
  20. }

    • 结束 verifyApplications 方法。

这个方法的主要目的是确保启动器的工作空间包含所有用户配置文件中安装的应用的快捷方式。这通常在启动器应用启动时执行,或者在应用安装或更新后执行,以确保工作空间中的快捷方式是最新的。通过遍历所有用户配置文件,这个方法确保了所有用户的主屏幕都包含了最新的应用快捷方式。

ok,AI解释到此结束

3、还差一点,马上就能将app显示到桌面上了

    @Override
    public final void run() {
        boolean isModelLoaded = Objects.requireNonNull(mModel).isModelLoaded();
        testLogD(WORK_TAB_MISSING, "modelLoaded: " + isModelLoaded + " forTask: " + this);
        if (!isModelLoaded) {
            if (DEBUG_TASKS) {
                Log.d(TAG, "Ignoring model task since loader is pending=" + this);
            }
            // Loader has not yet run.
            //return;
        }
		if(!FeatureFlags.REMOVE_DRAWER){
            return;
        }
        execute(mApp, mDataModel, mAllAppsList);
    }

在这里插入图片描述

上面这个代码,当我们需要显示所有app到桌面的时候,那么就不会执行return;这个语句,就去执行execute这个方法。

4、注意哈,上面的代码在桌面上有可能只显示下载的app,而不显示系统自带的app

上面的代码会进行往下走,会走到LauncherModel.java这个文件中:

LauncherModel.java
    public void addAndBindAddedWorkspaceItems(
            @NonNull final List<Pair<ItemInfo, Object>> itemList) {
        for (Callbacks cb : getCallbacks()) {
            cb.preAddApps();
        }
        enqueueModelUpdateTask(new AddWorkspaceItemsTask(itemList));
    }

可以看到在上面的代码中,会new一个AddWorkspaceItemsTask对象,开启添加的任务,我们深入进去看一下:

AddWorkspaceItemsTask.java

先导包:

import android.util.Log;

然后在构造方法中打Log,发现确实是走到这个地方的

    public AddWorkspaceItemsTask(@NonNull final List<Pair<ItemInfo, Object>> itemList,
            @NonNull final WorkspaceItemSpaceFinder itemSpaceFinder) {
        mItemList = itemList;
		for(Pair i : mItemList){
			Log.d("mmlb",""+i);
		}
        mItemSpaceFinder = itemSpaceFinder;
    }

在这里插入图片描述
还是在这个文件中,我们继续看:

    @Override
    public void execute(@NonNull final LauncherAppState app, @NonNull final BgDataModel dataModel,
            @NonNull final AllAppsList apps) {
        if (mItemList.isEmpty()) {
            return;
        }

        final ArrayList<ItemInfo> addedItemsFinal = new ArrayList<>();
        final IntArray addedWorkspaceScreensFinal = new IntArray();

        synchronized (dataModel) {
            IntArray workspaceScreens = dataModel.collectWorkspaceScreens();

            List<ItemInfo> filteredItems = new ArrayList<>();
            for (Pair<ItemInfo, Object> entry : mItemList) {
                ItemInfo item = entry.first;
                if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
                        item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
                    // Short-circuit this logic if the icon exists somewhere on the workspace
                    if (shortcutExists(dataModel, item.getIntent(), item.user)) {
                        continue;
                    }

                    // b/139663018 Short-circuit this logic if the icon is a system app
                    if (PackageManagerHelper.isSystemApp(app.getContext(),
                            Objects.requireNonNull(item.getIntent()))) {
                       // continue;
                    }
                }

                if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
                    if (item instanceof WorkspaceItemFactory) {
                        item = ((WorkspaceItemFactory) item).makeWorkspaceItem(app.getContext());
                    }
                }
                if (item != null) {
                    filteredItems.add(item);
                }
            }

在这里插入图片描述
将上面的continue注释掉,这样的话,系统app也会加载到桌面上。

5、好,显示到桌面上了,下面就要禁止上滑的操作了

PortraitStatesTouchController.java

先导包:

import com.android.launcher3.config.FeatureFlags;

加判断逻辑:

		if(FeatureFlags.REMOVE_DRAWER){
			return false;
		}

返回值是false就表示的是不能上滑显示出所有的app,上面的代码加载的位置如下哦:

在这里插入图片描述
这样写到这里,上滑就被禁止了。注意一个文件吧,AllAppsSwipeController.java这个文件你可能会用到。

6、还一个问题,显示到桌面上的app就没有移除按钮了,应该改成取消按钮,点击取消按钮的时候,图标回到原处,其余没有任何操作即可。

移除按钮变取消按钮:

DeleteDropTarget.java

先导包:

import com.android.launcher3.config.FeatureFlags;

再加条件判断语句进行取消拖拽操作:

    protected void drop(DropTarget dropTarget, Runnable flingAnimation) {
        final int[] coordinates = mCoordinatesTemp;
        mDragObject.x = coordinates[0];
        mDragObject.y = coordinates[1];

        // Move dragging to the final target.
        if (dropTarget != mLastDropTarget) {
            if (mLastDropTarget != null) {
                mLastDropTarget.onDragExit(mDragObject);
            }
            mLastDropTarget = dropTarget;
            if (dropTarget != null) {
                dropTarget.onDragEnter(mDragObject);
            }
        }

        mDragObject.dragComplete = true;
        if (mIsInPreDrag) {
            if (dropTarget != null) {
                dropTarget.onDragExit(mDragObject);
            }
            return;
        }

        // Drop onto the target.
        boolean accepted = false;
        if (dropTarget != null) {
            dropTarget.onDragExit(mDragObject);
            if (dropTarget.acceptDrop(mDragObject)) {
                if (flingAnimation != null) {
                    flingAnimation.run();
                } else {
                    dropTarget.onDrop(mDragObject, mOptions);
                }
                accepted = true;
				if (FeatureFlags.REMOVE_DRAWER) {
                    cancelDrag();
                }
            }
        }
        final View dropTargetAsView = dropTarget instanceof View ? (View) dropTarget : null;
        dispatchDropComplete(dropTargetAsView, accepted);
    }

修改处如图所示:

在这里插入图片描述

取消按钮相应的不能移除图标的实现:

DeleteDropTarget.java

先导包:

import com.android.launcher3.config.FeatureFlags;

再加条件控制语句:

    private boolean canRemove(ItemInfo item) {
    	if(FeatureFlags.REMOVE_DRAWER) {
        	return false ;
        }
        return item.id != ItemInfo.NO_ID;
    }

在这里插入图片描述

over:给你们个链接,这朋友写的比我还详细,不同的人,有不一样的实现方法,地方点也不同。

点击我看另一个朋友写的博客,学到就是赚到。

标签:Launcher,app,Android14,item,ArrayList,new,dropTarget,final
From: https://blog.csdn.net/qq_45696288/article/details/143067438

相关文章

  • Apple提出MM1.5:多模态大型语言模型微调的方法、分析和见解
    摘要我们介绍了MM1.5,一个新的多模态大型语言模型(MLLM)家族,旨在增强在富文本图像理解、视觉参照和定位以及多图像推理方面的能力。在MM1架构的基础上,MM1.5采用以数据为中心的模型训练方法,系统地探索了整个模型训练生命周期中各种数据混合的影响。这包括用于持续预......
  • [Mybatis Plus]lambdaQueryWrapper和QueryWrapper的选择
    结论更推荐使用:LambdaQueryWrapperQueryWrapper:灵活但是不够类型安全LambdaQueryWrapper:安全分析在MyBatis-Plus中,QueryWrapper和LambdaQueryWrapper都是用来构建查询条件的工具类。它们都提供了链式调用的方式来构造SQL语句中的WHERE条件部分,但是两者之间存在一些差异。......
  • 最佳的10款App安全测试工具
    网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!移动互联网时代,我们的生活和工作深受App影响。伴随移动App的广泛应用,App安全日益重要。本文介绍了App开发可能用到的安全测试工具。当今,全球移动用户大约超过37亿。GooglePlay上大约有220万个App,苹果......
  • 门店收银系统源码-php+flutter+uniapp
     1.系统开发语言核心开发语言: PHP、HTML5、Dart后台接口: PHP7.3后台管理网站: HTML5+vue2.0+element-ui+css+js线下收银台(安卓/PC收银、安卓自助收银): Dart3框架:Flutter 3.19.6移动店务助手: uniapp线上商城: uniapp2.线下收银端线下收银端支持pc版(exe安装......
  • python+uniapp微信小程序线上点餐管理信息系统java+nodejs-毕业设计
    前端开发框架:vue.js数据库mysql版本不限后端语言框架支持:1java(SSM/springboot)-idea/eclipse2.Nodejs+Vue.js-vscode3.python(flask/django)--pycharm/vscode4.php(thinkphp/laravel)-hbuilderx数据库工具:Navicat/SQLyog等都可以 随着科技的不断发展,移动互联网......
  • java代码生成器(controller,service,mapper)
    packagecom.cn.codeGenerator;importjava.awt.*;importjava.io.File;importjava.io.FileWriter;importjava.io.IOException;importjava.sql.*;importjava.util.ArrayList;importjava.util.List;publicclassCodeGenerator{privatestaticfinalStri......
  • abc284D Happy New Year 2023
    给定整数N,已知N可以写成ppq的形式,其中p和q为不同质数,求p和q。1<=N<=9E18分析:p与q的最小值不超过3E6,可以枚举。#include<bits/stdc++.h>usingi64=longlong;std::vector<int>minp,prime;voidsieve(intn){ minp.assign(n+1,0); prime.clear(); for(inti=2......
  • uni-app小程序(快手、抖音)getCurrentPages使用坑位记录2
    前情uni-app是我比较喜欢的跨平台框架,它能开发小程序/H5/APP(安卓/iOS),重要的是对前端开发友好,自带的IDE让开发体验也挺棒的,现公司项目就是主推uni-app,我主要负责抖音和快手端小程序。坑位公司历史原因项目有APP端小程序端,但并不使用uni-app的一端发布所有平台,各端都有它的开发......
  • Android 13.0 Launcher3定制之首页时钟小部件字体大小修改
    1.前言在13.0的系统rom产品开发中,在一些Launcher3的定制化开发中,在对于一些小屏幕的产品开发中,在首页添加时钟小部件会显得字体有点小,所以为了整体布局美观就需要改动小部件的布局日期字体的大小来实现整体的布局美观效果,接下来来具体实现相关的功能具体效果图:2.Launcher......
  • 基于51单片机的智能台灯光照坐姿检测PWM红外无线手机蓝牙/WiFi/WiFi视频监控APP设计C0
    51单片机+人走灯灭+光敏AD采集+自动+手动+10档调节+坐姿监测+蜂鸣器+OLED屏/C01N51+蓝牙APP控制+人走灯灭+光敏AD采集+自动+手动+10档调节+坐姿监测+蜂鸣器+OLED屏/C01B51+WIFI-APP控制+人走灯灭+光敏AD采集+自动+手动+10档调节+坐姿监测+蜂鸣器+OLED屏/C01W51+视频监控+WIF......