android Launcher3双层改单层

将Launcher3改为单层模式,这是android系统定制遇到的一个常见的需求。下面我将介绍一下我再MTK源码下将Luancher3改为单层的步骤和方法,以及解决一些bug。希望这个总结对读者有一点启发和用途。

一、打开Launcher3的单层开关

MTK源码的Launcher3本省就有单层开关。这个开关就是LauncherAppState.java的public static boolean isDisableAllApps()方法,只要把这个方法的返回值改为true即可。做好这一步,重新编译安装后,Launcher3就变为单层模式了。

二、虽然Launcher3变成了单层,但是带来了几个问题

1、重新启动Launcher3,安装一个第三方应用,这时应用可以被卸载;但是安装第三方应用后,再重启后就不能被卸载(长按不会出现卸载提示)。通过debug断点查看Launcher3的卸载过程,发现Launcher3是否能够删除主要是根据ShortcutInfo或Appinfo的flags来决定。但是,通过查看代码可以看到在LauncherModel.java(数据库操作类)通过方法getShortcutInfo获取ShortcutInfo时,flags没有被设置数字,一直为默认值0,因而无法删除应用。原生代码的两层UI对应的数据分别是ShortcutInfo和Appinfo,查询AppInfo时不同于ShortcutInfo,flags值会有赋值。同时,根据安装第三方应用后不重启可以被删除的情况判断,安装广播时得到新的ShoertcurInfo会对flags赋值。所以解决的办法就有了:修改getShortcutInfo方法,在方法中实现当isDisableAllApps == true时对flags进行赋值。赋值的方法参照对AppInfo的flags赋值的方法,最后方法如下:

try {
            final String packageName = componentName.getPackageName();
            PackageInfo pi = manager.getPackageInfo(packageName, 0);
            if (!pi.applicationInfo.enabled) {
                return null;
            }
            final int appFlags = manager.getApplicationInfo(packageName, 0).flags;
            if ((appFlags & android.content.pm.ApplicationInfo.FLAG_SYSTEM) == 0) {
                info.flags |= AppInfo.DOWNLOADED_FLAG;
                if ((appFlags & android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
                    info.flags |= AppInfo.UPDATED_SYSTEM_APP_FLAG;
                }
            }
        } catch (NameNotFoundException e) {
            return null;
        }

。。。。。。。。。。。。。。。。。。。。。。

打包、安装、运行,还是报错了。。。。。

查看日志,发现问题是DeleteDropTarget.java下:


onDragStart(DragSource source, Object info, int dragAction)实现图标更换:增加判断条件
boolean useUninstallLabel = LauncherAppState.isDisableAllApps() &&
                (info instanceof ShortcutInfo);
        boolean useDeleteLabel = !useUninstallLabel && (info instanceof LauncherAppWidgetInfo);


completeDrop(DragObject d)实现卸载操作:将11111111111111处改为2222222222222222
else if (isWorkspaceOrFolderApplication(d)) {
            if (LauncherLog.DEBUG) {
            LauncherLog.d(TAG, "33isWorkspaceOrFolderApplication");
            }
            //LauncherModel.deleteItemFromDatabase(mLauncher, item);//1111111111111111111111
            ///{22222222222
            ShortcutInfo shortcut = (ShortcutInfo) item;
            ComponentName componentName = shortcut.intent.getComponent();
            AppInfo appInfo = (AppInfo) shortcut.makeAppInfo();
            mLauncher.startApplicationUninstallActivity(componentName, appInfo.flags,
                    appInfo.user);
            ///22222222222}        
       
private boolean isWorkspaceOrFolderApplication(DragObject d) {
        return isDragSourceWorkspaceOrFolder(d) && (d.dragInfo instanceof ShortcutInfo);
  }

2、修改桌面为循环滚动:\packages\apps\Launcher3\ext\src\com\mediatek\launcher3\ext\DefaultWorkspaceExt.java
    @Override
    public boolean supportAppListCycleSliding() {
        LauncherLog.d(TAG, "default supportAppListCycleSliding called.");
        return true;
    }

3、修改后,添加appwidget后,workspace缩小后的状态不会变回来。解决的办法/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java下



    /**
     * Zoom the camera back into the workspace, hiding 'fromView'.
     * This is the opposite of showAppsCustomizeHelper.
     * @param animated If true, the transition will be animated.
     */
    private void hideAppsCustomizeHelper(Workspace.State toState, final boolean animated,
            final boolean springLoaded, final Runnable onCompleteRunnable) {

==================================此处没有修改=========================================
       

        if (animated && initialized) {
            ==================================此处没有修改=========================================
        } else {
                //yuanhcn add============================================================================================
                mStateAnimation = LauncherAnimUtils.createAnimatorSet();
            if (workspaceAnim != null) {
                mStateAnimation.play(workspaceAnim);
            }


            final AppsCustomizePagedView content = (AppsCustomizePagedView)
                    fromView.findViewById(R.id.apps_customize_pane_content);
            Log.i(TAG, "content visible: " + (content.getVisibility() == View.VISIBLE));
            Log.i(TAG, "mAppsCustomizeTabHost visible: " + (mAppsCustomizeTabHost.getVisibility() == View.VISIBLE));


            final View page = content.getPageAt(content.getNextPage());
            Log.i(TAG, "content.getNextPage: " + content.getNextPage());
            
            // We need to hide side pages of the Apps / Widget tray to avoid some ugly edge cases
            int count = content.getChildCount();
            for (int i = 0; i < count; i++) {
                View child = content.getChildAt(i);
                if (child != page) {
                    child.setVisibility(View.INVISIBLE);
                }
            }
            final View revealView = fromView.findViewById(R.id.fake_page);


            // hideAppsCustomizeHelper is called in some cases when it is already hidden
            // don't perform all these no-op animations. In particularly, this was causing
            // the all-apps button to pop in and out.
            if (fromView.getVisibility() == View.VISIBLE) {
                AppsCustomizePagedView.ContentType contentType = content.getContentType();
                final boolean isWidgetTray =
                        contentType == AppsCustomizePagedView.ContentType.Widgets;


                if (isWidgetTray) {
                    revealView.setBackground(res.getDrawable(R.drawable.quantum_panel_dark));
                } else {
                    /*ltz modify begin*/
                    if(Launcher.DISABLE_APPLIST_WHITE_BG) {
                        revealView.setBackground(null);
                    } else {
                        revealView.setBackground(res.getDrawable(R.drawable.quantum_panel));
                    }
                    /*ltz modify end*/
                }


                int width = revealView.getMeasuredWidth();
                int height = revealView.getMeasuredHeight();
                float revealRadius = (float) Math.sqrt((width * width) / 4 + (height * height) / 4);


                // Hide the real page background, and swap in the fake one
                revealView.setVisibility(View.VISIBLE);
                content.setPageBackgroundsVisible(false);


                
                //////
yuanhcn add  final View allAppsButton = getAllAppsButton();replece allAppsButton by mHotseat
                final View allAppsButton = getHotseat();
                
                
                revealView.setTranslationY(0);
                int[] allAppsToPanelDelta = Utilities.getCenterDeltaInScreenSpace(revealView,
                        allAppsButton, null);


                float xDrift = 0;
                float yDrift = 0;
                if (material) {
                    yDrift = isWidgetTray ? height / 2 : allAppsToPanelDelta[1];
                    xDrift = isWidgetTray ? 0 : allAppsToPanelDelta[0];
                } else {
                    yDrift = 2 * height / 3;
                    xDrift = 0;
                }
                Log.i(TAG, "yDrift: " + yDrift + ",xDrift: " + xDrift + ", isWidgetTray: " + isWidgetTray);


                revealView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
                TimeInterpolator decelerateInterpolator = material ?
                        new LogDecelerateInterpolator(100, 0) :
                        new DecelerateInterpolator(1f);


                // The vertical motion of the apps panel should be delayed by one frame
                // from the conceal animation in order to give the right feel. We correpsondingly
                // shorten the duration so that the slide and conceal end at the same time.
                ObjectAnimator panelDriftY = LauncherAnimUtils.ofFloat(revealView, "translationY",
                        0, yDrift);
                panelDriftY.setDuration(revealDuration - SINGLE_FRAME_DELAY);
                panelDriftY.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
                panelDriftY.setInterpolator(decelerateInterpolator);
                mStateAnimation.play(panelDriftY);


                ObjectAnimator panelDriftX = LauncherAnimUtils.ofFloat(revealView, "translationX",
                        0, xDrift);
                panelDriftX.setDuration(revealDuration - SINGLE_FRAME_DELAY);
                panelDriftX.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
                panelDriftX.setInterpolator(decelerateInterpolator);
              //  mStateAnimation.play(panelDriftX);


                if (isWidgetTray || !material) {
                    float finalAlpha = material ? 0.4f : 0f;
                    revealView.setAlpha(1f);
                    ObjectAnimator panelAlpha = LauncherAnimUtils.ofFloat(revealView, "alpha",
                            1f, finalAlpha);
                    panelAlpha.setDuration(material ? revealDuration : 150);
                    panelAlpha.setInterpolator(decelerateInterpolator);
                    panelAlpha.setStartDelay(material ? 0 : itemsAlphaStagger + SINGLE_FRAME_DELAY);
                    mStateAnimation.play(panelAlpha);
                }


                if (page != null) {
                    page.setLayerType(View.LAYER_TYPE_HARDWARE, null);


                    ObjectAnimator pageDrift = LauncherAnimUtils.ofFloat(page, "translationY",
                            0, yDrift);
                 //   page.setTranslationY(0);
                    pageDrift.setDuration(revealDuration - SINGLE_FRAME_DELAY);
                    pageDrift.setInterpolator(decelerateInterpolator);
                    pageDrift.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
                 //   mStateAnimation.play(pageDrift);


                    page.setAlpha(1f);
                    ObjectAnimator itemsAlpha = LauncherAnimUtils.ofFloat(page, "alpha", 1f, 0f);
                    itemsAlpha.setDuration(/*100*/60);
                    itemsAlpha.setInterpolator(decelerateInterpolator);
                    mStateAnimation.play(itemsAlpha);
                }


                View pageIndicators = fromView.findViewById(R.id.apps_customize_page_indicator);
              //  pageIndicators.setAlpha(1f);
                pageIndicators.setAlpha(0f);
                ObjectAnimator indicatorsAlpha =
                        LauncherAnimUtils.ofFloat(pageIndicators, "alpha", 0f);
                indicatorsAlpha.setDuration(revealDuration);
                indicatorsAlpha.setInterpolator(new DecelerateInterpolator(1.5f));
              //  mStateAnimation.play(indicatorsAlpha);


                width = revealView.getMeasuredWidth();


                if (material) {
                    if (!isWidgetTray) {
                        allAppsButton.setVisibility(View.INVISIBLE);
                    }
                    int allAppsButtonSize = LauncherAppState.getInstance().
                            getDynamicGrid().getDeviceProfile().allAppsButtonVisualSize;
                    float finalRadius = isWidgetTray ? 0 : allAppsButtonSize / 2;
                    Animator reveal =
                            LauncherAnimUtils.createCircularReveal(revealView, width / 2,
                                    height / 2, revealRadius, finalRadius);
                    reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
                    reveal.setDuration(revealDuration);
                    reveal.setStartDelay(itemsAlphaStagger);


                    reveal.addListener(new AnimatorListenerAdapter() {
                        public void onAnimationEnd(Animator animation) {
                            revealView.setVisibility(View.INVISIBLE);
                            if (!isWidgetTray) {
                                allAppsButton.setVisibility(View.VISIBLE);
                            }
                        }
                    });


                    mStateAnimation.play(reveal);
                }


                dispatchOnLauncherTransitionPrepare(fromView, animated, true);
                dispatchOnLauncherTransitionPrepare(toView, animated, true);
                mAppsCustomizeContent.stopScrolling();
            }


            mStateAnimation.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    fromView.setVisibility(View.GONE);
                    dispatchOnLauncherTransitionEnd(fromView, animated, true);
                    dispatchOnLauncherTransitionEnd(toView, animated, true);
                    if (onCompleteRunnable != null) {
                        onCompleteRunnable.run();
                    }


                    revealView.setLayerType(View.LAYER_TYPE_NONE, null);
                    if (page != null) {
                        page.setLayerType(View.LAYER_TYPE_NONE, null);
                    }
                    content.setPageBackgroundsVisible(true);
                    // Unhide side pages
                    int count = content.getChildCount();
                    for (int i = 0; i < count; i++) {
                        View child = content.getChildAt(i);
                        child.setVisibility(View.VISIBLE);
                    }


                    // Reset page transforms
                    if (page != null) {
                        page.setTranslationX(0);
                        page.setTranslationY(0);
                        page.setAlpha(1);
                    }
                    content.setCurrentPage(content.getNextPage());


                    mAppsCustomizeContent.updateCurrentPageScroll();


                    // This can hold unnecessary references to views.
                    mStateAnimation = null;
                }
            });


            final AnimatorSet stateAnimation = mStateAnimation;
            final Runnable startAnimRunnable = new Runnable() {
                public void run() {
                    // Check that mStateAnimation hasn't changed while
                    // we waited for a layout/draw pass
                    if (mStateAnimation != stateAnimation)
                        return;
                    dispatchOnLauncherTransitionStart(fromView, animated, false);
                    dispatchOnLauncherTransitionStart(toView, animated, false);


                    if (Utilities.isLmpOrAbove()) {
                        for (int i = 0; i < layerViews.size(); i++) {
                            View v = layerViews.get(i);
                            if (v != null) {
                                if (Utilities.isViewAttachedToWindow(v)) v.buildLayer();
                            }
                        }
                    }
                    mStateAnimation.start();
                }
            };
            fromView.post(startAnimRunnable);
                //
yuanhcnadd
        
                //
yuanhcn delete
//            fromView.setVisibility(View.GONE);
//            dispatchOnLauncherTransitionPrepare(fromView, animated, true);
//            dispatchOnLauncherTransitionStart(fromView, animated, true);
//            dispatchOnLauncherTransitionEnd(fromView, animated, true);
//            dispatchOnLauncherTransitionPrepare(toView, animated, true);
//            dispatchOnLauncherTransitionStart(toView, animated, true);
//            dispatchOnLauncherTransitionEnd(toView, animated, true);
                //
yuanhcn 
delete
        }
    }

你可能感兴趣的:(Android系统)