目前接收到一个需求,因为是小屏手机,需要修改为4宫格模式,去掉抽屉,将所有应用展示在一级页面。
1、加入开关
Launcher3\src\com\android\launcher3\LauncherAppState.java
添加一个方法
public static boolean isDisableAllApps() {
return true;
}
2、allapp键的加载
在hotseat里面去掉allapp键的加载 ,屏蔽isallappsbuttonrank()占用allapp位置。
1)不再占用allapp位置
2)在加载workspace时,会留出hotseat的第三个位置给allapp按钮,若不取消该位置的占用,在hotseat加载时会留出空位。
hotseat的初始化在Launcher3\src\com\android\launcher3\InvariantDeviceProfile.java中的
isAllAppsButtonRank()中。在6.0中,这个方法是在HotSeat.java中
public boolean isAllAppsButtonRank(int rank) {
if (LauncherAppState.isDisableAllApps()) {
return false;
}
return rank == getAllAppsButtonRank();
}
3)在HoSeat里面去掉AllApp键的布局加载
Launcher3\src\com\android\launcher3\HotSeat.java –>resetLayout():
void resetLayout() {
mContent.removeAllViewsInLayout();
//添加判断
if (LauncherAppState.isDisableAllApps()) {
return;
}
if (!FeatureFlags.NO_ALL_APPS_ICON) {
// Add the Apps button
Context context = getContext();
DeviceProfile grid = mLauncher.getDeviceProfile();
int allAppsButtonRank = grid.inv.getAllAppsButtonRank();
......
}
4)将所有应用放到第一层
Launcher3\src\com\android\launcher3\model\LoaderTask.java ->run()
// second step
if (DEBUG_LOADERS) Log.d(TAG, "step 2.1: loading all apps");
loadAllApps();
/*launcher single-deck start*/
//添加查找APP
if (LauncherAppState.isDisableAllApps()) {
loadAllApplications();
}
/*launcher single-deck end*/
在这个地方调用loadAllApplications是因为,只有当应用数据加载完全后,我们才能将所有应用绑定到第一层中。
新增loadAllApplications方法
private void loadAllApplications() {
final Context context = mApp.getContext();
final List<UserHandle> profiles = mUserManager.getUserProfiles();
Log.d("wangjin","LoaderTask loadAllApplications");
for (UserHandle user : profiles) {
final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null, user);
Log.d("wangjin","LoaderTask");
ArrayList<InstallShortcutReceiver.PendingInstallShortcutInfo> added = new ArrayList<InstallShortcutReceiver.PendingInstallShortcutInfo>();
synchronized (this) {
for (LauncherActivityInfo app : apps) {
InstallShortcutReceiver.PendingInstallShortcutInfo pendingInstallShortcutInfo = new InstallShortcutReceiver.PendingInstallShortcutInfo(app,context);
added.add(pendingInstallShortcutInfo);
Log.d("wangjin"," LoaderTask app ===== " + app);
}
}
if (!added.isEmpty()) {
Log.d("wangjin","LoaderTask added = " + added);
mApp.getModel().addAndBindAddedWorkspaceItems(new InstallShortcutReceiver.LazyShortcutsProvider(context.getApplicationContext(), added));
}
}
}
上面的代码考虑到多用户,拿到应用数据后,使用addAndBindAddedWorkspaceItems添加item。同时需要注意,需要将需要把InstallShortcutReceiver.PendingInstallShortcutInfo和InstallShortcutReceiver.LazyShortcutsProvider改为public。
按照上述修改后,仍然没有达到效果,发现AddWorkspaceItemsTask.java中的execute()方法没有执行,原因是BaseModelUpdateTask.java中run()中的判断问题,导致没有执行。
Launcher3/src/com/android/launcher3/model/BaseModelUpdateTask.java ->run中将return注释掉
public final void run() {
if (!mModel.isModelLoaded()) {
if (DEBUG_TASKS) {
Log.d(TAG, "Ignoring model task since loader is pending=" + this);
}
// Loader has not yet run.
//return;
}
execute(mApp, mDataModel, mAllAppsList);
}
3、有app变化时更新workspace
Launcher3/com/android/launcher3/model/PackageUpdatedTask.java -> execute():
addedOrModified.addAll(appsList.added);
final List<UserHandle> profiles = UserManagerCompat.getInstance(context).getUserProfiles();
ArrayList<InstallShortcutReceiver.PendingInstallShortcutInfo> added = new ArrayList<InstallShortcutReceiver.PendingInstallShortcutInfo>();
for (UserHandle user : profiles) {
final List<LauncherActivityInfo> apps = LauncherAppsCompat.getInstance(context).getActivityList(null, user);
synchronized (this) {
for (LauncherActivityInfo info : apps) {
for (AppInfo appInfo : appsList.added) {
if(info.getComponentName().equals(appInfo.componentName)){
InstallShortcutReceiver.PendingInstallShortcutInfo mPendingInstallShortcutInfo = new InstallShortcutReceiver.PendingInstallShortcutInfo(info,context);
added.add(mPendingInstallShortcutInfo);
}
}
}
}
}
if (!added.isEmpty()) {
Log.d("wangjin","PackageUpdatedTask.java ------------------------");
app.getModel().addAndBindAddedWorkspaceItems(new InstallShortcutReceiver.LazyShortcutsProvider(context.getApplicationContext(), added));
}
appsList.added.clear();
这里添加的代码和LoaderTask.java中一样,重新加载app数据。
4、隐藏allapp
1)将展示allapp的地方注释
src/com/android/launcher3/Launcher.java -> showAppsView():
public void showAppsView(boolean animated, boolean updatePredictedApps) {
/*<begin delect by wangjin in 2019/11/13
markAppsViewShown();
if (updatePredictedApps) {
tryAndUpdatePredictedApps();
}
showAppsOrWidgets(State.APPS, animated);
delect by wangjin in 2019/11/13 end>*/
}
2)去掉上滑唤出抽屉手势
src/com/android/launcher3/allapps/AllAppsTransitionController.java -> onDrag():
@Override
public boolean onDrag(float displacement, float velocity) {
if (mAppsView == null) {
return false; // early termination.
}
mContainerVelocity = velocity;
float shift = Math.min(Math.max(0, mShiftStart + displacement), mShiftRange);
//把调用的地方注释掉 begin
//setProgress(shift / mShiftRange);
//把调用的地方注释掉 end
return true;
}
3)移除Launcher向上跳动动画
在HotSeat上面一点,有一个向上的箭头,在Launcher的onResume状态时,HotSeat和箭头会一起做一个向上跳动的动画。
动画效果是用BounceInterpolator,在AllAppsTransitionController.java这个类中有showDiscoveryBounce()这个方法
查看调用的地方,是在
src/com/android/launcher3/Launcher.java -> onResume():
将调用的地方注释:
if (shouldShowDiscoveryBounce()) {
//mAllAppsController.showDiscoveryBounce();
}
4)去掉箭头
src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java -> onFinishInflate()
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mAllAppsHandle = (ImageView) findViewById(R.id.all_apps_handle);
//修改 begin
// mAllAppsHandle.setImageDrawable(getCaretDrawable());
mAllAppsHandle.setImageDrawable(null);
//修改 end
mAllAppsHandle.setOnClickListener(mLauncher);
mAllAppsHandle.setOnFocusChangeListener(mLauncher.mFocusHandler);
mLauncher.setAllAppsButton(mAllAppsHandle);
}
5、将长按移除修改为删除
此时所有应用都已经在workspcae中,allapp也已经隐藏,但是长按图标出现的是移除而不是卸载
Launcher3/src/com/android/launcher3/DeleteDropTarget.java
@Override
protected boolean supportsDrop(DragSource source, ItemInfo info) {
//添加判断 begin
if (info instanceof ShortcutInfo || info instanceof FolderInfo) {
return false;
}
//添加判断 end
return true;
}
src/com/android/launcher3/popup/PopupContainerWithArrow.java -> showForIcon():
public static PopupContainerWithArrow showForIcon(BubbleTextView icon) {
Launcher launcher = Launcher.getLauncher(icon.getContext());
if (getOpen(launcher) != null) {
// There is already an items container open, so don't open this one.
icon.clearFocus();
return null;
}
ItemInfo itemInfo = (ItemInfo) icon.getTag();
//修改类型 begin
itemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
//修改类型 end
if (!DeepShortcutManager.supportsShortcuts(itemInfo)) {
return null;
}
......
}
参考资料: