Android 9.0 launcher3 removes the drawer display of all apps (detailed code)

design sketch

Modification ideas

1. Add the global control variable sys.launcher3.is_ full_ App for dynamic switching

2. Add two sets of layouts, corresponding to drawers and no drawers

3. Remove allappsbutton

4. Load the icon in allappscontainerview into workspace

5. Newly installed apps automatically add icons to workspace

6. Replace the workspace icon and long press the delete option to cancel

7. Mask pull-up display drawer page gesture

8. Change page indicator to dot

Upper code

1. Add the global control variable sys.launcher3.is_ full_ app

1) Add the static method isdisableallapps() in launcherappstate by modifying the custom value sys.launcher3.is in settings_ full_ app

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

 private static Context mContext;

public static boolean isDisableAllApps() {
  if (mContext != null) {
   return Settings.System.getInt(mContext.getContentResolver(),"sys.launcher3.is_full_app",0) == 1;
  }
  return true;
 }

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

2) Add permissions in androidmanifest-common.xml

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

3) Add switchpreference in settingsactivity to dynamically modify sys.launcher3.is_ full_ app

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

Override onpreferencetreelick() in the inner class launchersettingsfragment to listen for switchpreference clicks

/**
  * This fragment shows the launcher preferences.
  */
 public static class LauncherSettingsFragment extends PreferenceFragment {
 .....
 @Override
 public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
 ....
   //读取保存的值,初始化 SwitchPreference 的初始状态,是否选中
   int isFull = Settings.System.getInt(getActivity().getContentResolver(),0);
   Log.d("Launcher3","sys.launcher3.is_full_app="+isFull);
   SwitchPreference fullSwitch = (SwitchPreference) findPreference("pref_is_full_app");
   fullSwitch.setChecked(isFull==1);
  }
 //add for change is_full_app value
 @Override
 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,Preference preference) {
   boolean result = true;
   final String key = preference.getKey();
    if ("pref_is_full_app".equals(key)) {
    boolean checked = ((SwitchPreference) preference).isChecked();
    Settings.System.putInt(getActivity().getContentResolver(),checked ? 1 : 0);
    Log.e("Launcher3","SwitchPreference checked="+checked);
    // Value has changed
    ProgressDialog.show(getActivity(),null /* title */,getActivity().getString(R.string.full_app_override_progress),true /* indeterminate */,false /* cancelable */);
    new LooperExecutor(LauncherModel.getWorkerLooper()).execute(
      new OverrideApplyHandler(getActivity()));
   }
   return result;
  }
}

After clicking switch preference, you need to save sys.launcher3.is_ full_ App, clear the cache of launcher3, delay the start and end the current process

The clear cache method clearapplicationuserdata compiles and reports an error in launcher3, so the real clear cache operation is carried out by sending a broadcast to setting

 //add for change is_full_app value
 private static class OverrideApplyHandler implements Runnable {
  private final Context mContext;
  private OverrideApplyHandler(Context context) {
   mContext = context;
  }
  @Override
  public void run() {
   // Clear the icon cache.
   LauncherAppState.getInstance(mContext).getIconCache().clear();
   // Wait for it
   try {
    Thread.sleep(1000);
   } catch (Exception e) {
    Log.e("Launcher3","Error waiting",e);
   }
   // Schedule an alarm before we kill ourself.
   Intent homeIntent = new Intent(Intent.ACTION_MAIN)
     .addCategory(Intent.CATEGORY_HOME)
     .setPackage(mContext.getPackageName())
     .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   PendingIntent pi = PendingIntent.getActivity(mContext,42,homeIntent,PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
   mContext.getSystemService(AlarmManager.class).setExact(
     AlarmManager.ELAPSED_REALTIME,SystemClock.elapsedRealtime() + 50,pi);
   //clear data will kill process
   Intent intent = new Intent("com.android.action.CLEAR_APP_DATA");
   intent.putExtra("pkgName","com.android.launcher3");
   intent.addFlags(0x01000000);
   mContext.sendBroadcast(intent);
   Log.i("Launcher3","Clearing user data com.android.launcher3");
   // Kill process
   android.os.Process.killProcess(android.os.Process.myPid());
  }
 }

4) Modify the launcher from the XML file corresponding to settingsactivity_ preferences

vendor\mediatek\proprietary\packages\apps\Launcher3\res\xml\launcher_ preferences.xml

 <SwitchPreference
  android:key="pref_is_full_app"
  android:title="@string/is_full_app_title"
  android:summary="@string/is_full_app_desc"
  android:defaultValue="false"
  android:persistent="true" />

The corresponding string file will not be pasted. Just add it yourself

2. Add two sets of layouts, corresponding to drawers and no drawers

The XML corresponding to loading the layout file is vendor \ MediaTek \ proprietary \ packages \ apps \ launcher3 \ res \ XML \ device_ profiles.xml

Launcher3 determines which profile to load by obtaining minwidthdps and minhightdps. The resolution of my tablet is 1280 * 800, and two profile nodes are added

 <profile
  launcher:name="Tablet"
  launcher:minWidthDps="376"
  launcher:minHeightDps="586"
  launcher:numRows="4"
  launcher:numColumns="5"
  launcher:numFolderRows="4"
  launcher:numFolderColumns="5"
  launcher:iconSize="50"
  launcher:iconTextSize="11"
  launcher:numHotseatIcons="5"
  launcher:defaultLayoutId="@xml/default_workspace_tb_5x6"
  />
 <profile
  launcher:name="Tablet_no_all_app"
  launcher:minWidthDps="380"
  launcher:minHeightDps="590"
  launcher:numRows="4"
  launcher:numColumns="5"
  launcher:numFolderRows="4"
  launcher:numFolderColumns="5"
  launcher:iconSize="50"
  launcher:iconTextSize="11"
  launcher:numHotseatIcons="4"
  launcher:defaultLayoutId="@xml/default_workspace_tb_5x6_no_all_app"
  />

Correspondingly, you need to add four files under the XML file, which are default_ workspace_ tb_ 5x6.xml dw_ hotseat_ tb.xml default_ workspace_ tb_ 5x6_ no_ all_ app.xml dw_ hotseat_ tb_ no_ all_ app.xml

The advantage of this is that you can customize the loading contents of different layout files. The above configuration meanings are: minimum width, minimum height, layout rows and columns, layout rows and columns in folders, icon size, icon text size, number of hotseat, and loaded layout files

Judge whether the tablet needs to be loaded in the invariantdeviceprofile()_ no_ all_ app profile

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

public InvariantDeviceProfile(Context context) {
  WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
  Display display = wm.getDefaultDisplay();
  DisplayMetrics dm = new DisplayMetrics();
  display.getMetrics(dm);
  Point smallestSize = new Point();
  Point largestSize = new Point();
  display.getCurrentSizeRange(smallestSize,largestSize);
  // This guarantees that width < height
  minWidthDps = Utilities.dpiFromPx(Math.min(smallestSize.x,smallestSize.y),dm);
  minHeightDps = Utilities.dpiFromPx(Math.min(largestSize.x,largestSize.y),dm);
  Log.i("Launcher3.profiles","orignalminWidthDps="+minWidthDps + " orignalminHeightDps="+minHeightDps);

  //add for load no_all_app xml
  if (LauncherAppState.isDisableAllApps()) {
   Log.e("Launcher3.profiles","load no all app profiles");
   //对应 device_profiles.xml 中 Tablet_no_all_app 的值
   minWidthDps = 380.0f;
   minHeightDps = 590.0f;
  }
  .....
}

3. Remove allappsbutton

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

Set featureflags.no in resetlayout()_ ALL_ APPS_ Replace icon with launcherappstate. Isdisableallapps()

void resetLayout(boolean hasVerticalHotseat) {
  mContent.removeAllViewsInLayout();
  mHasVerticalHotseat = hasVerticalHotseat;
  InvariantDeviceProfile idp = mLauncher.getDeviceProfile().inv;
  if (hasVerticalHotseat) {
   mContent.setGridSize(1,idp.numHotseatIcons);
  } else {
   mContent.setGridSize(idp.numHotseatIcons,1);
  }

  //if (!FeatureFlags.NO_ALL_APPS_ICON) {
  /// add for check is need allappbutton
  if (!LauncherAppState.isDisableAllApps()) {
   // Add the Apps button
   Context context = getContext();
   DeviceProfile grid = mLauncher.getDeviceProfile();

  ...
}

4. Load the icon in allappscontainerview into workspace

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

Add judgment in run(), add verifyapplications(), and modify pendinginstallshortcutinfo in installshortcutreceiver to public

public void run() {
  synchronized (this) {
   // Skip fast if we are already stopped.
   if (mStopped) {
    return;
   }
  }
  ....
  // second step
  TraceHelper.partitionSection(TAG,"step 2.1: loading all apps");
  loadAllApps();
  //add for load all app on workspace
  if (LauncherAppState.isDisableAllApps()) {
   android.util.Log.e("Launcher3","verifyApplications()");
   verifyApplications();
  }
  ....
}
 //add for load all app on workspace
private void verifyApplications() {
  final Context context = mApp.getContext();
  ArrayList<Pair<ItemInfo,Object>> installQueue = new ArrayList<>();
  final List<UserHandle> profiles = mUserManager.getUserProfiles();
  for (UserHandle user : profiles) {
   final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null,user);
   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);
     installQueue.add(pendingInstallShortcutInfo.getItemInfo());
    }
   }
   if (!added.isEmpty()) {
    mApp.getModel().addAndBindAddedWorkspaceItems(installQueue);
   }
  }
 }

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

Comment on return in run()

@Override
 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.
   //annotaion for load all app on workspace
   // return;
  }
  execute(mApp,mDataModel,mAllAppsList);
 }

5. Newly installed apps automatically add icons to workspace

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

Add judgment in execute() and updatetoworkspace()

public void execute(LauncherAppState app,BgDataModel dataModel,AllAppsList appsList) {
 ....
  final ArrayList<AppInfo> addedOrModified = new ArrayList<>();
 addedOrModified.addAll(appsList.added);
 //add for load new install app on workspace
 if (LauncherAppState.isDisableAllApps()) {
  android.util.Log.e("cczLauncher3","updateToWorkSpace()");
  updateToWorkSpace(context,app,appsList);
 }
 ...
}
//add for load new install app on workspace
public void updateToWorkSpace(Context context,LauncherAppState app,AllAppsList appsList){
   ArrayList<Pair<ItemInfo,Object>> installQueue = new ArrayList<>();
  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);
       installQueue.add(mPendingInstallShortcutInfo.getItemInfo());
      }
     }
    }
   }
  }
  if (!added.isEmpty()) {
   app.getModel().addAndBindAddedWorkspaceItems(installQueue);
  }
 }

6. Replace the workspace icon and long press the delete option to cancel

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

Add icons to settextbasedondragsource(), setcontroltypebasedondragsource(), onaccessibilitydrop(), respectively, to determine whether to delete icons

private void setTextBasedOnDragSource(ItemInfo item) {
  if (!TextUtils.isEmpty(mText)) {
   mText = getResources().getString(item.id != ItemInfo.NO_ID
     ? R.string.remove_drop_target_label
     : android.R.string.cancel);
   //add for hide deletedroptarget
   if (LauncherAppState.isDisableAllApps()) {
    android.util.Log.e("Launcher3","hide delete drop target");
    mText = getResources().getString(isCanDrop(item)
       ? R.string.remove_drop_target_label
       : android.R.string.cancel);
   }
   requestLayout();
  }
 }
 private void setControlTypeBasedOnDragSource(ItemInfo item) {
  mControlType = item.id != ItemInfo.NO_ID ? ControlType.REMOVE_TARGET
    : ControlType.CANCEL_TARGET;
  //add for hide deletedroptarget [S]
  if (LauncherAppState.isDisableAllApps()) {
   mControlType = isCanDrop(item) ? ControlType.REMOVE_TARGET
    : ControlType.CANCEL_TARGET;
  }
 }
public void onAccessibilityDrop(View view,ItemInfo item) {
  // Remove the item from launcher and the db,we can ignore the containerInfo in this call
  // because we already remove the drag view from the folder (if the drag originated from
  // a folder) in Folder.beginDrag()
  //add if juge is need remove item from workspace
  if (!LauncherAppState.isDisableAllApps() || isCanDrop(item)) {
   mLauncher.removeItem(view,item,true /* deleteFromDb */);
   mLauncher.getWorkspace().stripEmptyScreens();
   mLauncher.getDragLayer()
     .announceForAccessibility(getContext().getString(R.string.item_removed));
  }
}
private boolean isCanDrop(ItemInfo item){
  return !(item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
    item.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER);
}

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

Add judgment in drop() to cancel the current drag operation

private void drop(DropTarget dropTarget,Runnable flingAnimation) {
 ....
 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;
    //add for cancel canceldroptarget handle
    if (LauncherAppState.isDisableAllApps() && dropTarget instanceof DeleteDropTarget &&
      isNeedCancelDrag(mDragObject.dragInfo)) {
     cancelDrag();
    }
   }
  }
  ...
}
private boolean isNeedCancelDrag(ItemInfo item){
  return (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
    item.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER);
 }

7. Mask pull-up display drawer page gesture

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

\uioverrides\OverviewToAllAppsTouchController.java

canInterceptTouch() 中增加判断是否直接拦截
@Override
 protected boolean canInterceptTouch(MotionEvent ev) {
  //add for forbidden workspace drag change GradientView alph
  if (LauncherAppState.isDisableAllApps()){
   android.util.Log.e("Launcher3","canInterceptTouch()");
   return false;
  }
  if (mCurrentAnimation != null) {
   // If we are already animating from a prevIoUs state,we can intercept.
   return true;
  }
  if (AbstractFloatingView.getTopOpenView(mLauncher) != null) {
   return false;
  }
  if (mLauncher.isInState(ALL_APPS)) {
   // In all-apps only listen if the container cannot scroll itself
   return mLauncher.getAppsView().shouldContainerScroll(ev);
  } else if (mLauncher.isInState(NORMAL)) {
   return true;
  } else if (mLauncher.isInState(OVERVIEW)) {
   RecentsView rv = mLauncher.getOverviewPanel();
   return ev.getY() > (rv.getBottom() - rv.getPaddingBottom());
  } else {
   return false;
  }
 }

8. Change page indicator to dot

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

Change workspacepageindicator to pageindicatordots

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

\pageindicators\PageIndicatorDots.java

Add pageindicatordots, inherit insettable, duplicate setinsets(), and adjust the position of dots

public class PageIndicatorDots extends View implements PageIndicator,Insettable {
// add for change WorkspacePageIndicator line to dot
 @Override
 public void setInsets(Rect insets) {
  DeviceProfile grid = mLauncher.getDeviceProfile();
  FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
  if (grid.isVerticalBarLayout()) {
   Rect padding = grid.workspacePadding;
   lp.leftMargin = padding.left + grid.workspaceCellPaddingXPx;
   lp.rightMargin = padding.right + grid.workspaceCellPaddingXPx;
   lp.bottomMargin = padding.bottom;
  } else {
   lp.leftMargin = lp.rightMargin = 0;
   lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
   lp.bottomMargin = grid.hotseatBarSizePx + insets.bottom;
  }
  setLayoutParams(lp);
 }
 @Override
 public void setScroll(int currentScroll,int totalScroll) {
  if (mNumPages > 1) {
   if (mIsRtl) {
    currentScroll = totalScroll - currentScroll;
   }
   int scrollPerPage = totalScroll / (mNumPages - 1);
   // add for change WorkspacePageIndicator line to dot
   if (scrollPerPage == 0) {
    return;
   }
   int pageToLeft = currentScroll / scrollPerPage;
   int pageToLeftScroll = pageToLeft * scrollPerPage;
   int pageToRightScroll = pageToLeftScroll + scrollPerPage;
  ...
}

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

\states\SpringLoadedState.java

Note setshouldautohide(), to avoid crash when pressing workspace for a long time

@Override
 public void onStateEnabled(Launcher launcher) {
  Workspace ws = launcher.getWorkspace();
  ws.showPageIndicatorAtCurrentScroll();
  //annotaion for WorkspacePageIndicator line to dot
  // ws.getPageIndicator().setShouldAutoHide(false);
  // Prevent any Un/InstallShortcutReceivers from updating the db while we are
  // in spring loaded mode
  InstallShortcutReceiver.enableInstallQueue(InstallShortcutReceiver.FLAG_DRAG_AND_DROP);
  launcher.getRotationHelper().setCurrentStateRequest(REQUEST_LOCK);
 }
 @Override
 public void onStateDisabled(final Launcher launcher) {
  //annotaion for WorkspacePageIndicator line to dot
  // launcher.getWorkspace().getPageIndicator().setShouldAutoHide(true);
  // Re-enable any Un/InstallShortcutReceiver and Now process any queued items
  InstallShortcutReceiver.disableAndFlushInstallQueue(
    InstallShortcutReceiver.FLAG_DRAG_AND_DROP,launcher);
 }

summary

The above is what Xiaobian introduced to you. Android 9.0 launcher 3 removes the drawer display and explains all app codes in detail. I hope it will be helpful to you. If you have any questions, please leave me a message and Xiaobian will reply to you in time. Thank you very much for your support to our website! If you think this article is helpful to you, welcome to reprint, please indicate the source, thank you!

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>