Launcher功能入口

launcher各种功能入口

本篇:Launcher功能入口
下篇:launcher功能入口(二)
下篇:launcher功能入口(三)

1、点击事件、点击图标、点击文件夹等等

ItemClickHandler.java

public static final OnClickListener INSTANCE = ItemClickHandler::onClick;
2.1、长按桌面图标图标 、桌面文件夹、底边栏图标、桌面widget

src/com/android/launcher3/touch/ItemLongClickListener.java

    public static final OnLongClickListener INSTANCE_WORKSPACE =
            ItemLongClickListener::onWorkspaceItemLongClick;
2.2、 长按allapplist图标

src/com/android/launcher3/touch/ItemLongClickListener.java

    public static final OnLongClickListener INSTANCE_ALL_APPS =
            ItemLongClickListener::onAllAppsItemLongClick;
2.3、 长按文件夹内的应用图标
Folder.onLongClick
2.4、长按pop框里的widget or 长按小部件列表的widget
BaseWidgetSheet.onLongClick
2.5、长按添加到主屏幕中的widget
AddItemActivity.onLongClick
2.6、长按空白处弹出主屏幕设置、微件、壁纸菜单
WorkspaceTouchListener.onLongPress-->OptionsPopupView.showDefaultOptions-->OptionsPopupView.show

packages\apps\Launcher3\src\com\android\launcher3\views\OptionsPopupView.java

public static void showDefaultOptions(Launcher launcher, float x, float y) {
        float halfSize = launcher.getResources().getDimension(R.dimen.options_menu_thumb_size) / 2;
        if (x < 0 || y < 0) {
            x = launcher.getDragLayer().getWidth() / 2;
            y = launcher.getDragLayer().getHeight() / 2;
        }
        RectF target = new RectF(x - halfSize, y - halfSize, x + halfSize, y + halfSize);
        show(launcher, target, getOptions(launcher), false);
    }
3、recent界面clearAll

quickstep/src/com/android/quickstep/views/RecentsView.java

    public void dismissAllTasks(View view) {
        runDismissAnimation(createAllTasksDismissAnimation(DISMISS_TASK_DURATION));
        mActivity.getStatsLogManager().logger().log(LAUNCHER_TASK_CLEAR_ALL);
    }
3.1、recentUI界面隐藏掉主菜单界面的部分view
packages/apps/Launcher3/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
prepareRecentsUI中处理
4、recent界面菜单

quickstep/src/com/android/quickstep/views/TaskView.java

private boolean showTaskMenu()
5、recent界面点击单个Task

quickstep/src/com/android/quickstep/views/TaskView.java

setOnClickListener(this::onClick);
6、home页面滑动launcher底部,打开recentTask入口

quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java

case QUICK_SWITCH_STATE_ORDINAL: {
                RecentsView rv = getOverviewPanel();
                TaskView tasktolaunch = rv.getTaskViewAt(0);
                if (tasktolaunch != null) {
                    tasktolaunch.launchTask(success -> {
                        if (!success) {
                            getStateManager().goToState(OVERVIEW);
                        } else {
                            getStateManager().moveToRestState();
                        }
                    });
                } else {
                    getStateManager().goToState(NORMAL);
                }
                break;
            }
7、三方应用界面滑动底部,切换recentTask
8、recent界面点击图标弹出菜单

分屏显示判断

9、桌面切页速度

src/com/android/launcher3/PagedView.java中,onTouchEvent处理切页事件。
切页分2中:
一种是手指缓慢滑动后松手:

public static final int PAGE_SNAP_ANIMATION_DURATION = 300;
public boolean snapToPage(int whichPage) {
        return snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
}

一种是快速滑动:

protected boolean snapToPageWithVelocity(int whichPage, int velocity) {
        whichPage = validateNewPage(whichPage);
        int halfScreenSize = mOrientationHandler.getMeasuredSize(this) / 2;

        final int newLoc = getScrollForPage(whichPage);
        int delta = newLoc - mOrientationHandler.getPrimaryScroll(this);
        int duration = 0;

        if (Math.abs(velocity) < mMinFlingVelocity) {
            // If the velocity is low enough, then treat this more as an automatic page advance
            // as opposed to an apparent physical response to flinging
            return snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
        }

        // Here we compute a "distance" that will be used in the computation of the overall
        // snap duration. This is a function of the actual distance that needs to be traveled;
        // we keep this value close to half screen size in order to reduce the variance in snap
        // duration as a function of the distance the page needs to travel.
        float distanceRatio = Math.min(1f, 1.0f * Math.abs(delta) / (2 * halfScreenSize));
        float distance = halfScreenSize + halfScreenSize *
                distanceInfluenceForSnapDuration(distanceRatio);

        velocity = Math.abs(velocity);
        velocity = Math.max(mMinSnapVelocity, velocity);

        // we want the page's snap velocity to approximately match the velocity at which the
        // user flings, so we scale the duration by a value near to the derivative of the scroll
        // interpolator at zero, ie. 5. We use 4 to make it a little slower.
        duration = Math.round(1000 * Math.abs(distance / velocity));//4 *
		//根据速度计算出动画事件,然后调用切页动画。
        return snapToPage(whichPage, delta, duration);
    }
10、上滑进入recent
11、三方应用界面上滑返回launcher

quickstep/src/com/android/quickstep/TouchInteractionService.java
onInputEvent中处理输入事件

mInputMonitorCompat = new InputMonitorCompat("swipe-up", mDeviceState.getDisplayId());
        mInputEventReceiver = mInputMonitorCompat.getInputReceiver(Looper.getMainLooper(),
                mMainChoreographer, this::onInputEvent);
    private void onInputEvent(InputEvent ev) {
        ...
        MotionEvent event = (MotionEvent) ev;
        ...
        final int action = event.getAction();
        if (action == ACTION_DOWN) {
           //强制获取一次显示方向更新,概率性三方应用界面上滑失效问题
            DisplayController.INSTANCE.get(getBaseContext()).forceHandleInfoChange();
            mRotationTouchHelper.setOrientationTransformIfNeeded(event);

            if (!mDeviceState.isOneHandedModeActive()
                    && mRotationTouchHelper.isInSwipeUpTouchRegion(event)) {
                // Clone the previous gesture state since onConsumerAboutToBeSwitched might trigger
                // onConsumerInactive and wipe the previous gesture state
                GestureState prevGestureState = new GestureState(mGestureState);
                GestureState newGestureState = createGestureState(mGestureState);
                newGestureState.setSwipeUpStartTimeMs(SystemClock.uptimeMillis());
                mConsumer.onConsumerAboutToBeSwitched();
                mGestureState = newGestureState;
                mConsumer = newConsumer(prevGestureState, mGestureState, event);

                ActiveGestureLog.INSTANCE.addLog("setInputConsumer: " + mConsumer.getName());
                mUncheckedConsumer = mConsumer;
            } else if (mDeviceState.isUserUnlocked() && mDeviceState.isFullyGesturalNavMode()) {
                mGestureState = createGestureState(mGestureState);
                ActivityManager.RunningTaskInfo runningTask = mGestureState.getRunningTask();
                if (mDeviceState.canTriggerAssistantAction(event, runningTask)) {
                    // Do not change mConsumer as if there is an ongoing QuickSwitch gesture, we
                    // should not interrupt it. QuickSwitch assumes that interruption can only
                    // happen if the next gesture is also quick switch.
                    mUncheckedConsumer = new AssistantInputConsumer(
                            this,
                            mGestureState,
                            InputConsumer.NO_OP, mInputMonitorCompat,
                            mDeviceState,
                            event);
                } else if (mDeviceState.canTriggerOneHandedAction(event)) {
                    // Consume gesture event for triggering one handed feature.
                    mUncheckedConsumer = new OneHandedModeInputConsumer(this, mDeviceState,
                        InputConsumer.NO_OP, mInputMonitorCompat);
                } else {
                    mUncheckedConsumer = InputConsumer.NO_OP;
                }
            } else if (mDeviceState.canTriggerOneHandedAction(event)) {
                // Consume gesture event for triggering one handed feature.
                mUncheckedConsumer = new OneHandedModeInputConsumer(this, mDeviceState,
                        InputConsumer.NO_OP, mInputMonitorCompat);
            } else {
                mUncheckedConsumer = InputConsumer.NO_OP;
            }
        } else {
            // Other events
            if (mUncheckedConsumer != InputConsumer.NO_OP) {
                // Only transform the event if we are handling it in a proper consumer
                mRotationTouchHelper.setOrientationTransformIfNeeded(event);
            }
        }
        ...
        //上面都是对各种情况mUncheckedConsumer的赋值,最终调用这个方法下发event事件
        mUncheckedConsumer.onMotionEvent(event);
        ...
    }

src\com\android\launcher3\util\DisplayController.java

    public void forceHandleInfoChange(){
        Display display = mDM.getDisplay(DEFAULT_DISPLAY);
            handleInfoChange(display);
    }

最终走到OtherActivityInputConsumer.java的onMotionEvent中处理从其它应用界面上滑返回launcher的动画。

12、上滑进入all apps
13、桌面下拉显示通知栏
14、launcher中的framework.jar包

launcher或者其它系统应用中有framework jar包的,如果framework更新了Google patch,有时候需要单独给apk更新framework包。
Google BTS报错会检测代码漏洞,报错中也会有相应的修改方案,需要合入framework后编译jar包给到apk。

//整编过后,make framework生成jar包
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar
//不能用out/target/common/obj/JAVA_LIBRARIES/framework-minus-apex_intermediates/classes.jar
//这个包会有cts报错

launcher中的sysui包,来自systemui shared模块,单编模块后生成对应的jar包

//编译命令
make MtkSystemUISharedLib
//生成jar包路径
out/target/common/obj/JAVA_LIBRARIES/MtkSystemUISharedLib_intermediates/classes.jar
15、launcher应用列表界面最上面一行应用推荐

参考文章:https://blog.csdn.net/TSK_Amine/article/details/120362380
再加上一些自己的分析。2020/07/27日记录,整理如下。
现象:
Android S上,更新同年四月份gms包后,launcher应用列表上方多出一行图标。
{相册、时钟、比机、Gmail、YouTube、设置}
通过studio自带的Layout Inspector查看,这一部分界面属于all_apps_header。也就是应用列表的头信息布局中。

Android 12 支持了app prediction。
开启此功能后,app list、widget list、hotseat都会有相应的行为。具体见https://blog.csdn.net/a396604593/article/details/126060850

尾注

还有什么想了解的欢迎留言,我后续补充

Android LauncherAndroid系统上的一个应用程序,它是用户与系统交互的主要界面,也是用户启动应用程序的入口。它允许用户查看、操作和管理应用程序、小部件和系统功能Android Launcher的源码解析涉及到多个关键组件和类。其中最重要的是LauncherActivity、PackageManager、AppWidgetManager和DesktopPane。 LauncherActivity是应用程序启动的入口点。它负责显示主屏幕和响应用户的触摸事件。在LauncherActivity中,使用了ViewPager来创建多个屏幕来容纳应用程序和小部件。 PackageManager是应用程序的管理器。通过PackageManager,Launcher可以获取系统中安装的应用程序信息、启动应用程序和监听应用程序的安装、卸载等事件。 AppWidgetManager用于管理应用程序的小部件。Launcher通过AppWidgetManager注册、更新和删除小部件。它还负责接收小部件的更新事件。 DesktopPane是主屏幕的容器。它使用GridLayout将应用程序和小部件布局在主屏幕上。DesktopPane还处理用户在主屏幕上的拖放操作,允许用户重新排序应用程序和小部件。 在源码解析过程中,还需要了解Android应用程序交互的一些核心概念,如Intent、Broadcast和Service等。Intent用于在组件之间传递消息,Broadcast用于传递系统事件,Service用于在后台执行任务。 在分析Launcher源码时,还需要关注性能优化和用户体验。例如,使用异步加载和缓存来提高应用程序和小部件的加载速度,使用动画效果来增强界面的流畅性。 综上所述,Android Launcher源码解析涉及多个组件和类,需要了解Android应用程序交互的核心概念,同时需要关注性能优化和用户体验。这个过程可以帮助开发者深入理解和定制Android系统的启动器。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值