欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-03-16 11:13:08
...

效果图

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;
    }
	
	....
}
相关标签: launcher3 去抽屉