目录
10、切换列数少的layout再切换回来,桌面图标与hotseat图标重复问题:
本文所有代码修改/添加在代码实例的注释begin add和end add之间
1、声明标志字段用以记录当前模式
Launcher.java
isDeskMode:是否桌面模式(非抽屉模式)
isAutoFull:是否自动补位(只做当前是否自动补位开关的值,自动补位功能需要在桌面模式生效,所以声明为私有,然后提供对外方法需要判断同时是桌面模式):
//begin add
public static boolean isDeskMode = false;
private static boolean isAutoFull = false;
public static boolean isAutoFull(){
return isDeskMode && isAutoFull;
}
public static void isAutoFull(boolean autoFull){
isAutoFull = autoFull;
}
//end add
2、把所有图标加载到桌面上
LoaderTask.java
在run方法里面,注释的第二步后面执行一下代码:
// second step
Trace.beginSection("LoadAllApps");
List<LauncherActivityInfo> allActivityList;
try {
allActivityList = loadAllApps();
LauncherAppMonitor.getInstance(mApp.getContext()).onLoadAllAppsEnd(new ArrayList<>(mBgAllAppsList.data));
} finally {
Trace.endSection();
}
logASplit(logger, "loadAllApps");
//begin add
if(Launcher.isDeskMode){
verifyApplications();
}
//end add
verifyApplications()方法:
//把所有App放到workspace里面
public void verifyApplications() {
Context context = mApp.getContext();
ArrayList<Pair<ItemInfo, Object>> installQueue = new ArrayList<>();
UserManager mUserManager = context.getSystemService(UserManager.class);
final List<UserHandle> profiles = mUserManager.getUserProfiles();
ArrayList<ItemInstallQueue.PendingInstallShortcutInfo> added = new ArrayList<>();
LauncherApps mLauncherApps = context.getSystemService(LauncherApps.class);
for (UserHandle user : profiles) {
final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null, user);
synchronized (this) {
for (LauncherActivityInfo info : apps) {
for (AppInfo appInfo : mBgAllAppsList.data) {
String packageName = info.getComponentName().getPackageName();
if (info.getComponentName().equals(appInfo.componentName)) {
ItemInstallQueue.PendingInstallShortcutInfo
mPendingInstallShortcutInfo
= new ItemInstallQueue.PendingInstallShortcutInfo(packageName,info.getUser());
added.add(mPendingInstallShortcutInfo);
installQueue.add(mPendingInstallShortcutInfo.getItemInfo(context));
}
}
}
}
}
if (!added.isEmpty()) {
mApp.getModel().addAndBindAddedWorkspaceItems(installQueue);
}
}
网上的很多博客这个地方都有点不太一样,PendingInstallShortcutInfo都是 InstallShortcutReceiver.PendingInstallShortcutInfo的,但是Android12的代码里面根本就没有InstallShortcutReceiver这个类了,所以全局搜索PendingInstallShortcutInfo发现ItemInstallQueue才有这个类,并且是私有的,我们需要把它改成public。然后网上 InstallShortcutReceiver.PendingInstallShortcutInfo的才是只需要传info和context,我们找到的ItemInstallQueue.PendingInstallShortcutInfo类并不是这样的才是,所以根据它需要的参数传递包名和user。
以上代码加载app不成功需要修改类:BaseModelUpdateTask.java
将原return添加一个判断,如果是桌面模式则继续执行,不要return。
@Override
public final void run() {
if (!mModel.isModelLoaded() && !mIgnoreLoaded) {
if (DEBUG_TASKS) {
Log.d(TAG, "Ignoring model task since loader is pending=" + this);
}
// Loader has not yet run.
//begin add
if(!Launcher.isDeskMode){
return;
}
//end add
}
execute(mApp, mDataModel, mAllAppsList);
}
3、安装新的app之后需要添加到桌面:
PackageUpdatedTask.java
修改方法execute:
bindApplicationsIfNeeded();
//begin add
if(Launcher.isDeskMode){
updateToWorkSpace(app, appsList);
}
//end add
final IntSet removedShortcuts = new IntSet();
// Shortcuts to keep even if the corresponding app was removed
final IntSet forceKeepShortcuts = new IntSet();
updateToWorkSpace方法和加载所有app到桌面类似:
//begin add
public void updateToWorkSpace(LauncherAppState app, AllAppsList appsList) {
Context context = app.getContext();
ArrayList<Pair<ItemInfo, Object>> installQueue = new ArrayList<>();
UserManager mUserManager = context.getSystemService(UserManager.class);
final List<UserHandle> profiles = mUserManager.getUserProfiles();
ArrayList<ItemInstallQueue.PendingInstallShortcutInfo> added = new ArrayList<>();
LauncherApps mLauncherApps = context.getSystemService(LauncherApps.class);
for (UserHandle user : profiles) {
final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null, user);
synchronized (this) {
for (LauncherActivityInfo info : apps) {
for (AppInfo appInfo : appsList.data) {
String packageName = info.getComponentName().getPackageName();
if (info.getComponentName().equals(appInfo.componentName)) {
ItemInstallQueue.PendingInstallShortcutInfo
mPendingInstallShortcutInfo
= new ItemInstallQueue.PendingInstallShortcutInfo(packageName,info.getUser());
added.add(mPendingInstallShortcutInfo);
installQueue.add(mPendingInstallShortcutInfo.getItemInfo(context));
}
}
}
}
}
if (!added.isEmpty()) {
app.getModel().addAndBindAddedWorkspaceItems(installQueue);
}
}
//end add
4、桌面模式不允许移除桌面图标:
DeleteDropTarget.java
application类型的控件不允许拖动移除,小部件、快捷方式、文件夹等可以移除,这里可以根据需求添加或的判断。
protected boolean supportsDrop(ItemInfo info) {
//begin add
if(Launcher.isDeskMode && info.itemType == Favorites.ITEM_TYPE_APPLICATION){
return false;
}
//end add
return true;
}
我这里需求是可以移除文件夹,移除了之后,需要把文件夹里面app重新加载回桌面,并且桌面模式下移除了不需要撤销操作:
public void completeDrop(DragObject d) {
ItemInfo item = d.dragInfo;
if (canRemove(item)) {
//begin add
onAccessibilityDrop(null, item);