android P (9.0) Launcher3 去掉抽屉式,显示所有app

前言
参考自以下博文,感谢博主
https://blog.csdn.net/qq_30552095/article/details/80494770
https://blog.csdn.net/illailla/article/details/80972830

先下载Launcher3,git clone 或者到googlesource 下载,或者其他地方下载
git clone https://android.googlesource.com/platform/packages/apps/Launcher3

git clone 需要翻墙 遇到443问题的话设置下代理
git config --global http.proxy “localhost:1080”

下载后checkout branch到android 9.0 pie, 我check 的分支是pie-release-2
接下来就开始将Launcher3改成我们需要的样式了

Launcher3 改成抽屉式需要更改的内容
1.显示所有app在桌面上
2.去掉上划展开应用列表
3.长按拖动图标去掉删除改成取消 卸载

显示所有app在桌面上
要显示所有app在桌面上,也就是workspace上,首先是要先把所有应用加到桌面,然后要考虑安装后的应用显示到桌面
先在src/com.android.launcher3.config.BaseFlags添加个boolean值

abstract class BaseFlags {

    BaseFlags() {}

    public static final boolean REMOVE_DRAWER = true;
    ...

1.显示所有应用
应用加载在src/com.android.launcher3.model.LoaderTask 里
在run里面添加方法加载所有应用

  	// second step
            TraceHelper.partitionSection(TAG, "step 2.1: loading all apps");
            loadAllApps();
            //add by yy
            if (FeatureFlags.REMOVE_DRAWER) {
                verifyApplications();
            }
            //end add by yy
            TraceHelper.partitionSection(TAG, "step 2.2: Binding all apps");
            verifyNotStopped();
            mResults.bindAllApps();

    //add by yy
    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);
            }
        }
    }
    //end add by yy

然后再修改src/com.android.launcher3.model.BaseModelUpdateTask,把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.
            if(!FeatureFlags.REMOVE_DRAWER){
                return;
            }
        }
        execute(mApp, mDataModel, mAllAppsList);
    }

这样 应用就可以显示到桌面上了

2.应用安装后加载到桌面
涉及到文件src/com.android.launcher3.model.PackageUpdatedTask

  final ArrayList<AppInfo> addedOrModified = new ArrayList<>();
        addedOrModified.addAll(appsList.added);
        //add by yy
        if(FeatureFlags.REMOVE_DRAWER){
            updateToWorkSpace(context, app, appsList);
        }
        //end add by yy
        appsList.added.clear();
        addedOrModified.addAll(appsList.modified);
        appsList.modified.clear();

这样第一步就完成了

去掉上划展开应用列表
这一个问题跟了好多个文件,先是从博文里提到的src/com.android.launcher3.allapps.AllAppsTransitionController
再到src/com.android.launcher3.LauncherStateManager/StateHandler
再到src/com.android.launcher3.LauncherStateManager
在AllAppsTransitionController里修改setState方法和setStateWithAnimation方法

 public void setState(LauncherState state) {
 //2018.12.12 更新 setState方法可以不用管,不然会导致有动画效果没有
  //      if(FeatureFlags.REMOVE_DRAWER)
  //          return;
        setProgress(state.getVerticalProgress(mLauncher));
        setAlphas(state, NO_ANIM_PROPERTY_SETTER);
        onProgressAnimationEnd();
    }
     @Override
    public void setStateWithAnimation(LauncherState toState,
            AnimatorSetBuilder builder, AnimationConfig config) {
        if(FeatureFlags.REMOVE_DRAWER)
            return;
        float targetProgress = toState.getVerticalProgress(mLauncher);
        if (Float.compare(mProgress, targetProgress) == 0) {
            setAlphas(toState, config.getPropertySetter(builder));
            // Fail fast
            onProgressAnimationEnd();
            return;
        }

这样可以实现上划去掉展开所有app,但是可以上划,上划后会隐藏掉所有的app
在这里插入图片描述

然后找到滑动的地方src/com.android.launcher3.touch.AbstractStateChangeTouchController
最后发现修改src_ui_overrides/com.android.launcher3.uioverrides.AllAppsSwipeController

   @Override
    protected boolean canInterceptTouch(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            mTouchDownEvent = ev;
        }
        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(NORMAL) && !mLauncher.isInState(ALL_APPS)) {
            // Don't listen for the swipe gesture if we are already in some other state.
            return false;
        }
        if (mLauncher.isInState(ALL_APPS) && !mLauncher.getAppsView().shouldContainerScroll(ev)) {
            return false;
        }
        //add by yy
        if(FeatureFlags.REMOVE_DRAWER){
            return false;
        }
        //end add by yy
        return true;
    }

这样就上划不了了,但是这样会有什么其他影响暂时还没研究出来

长按拖动图标去掉删除改成取消 卸载
长按图标出现删除,卸载栏
src/com.android.launcher3.DropTargetBar
应用图标拖动的控制类
src/com.android.launcher3.dragndrop.DragController
删除,卸载类
src/com.android.launcher3.DeleteDropTarget
src/com.android.launcher3.SecondaryDropTarget
拖动应用图标或者文件夹的时候我们需要把删除改成取消,并且拖到取消后桌面不能移除图标
1.应用图标或者文件夹拖动删除改成取消
src/com.android.launcher3.DeleteDropTarget

  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);
            if(FeatureFlags.REMOVE_DRAWER){
                mText = getResources().getString(isCanDrop(item)
                        ? R.string.remove_drop_target_label
                        : android.R.string.cancel);
            }
            requestLayout();
        }
    }

mControlType 具体作用还不清楚,也一起改了

    /**
     * Set mControlType depending on the drag item.
     */
    private void setControlTypeBasedOnDragSource(ItemInfo item) {
        mControlType = item.id != ItemInfo.NO_ID ? ControlType.REMOVE_TARGET
                : ControlType.CANCEL_TARGET;
        if(FeatureFlags.REMOVE_DRAWER) {
            mControlType = isCanDrop(item) ? ControlType.REMOVE_TARGET
                    : ControlType.CANCEL_TARGET;
        }
    }

2.删除操作改为取消操作
DragController是应用图标拖动的控制类
onDriverDragEnd是拖动结束后调用的地方,drop 是执行拖动后操作

   @Override
    public void onDriverDragEnd(float x, float y) {
        DropTarget dropTarget;
        Runnable flingAnimation = mFlingToDeleteHelper.getFlingAnimation(mDragObject);
        if (flingAnimation != null) {
            dropTarget = mFlingToDeleteHelper.getDropTarget();
        } else {
            dropTarget = findDropTarget((int) x, (int) y, mCoordinatesTemp);
        }

        drop(dropTarget, flingAnimation);

        endDrag();
    }

在drop方法里对droptarget 判断 如果是拖动到删除 也就是DeleteDropTarget 就取消拖动

  private void drop(DropTarget dropTarget, Runnable flingAnimation) {
        final int[] coordinates = mCoordinatesTemp;
        mDragObject.x = coordinates[0];
        mDragObject.y = coordinates[1];

        // Move dragging to the final target.
        if (dropTarget != mLastDropTarget) {
            if (mLastDropTarget != null) {
                mLastDropTarget.onDragExit(mDragObject);
            }
            mLastDropTarget = dropTarget;
            if (dropTarget != null) {
                dropTarget.onDragEnter(mDragObject);
            }
        }

        mDragObject.dragComplete = true;
        if (mIsInPreDrag) {
            if (dropTarget != null) {
                dropTarget.onDragExit(mDragObject);
            }
            return;
        }


        // Drop onto the target.
        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 by yy //2018-11-30 16:05 修改
                if (FeatureFlags.REMOVE_DRAWER && dropTarget instanceof DeleteDropTarget &&
                        isNeedCancelDrag(mDragObject.dragInfo)) {
                    cancelDrag();
                }
                //end add by yy
            }
        }
        final View dropTargetAsView = dropTarget instanceof View ? (View) dropTarget : null;
        mLauncher.getUserEventDispatcher().logDragNDrop(mDragObject, dropTargetAsView);
        dispatchDropComplete(dropTargetAsView, accepted);
    }

    private boolean isNeedCancelDrag(ItemInfo item){
        return (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
                item.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER);
    }

这样只完成了一步,看 dropTarget.onDrop(mDragObject, mOptions); 这里执行了drop操作.
看DeleteDropTarget 的父类src/com.android.launcher3.ButtonDropTarget

  @Override
    public void onDrop(final DragObject d, final DragOptions options) {
        final DragLayer dragLayer = mLauncher.getDragLayer();
        final Rect from = new Rect();
        dragLayer.getViewRectRelativeToSelf(d.dragView, from);

        final Rect to = getIconRect(d);
        final float scale = (float) to.width() / from.width();
        mDropTargetBar.deferOnDragEnd();

        Runnable onAnimationEndRunnable = () -> {
            completeDrop(d);
            mDropTargetBar.onDragEnd();
            mLauncher.getStateManager().goToState(NORMAL);
        };

        dragLayer.animateView(d.dragView, from, to, scale, 1f, 1f, 0.1f, 0.1f,
                DRAG_VIEW_DROP_DURATION,
                Interpolators.DEACCEL_2, Interpolators.LINEAR, onAnimationEndRunnable,
                DragLayer.ANIMATION_END_DISAPPEAR, null);
    }

这里做了一个动画效果,动画完后就调用了onAnimationEndRunnable
completeDrop 就是做对应的操作了,然后看DeleteDropTarget 的completeDrop 方法

  @Override
    public void completeDrop(DragObject d) {
        ItemInfo item = d.dragInfo;
        if ((d.dragSource instanceof Workspace) || (d.dragSource instanceof Folder)) {
            onAccessibilityDrop(null, item);
        }
    }

    /**
     * Removes the item from the workspace. If the view is not null, it also removes the view.
     */
    @Override
    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 by yy ,cancel to remove app icon and folder
        if(!FeatureFlags.REMOVE_DRAWER || isCanDrop(item)) {
            mLauncher.removeItem(view, item, true /* deleteFromDb */);
            mLauncher.getWorkspace().stripEmptyScreens();
            mLauncher.getDragLayer()
                    .announceForAccessibility(getContext().getString(R.string.item_removed));
        }
        // end add by yy
    }

    private boolean isCanDrop(ItemInfo item){
        return !(item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
                item.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER);
    }

把删除应用图标操作去掉就好了,不让删除应用图标和文件夹

2018-12-03 12:00 更新
应用列表会有个提示上拉的跳动小动画,在src/com.android.launcher3.Launcher 的onResume里,把它去掉就好了

   @Override
    protected void onResume() {
        TraceHelper.beginSection("ON_RESUME");
        super.onResume();
        TraceHelper.partitionSection("ON_RESUME", "superCall");

        mHandler.removeCallbacks(mLogOnDelayedResume);
        Utilities.postAsyncCallback(mHandler, mLogOnDelayedResume);

        setOnResumeCallback(null);
        // Process any items that were added while Launcher was away.
        InstallShortcutReceiver.disableAndFlushInstallQueue(
                InstallShortcutReceiver.FLAG_ACTIVITY_PAUSED, this);

        // Refresh shortcuts if the permission changed.
        mModel.refreshShortcutsIfRequired();
        //Add by yy
        if(!FeatureFlags.REMOVE_DRAWER)
            DiscoveryBounce.showForHomeIfNeeded(this);
        //end add by yy
        if (mLauncherCallbacks != null) {
            mLauncherCallbacks.onResume();
        }
        UiFactory.onLauncherStateOrResumeChanged(this);

        TraceHelper.endSection("ON_RESUME");
    }

Launcher3 的Quickstep会调用DiscoveryBounce.showForOverviewIfNeeded 也会有all app跳动的动画
所以我把DiscoveryBounce里的showForHomeIfNeeded 和 showForOverviewIfNeeded 都给注释掉了

  • 6
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值