Launcher三方应用界面手势

您所在的位置:网站首页 realme桌面上滑进入浏览器 Launcher三方应用界面手势

Launcher三方应用界面手势

2023-09-23 19:52| 来源: 网络整理| 查看: 265

问题背景

客户在低配置机器上,原生的三方应用界面上滑home动画负载太重,动画效果卡顿。 希望去掉上滑跟手效果、修改上滑回home动画为最简单的透明度和缩放。

https://blog.csdn.net/a396604593/article/details/129733464中介绍了一些手势的知识

之前有关于这部分的简单逻辑 https://blog.csdn.net/a396604593/article/details/123487805参考第11条 以此为前提,进一步对launcher手势部分加深了一点了解,供各位参考

实现方案

1、屏蔽三方应用界面跟手效果 只屏蔽上下跟手,左右快速切换应用跟手保留 2、上滑回home动画修改,recent和其它动画保留,home动画时间调整

相关流程

本篇文章基于Android R,最新的代码大同小异,可以参考流程。 主要介绍Launcher的三方应用界面上滑、左右滑动切换Task功能。调用逻辑和一些控制判断

1、OtherActivityInputConsumer.onMotionEvent

相关的流程主要在DOWN、MOVE、UP中

1.0、 ACTION_DOWN case ACTION_DOWN: { Object traceToken = TraceHelper.INSTANCE.beginSection(DOWN_EVT, FLAG_CHECK_FOR_RACE_CONDITIONS); mActivePointerId = ev.getPointerId(0); mDownPos.set(ev.getX(), ev.getY());//记录坐标 mLastPos.set(mDownPos);//记录坐标 // Start the window animation on down to give more time for launcher to draw if the // user didn't start the gesture over the back button if (!mIsDeferredDownTarget) { //启动触摸跟手动画前期工作 startTouchTrackingForWindowAnimation(ev.getEventTime()); } TraceHelper.INSTANCE.endSection(traceToken); break; } 1.1、startTouchTrackingForWindowAnimation中 private void startTouchTrackingForWindowAnimation(long touchTimeMs) { ActiveGestureLog.INSTANCE.addLog("startRecentsAnimation"); mInteractionHandler = mHandlerFactory.newHandler(mGestureState, touchTimeMs, mTaskAnimationManager.isRecentsAnimationRunning());//上滑handler初始化 mInteractionHandler.setGestureEndCallback(this::onInteractionGestureFinished); //初始化运动检测器,用于判断滑动是否停顿 mMotionPauseDetector.setOnMotionPauseListener(mInteractionHandler::onMotionPauseChanged); Intent intent = new Intent(mInteractionHandler.getLaunchIntent()); mInteractionHandler.initWhenReady(intent);//上滑handler初始化 if (mTaskAnimationManager.isRecentsAnimationRunning()) { mActiveCallbacks = mTaskAnimationManager.continueRecentsAnimation(mGestureState); mActiveCallbacks.addListener(mInteractionHandler); mTaskAnimationManager.notifyRecentsAnimationState(mInteractionHandler); notifyGestureStarted(true /*isLikelyToStartNewTask*/); } else { intent.putExtra(INTENT_EXTRA_LOG_TRACE_ID, mGestureState.getGestureId()); //启动home动画的前提 mActiveCallbacks = mTaskAnimationManager.startRecentsAnimation(mGestureState, intent, mInteractionHandler); } }

startRecentsAnimation,最终走到startRecentsActivity。达到的效果就是launcher生命周期走到onStart,launcher启动了但是没有完全进入launcher。

1.3、ACTION_MOVE case ACTION_MOVE: { int pointerIndex = ev.findPointerIndex(mActivePointerId); if (pointerIndex == INVALID_POINTER_ID) { break; } mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));//更新当前点的坐标 float displacement = getDisplacement(ev);//计算偏移 float displacementX = mLastPos.x - mDownPos.x;//x偏移 float displacementY = mLastPos.y - mDownPos.y;//Y偏移 if (!mPassedWindowMoveSlop) { if (!mIsDeferredDownTarget) { // Normal gesture, ensure we pass the drag slop before we start tracking // the gesture if (Math.abs(displacement) > mTouchSlop) {//如果移动大于mTouchSlop,认为开始滑动 mPassedWindowMoveSlop = true; mStartDisplacement = Math.min(displacement, -mTouchSlop); } } } float horizontalDist = Math.abs(displacementX);//x方向移动的距离 float upDist = -displacement;//上滑距离 boolean passedSlop = squaredHypot(displacementX, displacementY) >= mSquaredTouchSlop; if (!mPassedSlopOnThisGesture && passedSlop) { mPassedSlopOnThisGesture = true; } // Until passing slop, we don't know what direction we're going, so assume // we're quick switching to avoid translating recents away when continuing // the gesture (in which case mPassedPilferInputSlop starts as true). boolean haveNotPassedSlopOnContinuedGesture = !mPassedSlopOnThisGesture && mPassedPilferInputSlop; boolean isLikelyToStartNewTask = haveNotPassedSlopOnContinuedGesture || horizontalDist > upDist;//区分是左右滑动还是上下滑动 if (!mPassedPilferInputSlop) { if (passedSlop) { if (mDisableHorizontalSwipe && Math.abs(displacementX) > Math.abs(displacementY)) { // Horizontal gesture is not allowed in this region forceCancelGesture(ev); break; } mPassedPilferInputSlop = true; if (mIsDeferredDownTarget) { // Deferred gesture, start the animation and gesture tracking once // we pass the actual touch slop startTouchTrackingForWindowAnimation(ev.getEventTime()); } if (!mPassedWindowMoveSlop) { mPassedWindowMoveSlop = true; mStartDisplacement = Math.min(displacement, -mTouchSlop); } notifyGestureStarted(isLikelyToStartNewTask); } } if (mInteractionHandler != null) { if (mPassedWindowMoveSlop) { // Move //上下滑动更新移动位置 mInteractionHandler.updateDisplacement(displacement - mStartDisplacement); } if (mDeviceState.isFullyGesturalNavMode()) { mMotionPauseDetector.setDisallowPause(upDist float displacementX = mLastPos.x - mDownPos.x; float displacementY = mLastPos.y - mDownPos.y; Log.d("Quickswitch", "mPassedWindowMoveSlop=false" + " disp=" + squaredHypot(displacementX, displacementY) + " slop=" + mSquaredTouchSlop); } //up或者cancel之后,处理后续界面走向 finishTouchTracking(ev); 1.5、finishTouchTracking

松手后进入home或者recent以及动画处理 后续我们只关注home的相关逻辑和动画,其它的逻辑暂时忽略

private void finishTouchTracking(MotionEvent ev) { ... if (mPassedWindowMoveSlop && mInteractionHandler != null) { if (ev.getActionMasked() == ACTION_CANCEL) { mInteractionHandler.onGestureCancelled(); } else { //速度计算 mVelocityTracker.computeCurrentVelocity(1000, ViewConfiguration.get(this).getScaledMaximumFlingVelocity()); float velocityX = mVelocityTracker.getXVelocity(mActivePointerId); float velocityY = mVelocityTracker.getYVelocity(mActivePointerId); float velocity = mNavBarPosition.isRightEdge() ? velocityX : mNavBarPosition.isLeftEdge() ? -velocityX : velocityY; //更新一次上滑 mInteractionHandler.updateDisplacement(getDisplacement(ev) - mStartDisplacement); //下发手势end mInteractionHandler.onGestureEnded(velocity, new PointF(velocityX, velocityY), mDownPos); ... } 2、BaseSwipeUpHandlerV2.onGestureEnded public void onGestureEnded(float endVelocity, PointF velocity, PointF downPos) { float flingThreshold = mContext.getResources() .getDimension(R.dimen.quickstep_fling_threshold_velocity); //根据结束手势时的速度判断是否在猛扔 boolean isFling = mGestureStarted && Math.abs(endVelocity) > flingThreshold; mStateCallback.setStateOnUiThread(STATE_GESTURE_COMPLETED); mLogAction = isFling ? Touch.FLING : Touch.SWIPE; boolean isVelocityVertical = Math.abs(velocity.y) > Math.abs(velocity.x); if (isVelocityVertical) { mLogDirection = velocity.y PointF velocityPxPerMs = new PointF(velocity.x / 1000, velocity.y / 1000); long duration = MAX_SWIPE_DURATION; float currentShift = mCurrentShift.value; //计算endTarget,也就是要去向home还是recent final GestureEndTarget endTarget = calculateEndTarget(velocity, endVelocity, isFling, isCancel); ... if (endTarget == HOME) { setShelfState(ShelfAnimState.CANCEL, LINEAR, 0); duration = Math.max(MIN_OVERSHOOT_DURATION, duration); } else if (endTarget == RECENTS) { ... } ... animateToProgress(startShift, endShift, duration, interpolator, endTarget, velocityPxPerMs); } 2.2、BaseSwipeUpHandlerV2.animateToProgress @UiThread private void animateToProgress(float start, float end, long duration, Interpolator interpolator, GestureEndTarget target, PointF velocityPxPerMs) { runOnRecentsAnimationStart(() -> animateToProgressInternal(start, end, duration, interpolator, target, velocityPxPerMs)); } 2.3、BaseSwipeUpHandlerV2.animateToProgressInternal @UiThread private void animateToProgressInternal(float start, float end, long duration, Interpolator interpolator, GestureEndTarget target, PointF velocityPxPerMs) { ... if (mGestureState.getEndTarget() == HOME) { //创建动画 HomeAnimationFactory homeAnimFactory = createHomeAnimationFactory(duration); //弹簧动画 RectFSpringAnim windowAnim = createWindowAnimationToHome(start, homeAnimFactory); windowAnim.addAnimatorListener(new AnimationSuccessListener() { @Override public void onAnimationSuccess(Animator animator) { if (mRecentsAnimationController == null) { // If the recents animation is interrupted, we still end the running // animation (not canceled) so this is still called. In that case, we can // skip doing any future work here for the current gesture. return; } // Finalize the state and notify of the change mGestureState.setState(STATE_END_TARGET_ANIMATION_FINISHED); } }); getOrientationHandler().adjustFloatingIconStartVelocity(velocityPxPerMs); //动画启动 windowAnim.start(mContext, velocityPxPerMs); homeAnimFactory.playAtomicAnimation(velocityPxPerMs.y); mRunningWindowAnim = RunningWindowAnim.wrap(windowAnim); mLauncherTransitionController = null; } else { ... } ... } 2.4、createWindowAnimationToHome、windowAnim.start

createWindowAnimationToHome创建具体的变化动画,要修改松手动画内容就得改里面的动画效果逻辑。 windowAnim.start中动画启动,这里用的是SpringAnimation,并非Android原生的三种动画(补间动画、属性动画、帧动画)

SpringAnimation:

没有动画时间属性------setStiffness、setDampingRatio、setStartVelocity根据刚值、阻尼系数、起始速度来决定动画时长。具体的可以百度一下SpringAnimation动画。

没有动画起始值和目标值------需要在update中计算每一帧界面,达到想要的效果。

3、跟手在哪里绘制

3.1、AndroidQ上 3.1.1、上下滑动跟手的处理:

OtherActivityInputConsumer#onMotionEvent ---mInteractionHandler.updateDisplacement ---WindowTransformSwipeHandler#updateDisplacement ---mCurrentShift.updateValue ---private final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift); ---updateFinalShift ---

updateFinalShift中

private void updateFinalShift() { float shift = mCurrentShift.value; SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController(); if (controller != null) { //获取偏移量---对应手指左右滚动时,recent界面的ScrollX值 float offsetX = mRecentsView == null ? 0 : mRecentsView.getScrollOffset(); float offsetScale = getTaskCurveScaleForOffsetX(offsetX, mClipAnimationHelper.getTargetRect().width()); //设置进度setProgress 这个表示上滑的进度,三方界面是0,上滑到recent时是1 //偏移setOffsetX X方向的滚动 //offsetScale注意,这个值不是task的缩放值 mTransformParams.setProgress(shift).setOffsetX(offsetX).setOffsetScale(offsetScale); //更新界面 mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet, mTransformParams); updateSysUiFlags(shift); } ... }

最终调用到ClipAnimationHelper.java的applyTransform方法

public RectF applyTransform(RemoteAnimationTargetSet targetSet, TransformParams params, boolean launcherOnTop) { // 根据progress缩放taskview的位置和大小 float progress = params.progress; if (params.currentRect == null) { RectF currentRect; mTmpRectF.set(mTargetRect); Utilities.scaleRectFAboutCenter(mTmpRectF, params.offsetScale); // evaluate方法会根据progress整体变换rectF坐标和大小 //计算当前显示的task大小,从这里可以看出task的大小是根据progress计算的 currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTmpRectF); Log.d("applyTransform","currentRect: "+currentRect+" mSourceRect: "+mSourceRect+" mTmpRectF: "+mTmpRectF); //设置task偏移量 currentRect.offset(params.offsetX, 0); ... } ... //最终调用这里更新界面实现缩放和位移的效果 applySurfaceParams(params.syncTransactionApplier, surfaceParams); }

如果要去掉上下跟手的效果,注释掉mInteractionHandler.updateDisplacement(displacement - mStartDisplacement); ,这里只是注释掉跟手效果的界面,手势判断还是有的,上滑up之后home,滑动停顿up之后recent。

3.1.2、左右跟手的处理:

OtherActivityInputConsumer.onMotionEvent ---mRecentsViewDispatcher.dispatchEvent(ev) ------mConsumer.accept(event) ---RecentsView.getEventDispatcher ------super::onTouchEvent ------PagedView.onTouchEvent ------scrollBy((int) deltaX, 0)

WindowTransformSwipeHandler.java中recentView设置滚动监听

mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> { if (mGestureEndTarget != HOME) { updateFinalShift(); } });

这里就殊途同归了,也是走到updateFinalShift更新界面。

要想去掉左右跟手,注释掉 OtherActivityInputConsumer中关于mRecentsViewDispatcher的调用即可。 左右滑动底部快速切换Task整个功能也会没有。

private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher(); mRecentsViewDispatcher.setConsumer( mRecentsViewDispatcher.dispatchEvent(ev);

整个ev没有分发给PagedView.onTouchEvent进行界面滚动,松手后进入上一页还是下一页也无法计算得知。

注释掉mRecentsViewDispatcher并不会影响HOME、RECENT、NEW_TASK、LAST_TASK的计算,但是onTouchEvent没有调用到PagedView去,导致没有后续的松手切页。

—一些猜想,我们是否可以根据结束时的LAST_TASK、X的速度值,计算出左右切页,然后屏蔽掉左右跟手达到保留效果的目的。

从目前来看,三方界面左右滑动和up之后的切页,和桌面切页的逻辑是一样的,都是走PagedView.onTouchEvent里面。

如果只去掉跟手效果,保留功能,修改updateFinalShift中的offsetX = 0;就可以了

private void updateFinalShift() { float shift = mCurrentShift.value; SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController(); if (controller != null) { float offsetX = 0;//mRecentsView == null ? 0 : mRecentsView.getScrollOffset(); float offsetScale = getTaskCurveScaleForOffsetX(offsetX, mClipAnimationHelper.getTargetRect().width()); mTransformParams.setProgress(shift).setOffsetX(offsetX).setOffsetScale(offsetScale); mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet, mTransformParams); updateSysUiFlags(shift); } ... }

后来验证这种方式有bug,只是注释掉了当前task的左右跟手,其它task还是会跟手动。 目前无法只去掉所有跟手效果而不影响功能。

3.2、AndroidR上 3.1.1、上下滑动跟手的处理: 在AndroidR上,和AndroidQ大同小异,只是代码结构发生了变化,类的名字变了。 上下滑动跟手事件传递:

OtherActivityInputConsumer#onMotionEvent ---mInteractionHandler.updateDisplacement ---SwipeUpAnimationLogic#updateDisplacement---mCurrentShift.updateValue ---private final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift); ---BaseSwipeUpHandlerV2.updateFinalShift ---

BaseSwipeUpHandlerV2.updateFinalShift中

@Override public void updateFinalShift() { ... updateSysUiFlags(mCurrentShift.value); //更新当前task的缩放和位移 applyWindowTransform(); //更新其它task的缩放 updateLauncherTransitionProgress(); }

BaseSwipeUpHandler.applyWindowTransform

/** * Applies the transform on the recents animation */ protected void applyWindowTransform() { //更新window动画的缩放 if (mWindowTransitionController != null) { float progress = mCurrentShift.value / mDragLengthFactor; mWindowTransitionController.setPlayFraction(progress); } if (mRecentsAnimationTargets != null) { //设置TaskViewSimulator的左右位移 if (mRecentsViewScrollLinked) { mTaskViewSimulator.setScroll(mRecentsView.getScrollOffset()); } //TaskViewSimulator是AndroidR上新增的类,用来处理taskview缩放和位移动画相关逻辑 //方法内部具体计算和更新缩放+位移 mTaskViewSimulator.apply(mTransformParams); } }

TaskViewSimulator.apply

public void apply(TransformParams params) { if (mDp == null || mThumbnailPosition.isEmpty()) { return; } if (!mLayoutValid) { mLayoutValid = true; getFullScreenScale(); mThumbnailData.rotation = mOrientationState.getDisplayRotation(); mPositionHelper.updateThumbnailMatrix( mThumbnailPosition, mThumbnailData, mTaskRect.width(), mTaskRect.height(), mDp, mOrientationState.getRecentsActivityRotation()); mPositionHelper.getMatrix().invert(mInversePositionMatrix); PagedOrientationHandler poh = mOrientationState.getOrientationHandler(); mScrollState.halfPageSize = poh.getPrimaryValue(mTaskRect.width(), mTaskRect.height()) / 2; mScrollState.halfScreenSize = poh.getPrimaryValue(mDp.widthPx, mDp.heightPx) / 2; mScrollValid = false; } if (!mScrollValid) { mScrollValid = true; int start = mOrientationState.getOrientationHandler() .getPrimaryValue(mTaskRect.left, mTaskRect.top); mScrollState.screenCenter = start + mScrollState.scroll + mScrollState.halfPageSize; mScrollState.updateInterpolation(start, mPageSpacing); mCurveScale = TaskView.getCurveScaleForInterpolation(mScrollState.linearInterpolation); } float progress = Utilities.boundToRange(fullScreenProgress.value, 0, 1); mCurrentFullscreenParams.setProgress( progress, recentsViewScale.value, mTaskRect.width(), mDp, mPositionHelper); // Apply thumbnail matrix RectF insets = mCurrentFullscreenParams.mCurrentDrawnInsets; float scale = mCurrentFullscreenParams.mScale; float taskWidth = mTaskRect.width(); float taskHeight = mTaskRect.height(); mMatrix.set(mPositionHelper.getMatrix()); mMatrix.postTranslate(insets.left, insets.top); mMatrix.postScale(scale, scale); // Apply TaskView matrix: translate, scale, scroll mMatrix.postTranslate(mTaskRect.left, mTaskRect.top); mMatrix.postScale(mCurveScale, mCurveScale, taskWidth / 2, taskHeight / 2); mOrientationState.getOrientationHandler().set( mMatrix, MATRIX_POST_TRANSLATE, mScrollState.scroll); // Apply recensView matrix mMatrix.postScale(recentsViewScale.value, recentsViewScale.value, mPivot.x, mPivot.y); applyWindowToHomeRotation(mMatrix); Log.d("apply","progress: "+progress+" mTaskRect.left: "+mTaskRect.left+" mTaskRect.top: "+mTaskRect.top+" mCurveScale: "+mCurveScale+" mScrollState.scroll: "+mScrollState.scroll); // Crop rect is the inverse of thumbnail matrix mTempRectF.set(-insets.left, -insets.top, taskWidth + insets.right, taskHeight + insets.bottom); mInversePositionMatrix.mapRect(mTempRectF); mTempRectF.roundOut(mTmpCropRect); params.applySurfaceParams(params.createSurfaceParams(this)); }

这里添加log发现: 1、progress控制进度,三方应用上滑到recent时,progress 1 — 0 2、mScrollState.scroll控制左右位移,所有滑动时跟手变化。 3、mCurveScale并非上滑时,taskView缩放,这个值一直是1 4、recentsViewScale.value是task当前的缩放值,三方界面的时候最大----recent大小的时候是1—继续上滑会小于1。松手后会恢复到recent大小 1 的状态 上滑:1.19—1—0.5 松手:?—1

apply方法只控制当前三方应用的位移和缩放,其它Task的缩放和位移不受影响。 注释掉applyWindowTransform,上下左右手势都不跟手,当前三方页面全屏,无法直接观察其它task的移动情况。使用布局工具动态跟踪,发现其它task是在位移的。

TaskViewSimulator只是负责更新当前task控制动画效果。 具体怎么控制当前task和其它task区分,暂时没有头绪

如果要去掉上下跟手效果: 方案1:

com/android/quickstep/BaseActivityInterface.java protected void createBackgroundToOverviewAnim(ACTIVITY_TYPE activity, PendingAnimation pa) { // Scale down recents from being full screen to being in overview. RecentsView recentsView = activity.getOverviewPanel(); //注释掉其它task的缩放跟手 // pa.addFloat(recentsView, SCALE_PROPERTY, // recentsView.getMaxScaleForFullScreen(), 1, LINEAR); pa.addFloat(recentsView, FULLSCREEN_PROGRESS, 1, 0, LINEAR); } com/android/quickstep/util/TaskViewSimulator.java public void addAppToOverviewAnim(PendingAnimation pa, TimeInterpolator interpolator) { pa.addFloat(fullScreenProgress, AnimatedFloat.VALUE, 1, 0, interpolator); //注释掉当前task的缩放 //pa.addFloat(recentsViewScale, AnimatedFloat.VALUE, getFullScreenScale(), 1, interpolator); } public void apply(TransformParams params) { if (mDp == null || mThumbnailPosition.isEmpty()) { return; } //apply时给当前task缩放赋默认值 recentsViewScale.value = getFullScreenScale(); ... }

方案2

if (mPassedWindowMoveSlop) { // Move //mInteractionHandler.updateDisplacement(displacement - mStartDisplacement); }

3.1.2、左右跟手的处理: 和AndroidQ类似

OtherActivityInputConsumer.onMotionEvent ---mRecentsViewDispatcher.dispatchEvent(ev) ------mConsumer.accept(event) ---RecentsView.getEventDispatcher ------super::onTouchEvent ------PagedView.onTouchEvent ---mOrientationHandler.set(this, VIEW_SCROLL_BY, (int) delta); PagedView.java public void scrollBy(int x, int y) { mOrientationHandler.delegateScrollBy(this, getUnboundedScroll(), x, y); } PortraitPagedViewHandler.java public void delegateScrollBy(PagedView pagedView, int unboundedScroll, int x, int y) { pagedView.scrollTo(unboundedScroll + x, pagedView.getScrollY() + y); }

quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java 监听滚动事件更新,调用updateFinalShift和AndroidQ有点类似,最终也是在updateFinalShift中更新界面。

protected void linkRecentsViewScroll() { SurfaceTransactionApplier.create(mRecentsView, applier -> { mTransformParams.setSyncTransactionApplier(applier); runOnRecentsAnimationStart(() -> mRecentsAnimationTargets.addReleaseCheck(applier)); }); mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> { if (moveWindowWithRecentsScroll()) { updateFinalShift();//更新界面 } }); runOnRecentsAnimationStart(() -> mRecentsView.setRecentsAnimationTargets(mRecentsAnimationController, mRecentsAnimationTargets)); mRecentsViewScrollLinked = true; }

com/android/quickstep/BaseSwipeUpHandler.java

protected void applyWindowTransform() { if (mWindowTransitionController != null) { float progress = mCurrentShift.value / mDragLengthFactor; mWindowTransitionController.setPlayFraction(progress); } if (mRecentsAnimationTargets != null) { //这个注释掉只能去掉当前task的位移,上滑之后左右滑动,其它的task还是会左右滚动 // if (mRecentsViewScrollLinked) { // mTaskViewSimulator.setScroll(mRecentsView.getScrollOffset()); // } mTaskViewSimulator.apply(mTransformParams); } }

暂时没有办法只去掉其它task的位移跟手,而不影响Quickswitch功能。 怀疑Q上也没有,是不是当时调试漏掉了现象。。。后面再check一遍

要想去掉左右跟手,注释掉 OtherActivityInputConsumer中关于mRecentsViewDispatcher的调用即可。 左右滑动底部快速切换Task整个功能也会没有。

private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher(); mRecentsViewDispatcher.setConsumer( mRecentsViewDispatcher.dispatchEvent(ev);

3.3、AndroidS上

呼呼,累了,流程看的头晕眼花,S上的先不写了。。。后续有需求再跟吧

尾注

以上,三方界面上滑的跟手、左右滑动的跟手、松手之后的动画,介绍完毕。

新增的知识点:

1、launcher上滑和左右滑动整套流程简介 2、SpringAnimation动画 3、SyncRtSurfaceTransactionApplierCompat 更新界面

public void applySurfaceParams(SurfaceParams[] params) { if (mSyncTransactionApplier != null) { mSyncTransactionApplier.scheduleApply(params); } else { TransactionCompat t = new TransactionCompat(); for (SurfaceParams param : params) { SyncRtSurfaceTransactionApplierCompat.applyParams(t, param); } t.apply(); } }

4、mSyncTransactionApplier SurfaceTransactionApplier.create传入了recentView创建的。 这个之前没遇到过,不清楚具体的界面细节

SurfaceTransactionApplier.create(mRecentsView, applier -> { mTransformParams.setSyncTransactionApplier(applier); runOnRecentsAnimationStart(() -> mRecentsAnimationTargets.addReleaseCheck(applier)); });

5、不同的Android版本上滑处理会有些许差异,参考的时候需要自行研究一下



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3