当前位置: 代码网 > it编程>App开发>Android > Android R 11.x quickstep 手势导航架构和详细实现

Android R 11.x quickstep 手势导航架构和详细实现

2024年08月02日 Android 我要评论
android 11.x quickstep 一文入门到精通

1. recent架构变更的技术背景

1.1 11.x quickstep架构图

2. 底部上滑手势的具体实现

2.1 触摸事件(手势事件 systemui -> launcher)注册发起流程

2.2 上滑手势起始区域判断

2.3 手势消费者选择&创建(区分不同场景的手势处理)

2.4 桌面(+quickstep)相关手势控制器选择&创建

2.4.1 上滑手势_控制器

2.4.2 卡片手势_控制器

2.5 手势消费者与控制器的映射流程

2.5.1 input consumer 选择流程

2.5.2 touch controllers 选择&拦截流程

3 两种桌面多任务架构实现

1. 架构变更的技术背景:

多任务模块&底部上滑手势模块 systemui ->launcher3_quickstep的设计原因:

a. 底部上滑手势的跟手效果(home + recent):

为了用户交互的动画效果手势中的home和menu不再是利用注入按键来实现,而是直接放在lanucher3(+overview)中实现,返回桌面手势和启动最近任务手势出现后,会在lanucher中直接启动对应的最近任务界面,从而使得手势交互更加流畅可以取消。

b. 侧滑返回手势:保持不变(back):

返回键还是沿用了虚拟按键的原理,通过注入keycode_back来实现,只不过时操作方式不同而已。

c. 手势判断:

手势的设计并不需要判断用户是否按下后向上滑动或者左右滑动,而是当我们按下处于这块区域时,此处的窗口就得到了事件从而跟随手指改变,并根据最后抬手的状态做出最终的处理。

1.1. 11.x quickstep架构图:备注:systemui <-> launcher.quickstep 流程概述:

--step1: sytstemui 发起bind launcher touchinteractionservice:

overviewproxyservice.internalconnecttocurrentuser()

--step2: systemui service connected后,获得操作launcher的代理对象moverviewproxy:--moverviewproxy 是launcher 在systemui的对象。

moverviewserviceconnection.onserviceconnected()

moverviewproxy = ioverviewproxy.stub.asinterface(service);

--step3: systemui 把自身操作对象msysuiproxy,回传给launcher:

//--misystemuiproxy就是systemui在lanucher的对象。

params.putbinder(key_extra_sysui_proxy, msysuiproxy.asbinder());

moverviewproxy.oninitialize(params);

--step4:桌面侧:获取到systemui的代理操作对象isystemuiproxy,msysuiproxy就是systemui在lanucher的对象:

systemuiproxy.instance.get(touchinteractionservice.this).setproxy(proxy);

2. 底部上滑手势的具体实现:

systemui部分:略。。。同10.x 流程

launcher部分

com.android.quickstep.touchinteractionservice

在lanucher中action为android.intent.action.quickstep_service的服务是touchinteractionservice,这个服务也设置了属性android:directbootaware="true"保证该服务的启动。

2.1 触摸事件(手势事件 systemui -> launcher)流程:

touchinteractionservice.this.initinputmonitor();

--在touchinteractionservice.oninitialize中初始化并注册了手势窗口的通道swipe-up。保证了事件能够传递给lanucher,在此处要注意android原生的系统中,手势区域是非透明的,因此此区域内触摸都将会被认为是手势。

2.2 上滑手势起始区域判断:

touchinteractionservice.oninputevent() 中

mrotationtouchhelper.isinswipeuptouchregion()

--在lanucher的方法中,当第一个手指的动作是down的时候,判断这个点是否在mswipesharedstate的矩形区域中

2.3 手势消费者选择&创建(区分不同场景的手势处理)

launcher3: app\quickstep\recents_ui_overrides\src\com\android\quickstep\inputconsumers

-->touchinteractionservice.oninputevent()

->touchinteractionservice.newconsumer()

--此处详细分析手势所在逻辑的位置newconsumer,在newconsumer方法中除了创建特殊consumer的逻辑外,我们主要看newbaseconsumer,手势真正的消费者在此处。

列举如下:

accessibilityinputconsumer: //场景:低概率场景:无障碍场景:

touch consumer for two finger swipe actions for accessibility actions

assistantinputconsumer //场景? :低概率场景:

//mdevicestate.cantriggerassistantaction()

touch consumer for handling events to launch assistant from launcher

devicelockedinputconsumer: //场景举例:锁屏进入相机 手势上滑场景?

//mdevicestate.iskeyguardshowingoccluded():锁屏相机上滑

a dummy input consumer used when the device is still locked, e.g. from secure camera.

otheractivityinputconsumer: //重点场景:非桌面的其他应用页,手势上滑场景?

input consumer for handling events originating from an activity other than launcher

overscrollinputconsumer://场景?:低概率场景:overscrollplugin

input consumer for handling events to pass to an {@code overscrollplugin}.

overviewinputconsumer: //重点场景:桌面|多任务页面,上滑手势场景?

input consumer for handling touch on the recents/launcher activity.

overviewwithoutfocusinputconsumer: //场景:桌面launcher activity resumed但未获得焦点的场景

using a separate inputconsumer when launcher is resumed but not focused.

when launcher is not focused and we try to dispatch events to launcher, it can lead to a inconsistent state. for eg, navbartouchcontroller was trying to take launcher from normal to normal state causing the endcallback to be called immediately, which in turn didn't clear swipedetetor state.

resetgestureinputconsumer: //场景:重置各类pending手势

a no_op input consumer which also resets any pending gesture.

bypass systemstate check when using shared state

system state can change using the interaction, for eg: an app can enter immersive mode in the middle of quickswitch. ignore such changes to prevent system gestures getting blocked by an app

fixing nullpointer in device locked consumer construction when user is not locked yet creating a fallback resetgesture input consumer, which cancels any pending transition in case we missed to cancel it

screenpinnedinputconsumer: //场景:低概率:固定屏幕场景:

//mdevicestate.isscreenpinningactive()

an input consumer that detects swipe up and hold to exit screen pinning mode.

sysuioverlayinputconsumer: //场景:systemui下拉展开 or 弹框window场景?

//mdevicestate.isbubblesexpanded() or mdevicestate.isglobalactionsshowing()

input consumer used when a fullscreen system ui overlay is showing (such as the expanded bubbles ui).

this responds to swipes up by sending a closesystemdialogs broadcast (causing overlays to close) rather than closing the app behind the overlay and sending the user all the way home.

2.4 桌面(+quickstep)相关手势控制器的选择与创建

launcher3: app\quickstep\recents_ui_overrides\src\com\android\launcher3\uioverrides\touchcontrollers

a. 当前场景,动态创建controller list:

->quicksteplauncher.createtouchcontrollers()

b. controller list遍历选择的责任链模式:--对比参照语音助手的语义parse解析器机制

->basedraglayer.onintercepttouchevent() //touch ev拦截?

->basedraglayer.findactivecontroller()

->basedraglayer.findcontrollertohandletouch() //遍历controller list

->controller.oncontrollerintercepttouchevent(ev) //判断特定item controller是否可以拦截touch ev 则选中

2.4.1 上滑手势_控制器

--如何区分不同场景&不同控制器:参照:quicksteplauncher.createtouchcontrollers()

备注如下:

详细说明:

场景1: 非虚拟按键_公共部分:

navbartohometouchcontroller //场景:

handles swiping up on the nav bar to go home from launcher, e.g. overview or all apps.

nobuttonquickswitchtouchcontroller //场景:

handles quick switching to a recent task from the home screen.

to give as much flexibility to the user as possible, also handles swipe up and hold to go to overview and swiping back home.

场景1.1: 非虚拟按键_(enable_overview_actions)_true:

flingandholdtouchcontroller //底部上滑_悬停 到多任务?

touch controller which handles swipe and hold to go to overview

场景1.2: 非虚拟按键_(enable_overview_actions)_false:

nobuttonnavbartooverviewtouchcontroller extends flingandholdtouchcontroller //底部上滑(a. 桌面进入多任务 b. 多任务返回桌面 )

touch controller which handles swipe and hold from the nav bar to go to overview.

swiping above the nav bar falls back to go to all apps.

swiping from the nav bar without holding goes to thefirst home screen instead of to overview.

场景2:虚拟按键场景:

场景2.1: 虚拟按键_竖向导航栏场景(isverticalbarlayout()):

overviewtoallappstouchcontroller //场景:多任务->所有应用页,暂不分析(os无此场景)

touch controller from going from overview to all_apps. this is used in landscape mode. it is also used in portrait mode for the fallback recents.

//如含上滑手势场景时支持此项(mode.hasgestures):

transposedquickswitchtouchcontroller extends quickswitchtouchcontroller

handles quick switching to a recent task from the home screen.

场景2.2: 虚拟按键_横向导航栏场景(!isverticalbarlayout()):

portraitstatestouchcontroller:

touch controller for handling various state transitions in portrait ui.

--备注:portraitoverviewstatetouchhelper //用于桌面portraitstatestouchcontroller ,暂不分析

helper class for {@link portraitstatestouchcontroller /*launcher3内功能*/} that determines swipeable regions and animations on the overview state

//如含上滑手势场景时支持此项(mode.hasgestures):

quickswitchtouchcontroller

handles quick switching to a recent task from the home screen.

2.4.2 卡片手势_控制器

recentstaskcontroller extends taskviewtouchcontroller //场景:多任务的卡片滑动(上下滑动移除?左右滑动切换卡片)

touch controller for handling task view card swipes

2.5 手势消费者与控制器的对应关系

2.5.1 input consumer 选择流程:

->touchinteractionservice.oninputevent() --quickstep 主动注册:监听全屏touch events

-> input events

-> input consumer(selected,依据systemui flag):touchinteractionservice.newconsumer()

-> controller(selected:依据mode):basedraglayer.findcontrollertohandletouch()

-> recent等

场景举例:

--overviewinputconsumer

2.5.2 touch controllers 选择&拦截流程:

创建手势 controller list:

->quicksteplauncher.createtouchcontrollers()

触摸事件controller拦截流程:

->basedraglayer.onintercepttouchevent() //touch ev拦截?

->basedraglayer.findactivecontroller()

->basedraglayer.findcontrollertohandletouch() //遍历controller list 核心机制!!!

->遍历controller 查找匹配控制器后,结束匹配流程:

->controller.oncontrollerintercepttouchevent(ev) //判断特定item controller是否可以拦截touch ev 则选中

场景举例:

--navbartohometouchcontroller.oncontrollerintercepttouchevent() ->canintercepttouch()

--abstractstatechangetouchcontroller.oncontrollerintercepttouchevent()

-->nobuttonnavbartooverviewtouchcontroller.canintercepttouch()

or:

-->quickswitchtouchcontroller.canintercepttouch()

3 两种桌面多任务的架构实现:

3.1 默认桌面(即含quickstep的原生桌面:多任务内嵌页面):

launcheractivityinterface extends baseactivityinterface

多任务页面(嵌套在launcher中):

quicksteplauncher extends basequicksteplauncher extends launcher 中

+launcherrecentsview extends recentsview

3.2 非默认桌面(三方桌面为默认桌面场景,多任务单独页面):

fallbackactivityinterface extends baseactivityinterface

多任务单独页面:

recentsactivity

+fallbackrecentsview extends recentsview

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com