本篇:Launcher功能入口
下篇:launcher功能入口(二)
下篇:launcher功能入口(三)
ItemClickHandler.java
public static final OnClickListener INSTANCE = ItemClickHandler::onClick;
src/com/android/launcher3/touch/ItemLongClickListener.java
public static final OnLongClickListener INSTANCE_WORKSPACE =
ItemLongClickListener::onWorkspaceItemLongClick;
src/com/android/launcher3/touch/ItemLongClickListener.java
public static final OnLongClickListener INSTANCE_ALL_APPS =
ItemLongClickListener::onAllAppsItemLongClick;
Folder.onLongClick
BaseWidgetSheet.onLongClick
AddItemActivity.onLongClick
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);
}
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);
}
packages/apps/Launcher3/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
prepareRecentsUI中处理
quickstep/src/com/android/quickstep/views/TaskView.java
private boolean showTaskMenu()
quickstep/src/com/android/quickstep/views/TaskView.java
setOnClickListener(this::onClick);
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;
}
分屏显示判断
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);
}
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的动画。
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
参考文章: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
还有什么想了解的欢迎留言,我后续补充