android 6.0 Launcher3 去掉抽屉式,显示所有 app

效果图

在这里插入图片描述

修改思路

1、去除 allAppsButton,调整 HotSeat 布局,禁止增删,禁止生成 Folder

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

3、去除 Workspace 图标长按删除选项

上代码

1、增加全局控制开关,方便客户选择是否需要去掉抽屉界面。

Launcher3\src\com\android\launcher3\LauncherAppState.java

//cczheng add check is need allappbutton
public static boolean isDisableAllApps() {
        if (sContext != null) {
            return Settings.System.getInt(sContext.getContentResolver(), "sys.launcher3.is_full_app", 1) == 1;
        }
        return true;
    }

在 LauncherAppState 中添加获取变量的值,对应的值修改可以在 Setting 中通过增加 SwitchPreference 开关或者在 workSpace 长按显示的 view 中增加。

2、取消占位,去除 allAppsButton 按钮

packages\apps\Launcher3\src\com\android\launcher3\Hotseat.java

取消占位

	public boolean isAllAppsButtonRank(int rank) {
        //cczheng add cancel allAppsButton location
        log("isAllAppsButtonRank=="+rank + " mAllAppsButtonRank="+mAllAppsButtonRank);
        if (LauncherAppState.isDisableAllApps()) {
            return false;
        }
        return rank == mAllAppsButtonRank;
    }

去除 allAppsButton 按钮

	void resetLayout() {
        mContent.removeAllViewsInLayout();

        // cczheng add juge is need add allAppsButton S
        if (!LauncherAppState.isDisableAllApps()) {
            Context context = getContext();

            LayoutInflater inflater = LayoutInflater.from(context);
            TextView allAppsButton = (TextView)
                    inflater.inflate(R.layout.all_apps_button, mContent, false);
            Drawable d = context.getResources().getDrawable(R.drawable.all_apps_button_icon);

            mLauncher.resizeIconDrawable(d);
            allAppsButton.setCompoundDrawables(null, d, null, null);

            allAppsButton.setContentDescription(context.getString(R.string.all_apps_button_label));
            allAppsButton.setOnKeyListener(new HotseatIconKeyEventListener());
            if (mLauncher != null) {
                mLauncher.setAllAppsButton(allAppsButton);
                allAppsButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
                allAppsButton.setOnClickListener(mLauncher);
                allAppsButton.setOnLongClickListener(mLauncher);
                allAppsButton.setOnFocusChangeListener(mLauncher.mFocusHandler);
            }

            // Note: We do this to ensure that the hotseat is always laid out in the orientation of
            // the hotseat in order regardless of which orientation they were added
            int x = getCellXFromOrder(mAllAppsButtonRank);
            int y = getCellYFromOrder(mAllAppsButtonRank);
            CellLayout.LayoutParams lp = new CellLayout.LayoutParams(x,y,1,1);
            lp.canReorder = false;
            mContent.addViewToCellLayout(allAppsButton, -1, allAppsButton.getId(), lp, true);
        }//E
    }

HotSeat 增加背景

@Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        DeviceProfile grid = mLauncher.getDeviceProfile();

        mAllAppsButtonRank = grid.inv.hotseatAllAppsRank;
        mContent = (CellLayout) findViewById(R.id.layout);
        if (grid.isLandscape && !grid.isLargeTablet) {
            mContent.setGridSize(1, (int) grid.inv.numHotseatIcons);
        } else {
            mContent.setGridSize((int) grid.inv.numHotseatIcons, 1);
        }
        mContent.setIsHotseat(true);

        Log.i(TAG, "onFinishInflate,(int) grid.numHotseatIcons: ");

        //cczheng add hotseat bg [s]
        if (LauncherAppState.isDisableAllApps()) {
            setBackgroundResource(R.drawable.hotseat_bg);
        }//E
        resetLayout();
    }

hotseat_bg.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    
    <stroke
        android:width="0.1dp"
        android:color="#ffffffff" />

    <solid android:color="#50000000" />

    <corners android:radius="10dp" />

</shape>

3、HotSeat 区域图标大小调整

Launcher3\src\com\android\launcher3\DeviceProfile.java

区域大小调整

public void layout(Launcher launcher) {
        FrameLayout.LayoutParams lp;
        boolean hasVerticalBarLayout = isVerticalBarLayout();
        final boolean isLayoutRtl = Utilities.isRtl(launcher.getResources());

        ....

        else {
            // For phones, layout the hotseat without any bottom margin
            // to ensure that we have space for the folders
            /*lp.gravity = Gravity.BOTTOM;
            lp.width = LayoutParams.MATCH_PARENT;
            lp.height = hotseatBarHeightPx;
            hotseat.findViewById(R.id.layout).setPadding(2 * edgeMarginPx, 0,
                    2 * edgeMarginPx, 0);*/
            //cczheng add if change hotseat default size S
            if (LauncherAppState.isDisableAllApps()) {
                lp.gravity = Gravity.BOTTOM | Gravity.CENTER;
                lp.width = 600;
                lp.height = 120;
            }else{//E
                lp.gravity = Gravity.BOTTOM;
                lp.width = LayoutParams.MATCH_PARENT;
                lp.height = hotseatBarHeightPx;
                hotseat.findViewById(R.id.layout).setPadding(2 * edgeMarginPx, 0,
                        2 * edgeMarginPx, 0);
            }
        }
        hotseat.setLayoutParams(lp);

		...
}

图标大小调整

Launcher3\src\com\android\launcher3\CellLayout.java

public float getChildrenScale() {
        //cczheng add don't sclae large hotseat
        return mIsHotseat ? (LauncherAppState.isDisableAllApps() ? 0.75f : mHotseatScale) : 1.0f;
    }

4、HotSeat 禁止增删,禁止生成 Folder

禁用长按事件

Launcher3\src\com\android\launcher3\Launcher.java

public boolean onLongClick(View v) {

	....

	CellLayout.CellInfo longClickCellInfo = null;
        View itemUnderLongClick = null;
        if (v.getTag() instanceof ItemInfo) {
            ItemInfo info = (ItemInfo) v.getTag();
            longClickCellInfo = new CellLayout.CellInfo(v, info);
            itemUnderLongClick = longClickCellInfo.cell;
            resetAddInfo();
        }

        //cczheng add , hotseat can't be moved and deleted [S] 
         if (LauncherAppState.isDisableAllApps()) {
            if(longClickCellInfo != null && longClickCellInfo.container==-101){
                    return false;
                }
        }//E

		...
}

禁止生成 Folder

Launcher3\src\com\android\launcher3\Workspace.java

 boolean createUserFolderIfNecessary(View newView, long container, CellLayout target,
            int[] targetCell, float distance, boolean external, DragView dragView,
            Runnable postAnimationRunnable) {
        ....

        if (v == null || hasntMoved || !mCreateUserFolderOnDrop) {
            if (LauncherLog.DEBUG) {
                LauncherLog.d(TAG, "Do not create user folder: hasntMoved = " + hasntMoved
                    + ", mCreateUserFolderOnDrop = " + mCreateUserFolderOnDrop + ", v = " + v);
            }
            return false;
        }

        //cczheng add don't creat folder in hotseat area [S]
        if (LauncherAppState.isDisableAllApps() && mLauncher.isHotseatLayout(target)) {
            Log.e("Launcher3", "isHotseatLayout return false");
            return false;
        }
        //[E]

        mCreateUserFolderOnDrop = false;
        final long screenId = (targetCell == null) ? mDragInfo.screenId : getIdForScreen(target);

		....
}

屏蔽圆形浮窗文件夹背景

Launcher3\src\com\android\launcher3\Workspace.java

public void onDragOver(DragObject d) {
        if (LauncherLog.DEBUG_DRAG) {
            LauncherLog.d(TAG, "onDragOver: d = " + d + ", dragInfo = " + d.dragInfo
                + ", mInScrollArea = " + mInScrollArea + ", mIsSwitchingState = "
                + mIsSwitchingState);
        }

        // Skip drag over events while we are dragging over side pages
        if (mInScrollArea || !transitionStateShouldAllowDrop()) return;

        .....

        // Handle the drag over
        if (mDragTargetLayout != null) {
            // We want the point to be mapped to the dragTarget.
            if (mLauncher.isHotseatLayout(mDragTargetLayout)) {
                //cczheng don't show folder cicle when dragtarget in hotseat are
                if (LauncherAppState.isDisableAllApps()) {
                    Log.d("Launcher3", "don't show folder cicle when dragtarget in hotseat are");
                    return;
                }else{//E
                    mapPointFromSelfToHotseatLayout(mLauncher.getHotseat(), mDragViewVisualCenter);
                }
            } else {
                mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
            }

			....

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

Launcher3\src\com\android\launcher3\LauncherModel.java

内部类 LoaderTask 中, run 方法

private class LoaderTask implements Runnable {
        private Context mContext;
        @Thunk boolean mIsLoadingAndBindingWorkspace;
        private boolean mStopped;
        @Thunk boolean mLoadAndBindStepFinished;
        private int mFlags;

        LoaderTask(Context context, int flags) {
            mContext = context;
            mFlags = flags;
        }
		
		....


		public void run() {
            ....

            // Optimize for end-user experience: if the Launcher is up and // running with the
            // All Apps interface in the foreground, load All Apps first. Otherwise, load the
            // workspace first (default).
            keep_running: {
                if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
                loadAndBindWorkspace();

                if (mStopped) {
                    LauncherLog.i(TAG, "LoadTask break in the middle, this = " + this);
                    break keep_running;
                }

                waitForIdle();

                // second step
                if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
                loadAndBindAllApps();

                //cczheng add for load all app shortcut on workspace
                if (LauncherAppState.isDisableAllApps()) {
                  verifyApplications();
                }//E
            }

            ....
        }

		...

在 loadAndBindAllApps() 附近增加 verifyApplications()

//cczheng add for load all app shortcut on workspace
private void verifyApplications() {
    Log.e("Launcher3", "verifyApplications()");
    final Context context = mApp.getContext();
    // Cross reference all the applications in our apps list with items in the workspace
    ArrayList<ItemInfo> tmpInfos;
    ArrayList<ItemInfo> added = new ArrayList<ItemInfo>();
    Log.i("Launcher3", "mBgAllAppsList.data size=="+mBgAllAppsList.data.size());
    synchronized (sBgLock) {
      for (AppInfo app : mBgAllAppsList.data) {
        tmpInfos = getItemInfoForComponentName(app.componentName, app.user, app.title.toString());
        if (tmpInfos.isEmpty()) {
          // We are missing an application icon, so add this to the workspace
          added.add(app);
          // This is a rare event, so lets log it
          Log.e("Launcher3", "Missing Application on load: " + app);
        }else{
           Log.i("Launcher3", "app.componentName: " + app.componentName); 
        }
      }
    }
    Log.e("Launcher3", "added.isEmpty()="+added.isEmpty());
    if (!added.isEmpty()) {
      addAndBindAddedWorkspaceItems(context, added);
    }
}
//E

private void loadAndBindAllApps() {
	....
}

内部类 PackageUpdatedTask 中,run 方法

Launcher3\src\com\android\launcher3\LauncherModel.java

private class PackageUpdatedTask implements Runnable {
        int mOp;
        String[] mPackages;
        UserHandleCompat mUser;

        public static final int OP_NONE = 0;
        public static final int OP_ADD = 1;
        public static final int OP_UPDATE = 2;
        public static final int OP_REMOVE = 3; // uninstlled
        public static final int OP_UNAVAILABLE = 4; // external media unmounted


        public PackageUpdatedTask(int op, String[] packages, UserHandleCompat user) {
            mOp = op;
            mPackages = packages;
            mUser = user;
        }

        public void run() {
            ....

            if (LauncherLog.DEBUG) {
                LauncherLog.d(TAG, "PackageUpdatedTask: added = " + added + ",modified = "
                        + modified + ",removedApps = " + removedApps);
            }

            final HashMap<ComponentName, AppInfo> addedOrUpdatedApps =
                    new HashMap<ComponentName, AppInfo>();

            if (added != null) {
                //cczheng add for load all app shortcut on workspace
                if (LauncherAppState.isDisableAllApps()) {
                    final ArrayList<ItemInfo> addedInfos = new ArrayList<ItemInfo>(added);
                    addAndBindAddedWorkspaceItems(context, addedInfos);
                }else{//E
                    addAppsToAllApps(context, added);
                }
                for (AppInfo ai : added) {
                    addedOrUpdatedApps.put(ai.componentName, ai);
                }
            }

            ....

}

6、去除 Workspace 图标长按删除选项

ButtonDropTarget 的三个实现类,onDragStart() 中 通过 supportsDrop() 控制 ViewGroup 是否显示,那么我只需让 DeleteDropTarget 中 supportsDrop() 为 false

DeleteDropTarget

InfoDropTarget

UninstallDropTarget
public static boolean supportsDrop(Object info) {
        //cczheng add for don't show delete icon for shortcut [S]
        android.util.Log.e("ccz","dele drop ");
        if (LauncherAppState.isDisableAllApps()) {
            if (info instanceof ShortcutInfo) {
                ShortcutInfo item = (ShortcutInfo) info;
                return item.itemType != LauncherSettings.BaseLauncherColumns.ITEM_TYPE_APPLICATION;
            }
            return info instanceof LauncherAppWidgetInfo;
        }
        //cczheng add for don't show delete icon for shortcut [E]
        return (info instanceof ShortcutInfo)
                || (info instanceof LauncherAppWidgetInfo)
                || (info instanceof FolderInfo);
    }

7、根据全局控制开关,加载不同的布局

Launcher3\src\com\android\launcher3\InvariantDeviceProfile.java

public class InvariantDeviceProfile {

	....

	DeviceProfile landscapeProfile;
    DeviceProfile portraitProfile;
	
	//cczheng add 
    boolean isDisableAllApps = LauncherAppState.isDisableAllApps(); 

    InvariantDeviceProfile() {
    }

	...

	ArrayList<InvariantDeviceProfile> getPredefinedDeviceProfiles() {
        ArrayList<InvariantDeviceProfile> predefinedDeviceProfiles = new ArrayList<>();

        ....

        predefinedDeviceProfiles.add(new InvariantDeviceProfile("Nexus S",
                296, 491.33f, 4, 4, 4, 4, 4, 48, 13, 5, 48, R.xml.default_workspace_4x4));
        predefinedDeviceProfiles.add(new InvariantDeviceProfile("Nexus 4",
                335, 567,     4, 4, 4, 4, 4, DEFAULT_ICON_SIZE_DP, 13, 5, 56, R.xml.default_workspace_4x4));
        predefinedDeviceProfiles.add(new InvariantDeviceProfile("Nexus 5",
                359, 567,     4, 4, 4, 4, 4, DEFAULT_ICON_SIZE_DP, 13, 5, 56, R.xml.default_workspace_4x4));
        //cczheng add,4x5 xml,5 rows,4 columns [S]
        predefinedDeviceProfiles.add(new InvariantDeviceProfile("MTK",
                375, 567,     5, 4, 5, 4, 4, 56, 10, isDisableAllApps ? 3 : 5, 
                56, 
                isDisableAllApps ? R.xml.default_workspace_4x5_no_all_apps : R.xml.default_workspace_4x5));
        //cczheng add,4x5 xml,5 rows,4 columns [E]

        predefinedDeviceProfiles.add(new InvariantDeviceProfile("Large Phone",
                406, 694,     5, 5, 4, 4, 4, 64, 14.4f,  5, 56, R.xml.default_workspace_5x5));
        ....

        return predefinedDeviceProfiles;
    }
	
	....
}
发布了87 篇原创文章 · 获赞 157 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/u012932409/article/details/102922170