android 9.0 launcher3 去掉抽屉式显示所有 app(代码详解)

前端之家收集整理的这篇文章主要介绍了android 9.0 launcher3 去掉抽屉式显示所有 app(代码详解)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

效果

android 9.0 launcher3 去掉抽屉式显示所有 app(代码详解)


修改思路

1、增加全局控制变量 sys.launcher3.is_full_app,用来动态切换

2、增加两套布局,对应有抽屉和无抽屉

3、去除 allAppsButton

4、将 AllAppsContainerView 中的图标加载到 Workspace

5、新安装的 app 自动添加图标到 Workspace

6、替换 Workspace 图标长按删除选项为取消

7、屏蔽上拉显示抽屉页面手势

8、修改页面指示线为圆点

代码

1、增加全局控制变量 sys.launcher3.is_full_app

1) 在 LauncherAppState 中增加静态方法 isDisableAllApps(),通过修改 Settings 中自定义的值 sys.launcher3.is_full_app

vendor\mediatek\proprietary\packages\apps\Launcher3\src\com\android\launcher3\LauncherAppState.java

  1. private static Context mContext;
  2.  
  3. public static boolean isDisableAllApps() {
  4. if (mContext != null) {
  5. return Settings.System.getInt(mContext.getContentResolver(),"sys.launcher3.is_full_app",0) == 1;
  6. }
  7. return true;
  8. }

vendor\mediatek\proprietary\packages\apps\Launcher3\AndroidManifest-common.xml

2) AndroidManifest-common.xml 中增加权限

  1. <uses-permission android:name="android.permission.WRITE_SETTINGS" />

3) 在 SettingsActivity 中增加 SwitchPreference 用以动态修改 sys.launcher3.is_full_app

vendor\mediatek\proprietary\packages\apps\Launcher3\src\com\android\launcher3\SettingsActivity.java

在内部类 LauncherSettingsFragment 中重写 onPreferenceTreeClick() 用以监听 SwitchPreference 点击

  1. /**
  2. * This fragment shows the launcher preferences.
  3. */
  4. public static class LauncherSettingsFragment extends PreferenceFragment {
  5. .....
  6. @Override
  7. public void onCreate(Bundle savedInstanceState) {
  8. super.onCreate(savedInstanceState);
  9. ....
  10. //读取保存的值,初始化 SwitchPreference 的初始状态,是否选中
  11. int isFull = Settings.System.getInt(getActivity().getContentResolver(),0);
  12. Log.d("Launcher3","sys.launcher3.is_full_app="+isFull);
  13. SwitchPreference fullSwitch = (SwitchPreference) findPreference("pref_is_full_app");
  14. fullSwitch.setChecked(isFull==1);
  15. }
  16. //add for change is_full_app value
  17. @Override
  18. public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,Preference preference) {
  19. boolean result = true;
  20. final String key = preference.getKey();
  21. if ("pref_is_full_app".equals(key)) {
  22. boolean checked = ((SwitchPreference) preference).isChecked();
  23. Settings.System.putInt(getActivity().getContentResolver(),checked ? 1 : 0);
  24. Log.e("Launcher3","SwitchPreference checked="+checked);
  25. // Value has changed
  26. ProgressDialog.show(getActivity(),null /* title */,getActivity().getString(R.string.full_app_override_progress),true /* indeterminate */,false /* cancelable */);
  27. new LooperExecutor(LauncherModel.getWorkerLooper()).execute(
  28. new OverrideApplyHandler(getActivity()));
  29. }
  30. return result;
  31. }
  32. }

点击 SwitchPreference 后需要保存 sys.launcher3.is_full_app 新值,同时清除 Launcher3 的缓存,延时启动并结束当前进程

清除缓存方法 clearApplicationUserData 在 Launcher3 中编译报错,所以通过发送广播到 Setting 中进行真正的清缓存操作

  1. //add for change is_full_app value
  2. private static class OverrideApplyHandler implements Runnable {
  3. private final Context mContext;
  4. private OverrideApplyHandler(Context context) {
  5. mContext = context;
  6. }
  7. @Override
  8. public void run() {
  9. // Clear the icon cache.
  10. LauncherAppState.getInstance(mContext).getIconCache().clear();
  11. // Wait for it
  12. try {
  13. Thread.sleep(1000);
  14. } catch (Exception e) {
  15. Log.e("Launcher3","Error waiting",e);
  16. }
  17. // Schedule an alarm before we kill ourself.
  18. Intent homeIntent = new Intent(Intent.ACTION_MAIN)
  19. .addCategory(Intent.CATEGORY_HOME)
  20. .setPackage(mContext.getPackageName())
  21. .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  22. PendingIntent pi = PendingIntent.getActivity(mContext,42,homeIntent,PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
  23. mContext.getSystemService(AlarmManager.class).setExact(
  24. AlarmManager.ELAPSED_REALTIME,SystemClock.elapsedRealtime() + 50,pi);
  25. //clear data will kill process
  26. Intent intent = new Intent("com.android.action.CLEAR_APP_DATA");
  27. intent.putExtra("pkgName","com.android.launcher3");
  28. intent.addFlags(0x01000000);
  29. mContext.sendBroadcast(intent);
  30. Log.i("Launcher3","Clearing user data com.android.launcher3");
  31. // Kill process
  32. android.os.Process.killProcess(android.os.Process.myPid());
  33. }
  34. }

4) SettingsActivity 对应的 xml 文件修改 launcher_preferences

vendor\mediatek\proprietary\packages\apps\Launcher3\res\xml\launcher_preferences.xml

  1. <SwitchPreference
  2. android:key="pref_is_full_app"
  3. android:title="@string/is_full_app_title"
  4. android:summary="@string/is_full_app_desc"
  5. android:defaultValue="false"
  6. android:persistent="true" />

对应的 string 文件就不贴了,自己增加下就行

2、增加两套布局,对应有抽屉和无抽屉

加载布局文件对应的 xml 为 vendor\mediatek\proprietary\packages\apps\Launcher3\res\xml\device_profiles.xml

Launcher3 通过获取 minWidthDps 和 minHeightDps 来确定加载哪一个 profile,我的平板分辨率是 1280*800 的,增加两个 profile 节点

  1. <profile
  2. launcher:name="Tablet"
  3. launcher:minWidthDps="376"
  4. launcher:minHeightDps="586"
  5. launcher:numRows="4"
  6. launcher:numColumns="5"
  7. launcher:numFolderRows="4"
  8. launcher:numFolderColumns="5"
  9. launcher:iconSize="50"
  10. launcher:iconTextSize="11"
  11. launcher:numHotseatIcons="5"
  12. launcher:defaultLayoutId="@xml/default_workspace_tb_5x6"
  13. />
  14. <profile
  15. launcher:name="Tablet_no_all_app"
  16. launcher:minWidthDps="380"
  17. launcher:minHeightDps="590"
  18. launcher:numRows="4"
  19. launcher:numColumns="5"
  20. launcher:numFolderRows="4"
  21. launcher:numFolderColumns="5"
  22. launcher:iconSize="50"
  23. launcher:iconTextSize="11"
  24. launcher:numHotseatIcons="4"
  25. launcher:defaultLayoutId="@xml/default_workspace_tb_5x6_no_all_app"
  26. />

对应的你需要在 xml 文件增加 4 个文件,分别是 default_workspace_tb_5x6.xml dw_hotseat_tb.xml default_workspace_tb_5x6_no_all_app.xml dw_hotseat_tb_no_all_app.xml

这样的好处是你可以自定义不同的布局文件加载内容,上面的配置含义简单说一下,分别是最小宽度、最小高度、布局的行和列、文件夹中布局行和列、图标大小、图标文字大小、HotSeat 个数,加载的布局文件

在 InvariantDeviceProfile() 判断是否需要加载 Tablet_no_all_app profile

vendor\mediatek\proprietary\packages\apps\Launcher3\src\com\android\launcher3\InvariantDeviceProfile.java

  1. public InvariantDeviceProfile(Context context) {
  2. WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
  3. Display display = wm.getDefaultDisplay();
  4. DisplayMetrics dm = new DisplayMetrics();
  5. display.getMetrics(dm);
  6. Point smallestSize = new Point();
  7. Point largestSize = new Point();
  8. display.getCurrentSizeRange(smallestSize,largestSize);
  9. // This guarantees that width < height
  10. minWidthDps = Utilities.dpiFromPx(Math.min(smallestSize.x,smallestSize.y),dm);
  11. minHeightDps = Utilities.dpiFromPx(Math.min(largestSize.x,largestSize.y),dm);
  12. Log.i("Launcher3.profiles","orignalminWidthDps="+minWidthDps + " orignalminHeightDps="+minHeightDps);
  13.  
  14. //add for load no_all_app xml
  15. if (LauncherAppState.isDisableAllApps()) {
  16. Log.e("Launcher3.profiles","load no all app profiles");
  17. //对应 device_profiles.xml 中 Tablet_no_all_app 的值
  18. minWidthDps = 380.0f;
  19. minHeightDps = 590.0f;
  20. }
  21. .....
  22. }

3、去除 allAppsButton

vendor\mediatek\proprietary\packages\apps\Launcher3\src\com\android\launcher3\Hotseat.java

将 resetLayout() 中 FeatureFlags.NO_ALL_APPS_ICON 替换为 LauncherAppState.isDisableAllApps()

  1. void resetLayout(boolean hasVerticalHotseat) {
  2. mContent.removeAllViewsInLayout();
  3. mHasVerticalHotseat = hasVerticalHotseat;
  4. InvariantDeviceProfile idp = mLauncher.getDeviceProfile().inv;
  5. if (hasVerticalHotseat) {
  6. mContent.setGridSize(1,idp.numHotseatIcons);
  7. } else {
  8. mContent.setGridSize(idp.numHotseatIcons,1);
  9. }
  10.  
  11. //if (!FeatureFlags.NO_ALL_APPS_ICON) {
  12. /// add for check is need allappbutton
  13. if (!LauncherAppState.isDisableAllApps()) {
  14. // Add the Apps button
  15. Context context = getContext();
  16. DeviceProfile grid = mLauncher.getDeviceProfile();
  17.  
  18. ...
  19. }

4、将 AllAppsContainerView 中的图标加载到 Workspace

vendor\mediatek\proprietary\packages\apps\Launcher3\src\com\android\launcher3\model\LoaderTask.java

run() 中增加判断,添加 verifyApplications(),修改 InstallShortcutReceiver 中 PendingInstallShortcutInfo 为 public

  1. public void run() {
  2. synchronized (this) {
  3. // Skip fast if we are already stopped.
  4. if (mStopped) {
  5. return;
  6. }
  7. }
  8. ....
  9. // second step
  10. TraceHelper.partitionSection(TAG,"step 2.1: loading all apps");
  11. loadAllApps();
  12. //add for load all app on workspace
  13. if (LauncherAppState.isDisableAllApps()) {
  14. android.util.Log.e("Launcher3","verifyApplications()");
  15. verifyApplications();
  16. }
  17. ....
  18. }
  19. //add for load all app on workspace
  20. private void verifyApplications() {
  21. final Context context = mApp.getContext();
  22. ArrayList<Pair<ItemInfo,Object>> installQueue = new ArrayList<>();
  23. final List<UserHandle> profiles = mUserManager.getUserProfiles();
  24. for (UserHandle user : profiles) {
  25. final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null,user);
  26. ArrayList<InstallShortcutReceiver.PendingInstallShortcutInfo> added = new ArrayList<InstallShortcutReceiver.PendingInstallShortcutInfo>();
  27. synchronized (this) {
  28. for (LauncherActivityInfo app : apps) {
  29. InstallShortcutReceiver.PendingInstallShortcutInfo pendingInstallShortcutInfo = new InstallShortcutReceiver.PendingInstallShortcutInfo(app,context);
  30. added.add(pendingInstallShortcutInfo);
  31. installQueue.add(pendingInstallShortcutInfo.getItemInfo());
  32. }
  33. }
  34. if (!added.isEmpty()) {
  35. mApp.getModel().addAndBindAddedWorkspaceItems(installQueue);
  36. }
  37. }
  38. }

vendor\mediatek\proprietary\packages\apps\Launcher3\src\com\android\launcher3\model\BaseModelUpdateTask.java

注释 run() 中的 return

  1. @Override
  2. public final void run() {
  3. if (!mModel.isModelLoaded()) {
  4. if (DEBUG_TASKS) {
  5. Log.d(TAG,"Ignoring model task since loader is pending=" + this);
  6. }
  7. // Loader has not yet run.
  8. //annotaion for load all app on workspace
  9. // return;
  10. }
  11. execute(mApp,mDataModel,mAllAppsList);
  12. }

5、新安装的 app 自动添加图标到 Workspace

vendor\mediatek\proprietary\packages\apps\Launcher3\src\com\android\launcher3\model\PackageUpdatedTask.java

execute() 中增加判断,添加 updateToWorkSpace()

  1. public void execute(LauncherAppState app,BgDataModel dataModel,AllAppsList appsList) {
  2. ....
  3. final ArrayList<AppInfo> addedOrModified = new ArrayList<>();
  4. addedOrModified.addAll(appsList.added);
  5. //add for load new install app on workspace
  6. if (LauncherAppState.isDisableAllApps()) {
  7. android.util.Log.e("cczLauncher3","updateToWorkSpace()");
  8. updateToWorkSpace(context,app,appsList);
  9. }
  10. ...
  11. }
  12. //add for load new install app on workspace
  13. public void updateToWorkSpace(Context context,LauncherAppState app,AllAppsList appsList){
  14. ArrayList<Pair<ItemInfo,Object>> installQueue = new ArrayList<>();
  15. final List<UserHandle> profiles = UserManagerCompat.getInstance(context).getUserProfiles();
  16. ArrayList<InstallShortcutReceiver.PendingInstallShortcutInfo> added
  17. = new ArrayList<InstallShortcutReceiver.PendingInstallShortcutInfo>();
  18.  
  19. for (UserHandle user : profiles) {
  20. final List<LauncherActivityInfo> apps = LauncherAppsCompat.getInstance(context).getActivityList(null,user);
  21. synchronized (this) {
  22. for (LauncherActivityInfo info : apps) {
  23. for (AppInfo appInfo : appsList.added) {
  24. if(info.getComponentName().equals(appInfo.componentName)){
  25. InstallShortcutReceiver.PendingInstallShortcutInfo mPendingInstallShortcutInfo
  26. = new InstallShortcutReceiver.PendingInstallShortcutInfo(info,context);
  27. added.add(mPendingInstallShortcutInfo);
  28. installQueue.add(mPendingInstallShortcutInfo.getItemInfo());
  29. }
  30. }
  31. }
  32. }
  33. }
  34. if (!added.isEmpty()) {
  35. app.getModel().addAndBindAddedWorkspaceItems(installQueue);
  36. }
  37. }

6、替换 Workspace 图标长按删除选项为取消

vendor\mediatek\proprietary\packages\apps\Launcher3\src\com\android\launcher3\DeleteDropTarget.java

在 setTextBasedOnDragSource() 、setControlTypeBasedOnDragSource()、onAccessibilityDrop() 中分别增加判断是否需要删除图标

  1. private void setTextBasedOnDragSource(ItemInfo item) {
  2. if (!TextUtils.isEmpty(mText)) {
  3. mText = getResources().getString(item.id != ItemInfo.NO_ID
  4. ? R.string.remove_drop_target_label
  5. : android.R.string.cancel);
  6. //add for hide deletedroptarget
  7. if (LauncherAppState.isDisableAllApps()) {
  8. android.util.Log.e("Launcher3","hide delete drop target");
  9. mText = getResources().getString(isCanDrop(item)
  10. ? R.string.remove_drop_target_label
  11. : android.R.string.cancel);
  12. }
  13. requestLayout();
  14. }
  15. }
  16. private void setControlTypeBasedOnDragSource(ItemInfo item) {
  17. mControlType = item.id != ItemInfo.NO_ID ? ControlType.REMOVE_TARGET
  18. : ControlType.CANCEL_TARGET;
  19. //add for hide deletedroptarget [S]
  20. if (LauncherAppState.isDisableAllApps()) {
  21. mControlType = isCanDrop(item) ? ControlType.REMOVE_TARGET
  22. : ControlType.CANCEL_TARGET;
  23. }
  24. }
  25. public void onAccessibilityDrop(View view,ItemInfo item) {
  26. // Remove the item from launcher and the db,we can ignore the containerInfo in this call
  27. // because we already remove the drag view from the folder (if the drag originated from
  28. // a folder) in Folder.beginDrag()
  29. //add if juge is need remove item from workspace
  30. if (!LauncherAppState.isDisableAllApps() || isCanDrop(item)) {
  31. mLauncher.removeItem(view,item,true /* deleteFromDb */);
  32. mLauncher.getWorkspace().stripEmptyScreens();
  33. mLauncher.getDragLayer()
  34. .announceForAccessibility(getContext().getString(R.string.item_removed));
  35. }
  36. }
  37. private boolean isCanDrop(ItemInfo item){
  38. return !(item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
  39. item.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER);
  40. }

vendor\mediatek\proprietary\packages\apps\Launcher3\src\com\android\launcher3\dragndrop\DragController.java

drop() 中增加判断,取消当前拖拽操作

  1. private void drop(DropTarget dropTarget,Runnable flingAnimation) {
  2. ....
  3. boolean accepted = false;
  4. if (dropTarget != null) {
  5. dropTarget.onDragExit(mDragObject);
  6. if (dropTarget.acceptDrop(mDragObject)) {
  7. if (flingAnimation != null) {
  8. flingAnimation.run();
  9. } else {
  10. dropTarget.onDrop(mDragObject,mOptions);
  11. }
  12. accepted = true;
  13. //add for cancel canceldroptarget handle
  14. if (LauncherAppState.isDisableAllApps() && dropTarget instanceof DeleteDropTarget &&
  15. isNeedCancelDrag(mDragObject.dragInfo)) {
  16. cancelDrag();
  17. }
  18. }
  19. }
  20. ...
  21. }
  22. private boolean isNeedCancelDrag(ItemInfo item){
  23. return (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
  24. item.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER);
  25. }

7、屏蔽上拉显示抽屉页面手势

  1. vendor\mediatek\proprietary\packages\apps\Launcher3\quickstep\src\com\android\launcher3

\uioverrides\OverviewToAllAppsTouchController.java

  1. canInterceptTouch() 增加判断是否直接拦截
  2. @Override
  3. protected boolean canInterceptTouch(MotionEvent ev) {
  4. //add for forbidden workspace drag change GradientView alph
  5. if (LauncherAppState.isDisableAllApps()){
  6. android.util.Log.e("Launcher3","canInterceptTouch()");
  7. return false;
  8. }
  9. if (mCurrentAnimation != null) {
  10. // If we are already animating from a prevIoUs state,we can intercept.
  11. return true;
  12. }
  13. if (AbstractFloatingView.getTopOpenView(mLauncher) != null) {
  14. return false;
  15. }
  16. if (mLauncher.isInState(ALL_APPS)) {
  17. // In all-apps only listen if the container cannot scroll itself
  18. return mLauncher.getAppsView().shouldContainerScroll(ev);
  19. } else if (mLauncher.isInState(NORMAL)) {
  20. return true;
  21. } else if (mLauncher.isInState(OVERVIEW)) {
  22. RecentsView rv = mLauncher.getOverviewPanel();
  23. return ev.getY() > (rv.getBottom() - rv.getPaddingBottom());
  24. } else {
  25. return false;
  26. }
  27. }

8、修改页面指示线为圆点

vendor\mediatek\proprietary\packages\apps\Launcher3\res\layout\launcher.xml

WorkspacePageIndicator 改为 PageIndicatorDots

  1. <com.android.launcher3.pageindicators.PageIndicatorDots
  2. android:id="@+id/page_indicator"
  3. android:layout_width="match_parent"
  4. android:layout_height="4dp"
  5. android:layout_gravity="bottom|center_horizontal"
  6. android:theme="@style/HomeScreenElementTheme" />
  7. vendor\mediatek\proprietary\packages\apps\Launcher3\src\com\android\launcher3

\pageindicators\PageIndicatorDots.java

增加 PageIndicatorDots 继承 Insettable,复写setInsets(),调整圆点的位置

  1. public class PageIndicatorDots extends View implements PageIndicator,Insettable {
  2. // add for change WorkspacePageIndicator line to dot
  3. @Override
  4. public void setInsets(Rect insets) {
  5. DeviceProfile grid = mLauncher.getDeviceProfile();
  6. FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
  7. if (grid.isVerticalBarLayout()) {
  8. Rect padding = grid.workspacePadding;
  9. lp.leftMargin = padding.left + grid.workspaceCellPaddingXPx;
  10. lp.rightMargin = padding.right + grid.workspaceCellPaddingXPx;
  11. lp.bottomMargin = padding.bottom;
  12. } else {
  13. lp.leftMargin = lp.rightMargin = 0;
  14. lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
  15. lp.bottomMargin = grid.hotseatBarSizePx + insets.bottom;
  16. }
  17. setLayoutParams(lp);
  18. }
  19. @Override
  20. public void setScroll(int currentScroll,int totalScroll) {
  21. if (mNumPages > 1) {
  22. if (mIsRtl) {
  23. currentScroll = totalScroll - currentScroll;
  24. }
  25. int scrollPerPage = totalScroll / (mNumPages - 1);
  26. // add for change WorkspacePageIndicator line to dot
  27. if (scrollPerPage == 0) {
  28. return;
  29. }
  30. int pageToLeft = currentScroll / scrollPerPage;
  31. int pageToLeftScroll = pageToLeft * scrollPerPage;
  32. int pageToRightScroll = pageToLeftScroll + scrollPerPage;
  33. ...
  34. }

vendor\mediatek\proprietary\packages\apps\Launcher3\src\com\android\launcher3

\states\SpringLoadedState.java

注释 setShouldAutoHide(),避免长按 workSpace 时发生崩溃

  1. @Override
  2. public void onStateEnabled(Launcher launcher) {
  3. Workspace ws = launcher.getWorkspace();
  4. ws.showPageIndicatorAtCurrentScroll();
  5. //annotaion for WorkspacePageIndicator line to dot
  6. // ws.getPageIndicator().setShouldAutoHide(false);
  7. // Prevent any Un/InstallShortcutReceivers from updating the db while we are
  8. // in spring loaded mode
  9. InstallShortcutReceiver.enableInstallQueue(InstallShortcutReceiver.FLAG_DRAG_AND_DROP);
  10. launcher.getRotationHelper().setCurrentStateRequest(REQUEST_LOCK);
  11. }
  12. @Override
  13. public void onStateDisabled(final Launcher launcher) {
  14. //annotaion for WorkspacePageIndicator line to dot
  15. // launcher.getWorkspace().getPageIndicator().setShouldAutoHide(true);
  16. // Re-enable any Un/InstallShortcutReceiver and now process any queued items
  17. InstallShortcutReceiver.disableAndFlushInstallQueue(
  18. InstallShortcutReceiver.FLAG_DRAG_AND_DROP,launcher);
  19. }

总结

以上所述是小编给大家介绍的android 9.0 launcher3 去掉抽屉式显示所有 app代码详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

猜你在找的Android相关文章