问题背景
客户在低配置机器上,原生的三方应用界面上滑home动画负载太重,动画效果卡顿。
希望去掉上滑跟手效果、修改上滑回home动画为最简单的透明度和缩放。
中介绍了一些手势的知识
之前有关于这部分的简单逻辑 参考第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 < mmotionpausemindisplacement
|| islikelytostartnewtask);
mmotionpausedetector.addposition(ev);
minteractionhandler.setislikelytostartnewtask(islikelytostartnewtask);
}
}
break;
}
1.4、action_up
case action_cancel:
case action_up: {
if (debug_failed_quickswitch && !mpassedwindowmoveslop) {
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 < 0 ? direction.up : direction.down;
} else {
mlogdirection = velocity.x < 0 ? direction.left : direction.right;
}
mdownpos = downpos;
//手势处理方法
handlenormalgestureend(endvelocity, isfling, velocity, false /* iscancel */);
}
2.1、baseswipeuphandlerv2.handlenormalgestureend
private void handlenormalgestureend(float endvelocity, boolean isfling, pointf velocity,
boolean iscancel) {
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版本上滑处理会有些许差异,参考的时候需要自行研究一下
发表评论