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

 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) AndroidManifest-common.xml 中增加权限

<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 点击

/**
  * 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(),
    "sys.launcher3.is_full_app", 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(), "sys.launcher3.is_full_app",
      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;
  }
}

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

清除缓存方法 clearApplicationUserData 在 Launcher3 中编译报错,所以通过发送广播到 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) SettingsActivity 对应的 xml 文件修改 launcher_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" />

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

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

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

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

 <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"
  />

对应的你需要在 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

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、去除 allAppsButton

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

将 resetLayout() 中 FeatureFlags.NO_ALL_APPS_ICON 替换为 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、将 AllAppsContainerView 中的图标加载到 Workspace

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

run() 中增加判断,添加 verifyApplications(), 修改 InstallShortcutReceiver 中 PendingInstallShortcutInfo 为 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

注释 run() 中的 return

@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、新安装的 app 自动添加图标到 Workspace

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

execute() 中增加判断,添加 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、替换 Workspace 图标长按删除选项为取消

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

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

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

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

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、屏蔽上拉显示抽屉页面手势

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、修改页面指示线为圆点

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

WorkspacePageIndicator 改为 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

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

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

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

@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);
 }

总结

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

(0)

相关推荐

  • Android开发实现Launcher3应用列表修改透明背景的方法

    本文实例讲述了Android开发实现Launcher3应用列表修改透明背景的方法.分享给大家供大家参考,具体如下: Launcher时开机完成后第一个启动的应用,用来展示应用列表和快捷方式.小部件等.Launcher作为第一个(开机后第一个启动的应用)展示给用户的应用程序,其设计的好坏影响到用户的体验,甚至影响用户购机的判断.所以很多品牌厂商都会不遗余力的对Launcher进行深度定制,如小米的MIUI.华为的EMUI等.Android默认的Launcher没有过多的定制,更加简洁,受到源生党的

  • Android6.0 Launcher2应用解析

    在之前我们分析了Android6.0系统在启动时安装应用程序的过程,这些应用程序安装好之后,Launcher应用就负责把它们在桌面上展示出来. 一.AMS启动Launcher Launcher应用是在AMS的systemReady方法中直接调用startHomeActivityLocked启动的,下面是systemReady启动Launcher的代码. startHomeActivityLocked(mCurrentUserId, "systemReady");我们来看下这个函数,先调

  • Android的Launcher启动器中添加快捷方式及小部件实例

    前言: 最近一直在看Launcher模块,经过差不多两个月学习,终于摸透了Launcher的一些主要功能实现,目前继续还处于 摸索状态.未看Launcher时,于我而言,只能膜拜,以为所有功能都是它实现的 :入门后,才发现,Launcher的很多功能只是 集成了框架/应用程序提供的功能.很多陌生的东西,只有接触了才感叹:"oh ,原来是这样的!" 添加快捷方式 今天先给大家分享下Launcher如何实现添加快捷方式(Shortcut) ,后续会慢慢增加其他方面的功能,帮助大家"

  • Android开发中Launcher3常见默认配置修改方法总结

    本文实例讲述了Android开发中Launcher3常见默认配置修改方法.分享给大家供大家参考,具体如下: Launcher概述 Launcher是开机完成后第一个启动的应用,用来展示应用列表和快捷方式.小部件等.Launcher作为第一个(开机后第一个启动的应用)展示给用户的应用程序,其设计的好坏影响到用户的体验,甚至影响用户购机的判断.所以很多品牌厂商都会不遗余力的对Launcher进行深度定制,如小米的MIUI.华为的EMUI等.Android默认的Launcher没有过多的定制,更加简洁

  • Android实现向Launcher添加快捷方式的方法

    本文实例讲述了Android实现向Launcher添加快捷方式的方法.分享给大家供大家参考.具体如下: 当我们在应用程序Launcher的桌面空白处长按触摸时,会出现一个对话框,提示选择要添加的桌面组件,如下图所示 选择快捷方式后,会弹出一个对话框,显示出了可添加快捷方式的Activity所属的应用程序的图标和名称的列表.当我们想把添加快捷方式的Activity添加到这一列表时,只需要在这个Activity注册时添加一个Action为android.intent.action.CREATE_SH

  • Android7.0开发实现Launcher3去掉应用抽屉的方法详解

    本文实例讲述了Android7.0开发实现Launcher3去掉应用抽屉的方法.分享给大家供大家参考,具体如下: 年初做过一个项目,有一个需求就是需要将桌面变为单层不需要二级菜单.最近几次有小伙伴有这个问我这个解决办法.现在我将分享给大家. 先上效果图:   功能分解 1. 去除Allapp键,调整HotSeat布局 2. 将所有应用摆在launcher第一层 3. 去掉长按时删除选项 解决方案 一.设置总开关 按照6.0 Launcher3 的模式,添加一个开关,控制是否去掉抽屉. Launc

  • 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_

  • Android 5.0以上Toast不显示的解决方法

    原因分析 用户使用android 5.0以上的系统在安装APP时,将消息通知的权限关闭掉了.实际上用户本意只是想关闭Notification,但是Toast的show方法中有调用INotificationManager这个类,而这个类在用户关闭消息通知权限的同时被禁用了,所以我们的吐司无法显示. Toast.show() 效果图 自定义Toast(上)与Toast(下)比对 问题解决 既然系统不允许我们调用Toast,那么我们就自立门户--自己写一个Toast出来.我们总体的思路是:在Activ

  • Android自定义多节点进度条显示的实现代码(附源码)

    亲们里面的线段颜色和节点图标都是可以自定义的. 在没给大家分享实例代码之前,先给大家展示下效果图: main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rl_parent" xmlns:tools="http://schemas.android.com/tools" android:layou

  • Android屏蔽软键盘并且显示光标的实例详解

    Android屏蔽软键盘并且显示光标的实例详解 如果是android4.0以下,那么 editText.setInputType(InputType.TYPE_NULL); 就够了,android4.0以上屏蔽软键盘并且有光标,需要用到. if (android.os.Build.VERSION.SDK_INT <= 10) {//4.0以下 danielinbiti editText.setInputType(InputType.TYPE_NULL); } else { this.act.ge

  • Android中用Bmob实现短信验证码功能的方法详解

    这篇文章主要介绍发送验证码和校验验证码的功能,用到一个第三方平台Bmob,那Bmob是什么呢?Bmob可以开发一个云存储的移动应用软件,他提供了大量的标准的API接口,根据需要接入相关服务,开发者可以更加专注于应用的开发,让产品交付更快速,验证码功能就是其中一个. 一.跟其他第三方一样,我们开发之前要做一些准备工作. 1.首先,去官网注册一个帐号:http://www.bmob.cn/: 2.然后就可以创建应用了:具体怎么做Bmob说得很清楚了(官方操作介绍),如果你不想看,我简单说一下:点击右

  • Android中Spinner(下拉框)控件的使用详解

    android给我们提供了一个spinner控件,这个控件主要就是一个列表,那么我们就来说说这个控件吧,这个控件在以前的也看见过,但今天还是从新介绍一遍吧. Spinner位于 android.widget包下,每次只显示用户选中的元素,当用户再次点击时,会弹出选择列表供用户选择,而选择列表中的元素同样来自适配器.Spinner是View类得一个子类. 1.效果图 2.创建页面文件(main.xml) <Spinner android:id="@+id/spinner1" and

  • Android 使用PopupWindow实现弹出更多的菜单实例详解

    最近想要做一个弹出更多的菜单,而原生的弹出菜单却不是我们想要的效果,所以必然要自定义菜单咯.本人也是借鉴网上的资料进行封装的,感觉还蛮不错的. 原生的菜单如下图: 自定义之后的效果图: 是不是看到这里之后,对比可知,原生的效果不太理想,所以还是再自己定义吧! 1.PopupWindow可以说是一个浮动在Activity之上的容器,通常用来显示自定义的视图.弹出菜单的封装PopMenuMore /** * 对弹出菜单的封装. * http://blog.csdn.net/maosidiaoxian

  • Android自定义进度条的圆角横向进度条实例详解

    1.本文将向你介绍自定义进度条的写法,比较简单,但还是有些知识点是需要注意的: invalidate()方法 RectF方法的应用 onMeasure方法的应用 2.原理 画3层圆角矩形,底层为黑色,第二层为灰色,最上一层为进度条颜色,示例图如下: 3.效果图   实现圆角进度条还有很多其他方法,比如在Progress控件里填充圆角图片,通过拉伸图片来达到预想的效果,虽然听起来很简单,但实现起来还是有些麻烦的. 4.解说方法 (1)invalidate()方法 invalidate()是用来刷新

  • Android自定义指示器时间轴效果实例代码详解

    指示器时间轴在外卖.购物类的APP里会经常用到,效果大概就像下面这样,看了网上很多文章,大都是自己绘制,太麻烦,其实通过ListView就可以实现. 在Activity关联的布局文件activity_main.xml中放置一个ListView,代码如下.由于这个列表只是用于展示信息,并不需要用户去点击,所以将其clickable属性置为false:为了消除ListView点击产生的波纹效果,我们设置其listSelector属性的值为透明:我们不需要列表项之间的分割线,所以设置其divider属

  • Android实现状态栏和虚拟按键背景颜色的变化实例代码详解

    今天介绍一下,我在项目开发过程中,实现状态栏和虚拟按键背景颜色变化的方法,实现方式是,通过隐藏系统的状态栏和虚拟按键的背景,实现图片和背景显示到状态栏和虚拟按键下方.下面来看实现代码: 实现状态栏背景的设置 状态栏工具类 public class StatusBarUtil { /** * 设置沉浸式状态栏 * * @param activity 需要设置的activity */ public static void setTransparent(Activity activity) { //A

随机推荐