Android Launcher负一屏实现方案@TOC
-
整体方案: 利用Google Feed屏方案, 基于Google定义的ILauncherOverlay和 ILauncherOverlayCallback两个接口,通过AIDL通信方式实现。 Launcher作为客户端, 负一屏是独立的应用作为服务端。 Launcher将其Activity的window属性和滑动信息传递给应用端。应用端根据Launcher窗口属性创建一个相同属性的窗口,以WindowManager.addView方式添加此浮动窗口,并根据Launcher传递过来的滑动信息,用translationX改变负一屏View的位置来实现窗口的顺势进入显示区和滑出显示区的效果。 -
方案有缺点: 缺点:实现复杂,需要应用自己实现View显示滑动等处理。 优点:与Launcher解构,虽然负一屏的显示依赖launcher的activity的token,但运行在独立的进程中,不影响Launcher性能。 -
具体实现过程: 客户端Launcher的实现: 1)客户端实现ILauncherOverlayCallback接口。
- 接口函数overlayScrollChanged由服务端回调,参数为服务端窗口的移动进度,launcher根据此值让workspace做相应的translationX,达到和应用负一屏窗口联动的功能。
- 接口函数overlayStatusChanged由服务端回调,通知Launcher端,服务端的Overlay的状态,1-表示状态已打开, 0-表示已关闭。状态打开时, Launcher要对应处理overlayScrollChanged的滑动过程。
2)Launcher在onAttachedToWindow的时候,会通过windowAttached(WindowManager.LayoutParams attrs, ILauncherOverlayCallback callbacks, int options)方法,将Launcher的Activity的window属性,和launcher实例化出来的ILauncherOverlayCallback.Stub回调传给服务端。 Sample code:
WindowManager.LayoutParams lp = getWindow().getAttributes();
windowAttached(lp, loverlayCb, 0);
3)用户在屏幕的滑动操作, 调用startScroll(), onScroll(float progress), endScroll()来通知服务端。 4)Launcher这边打开关闭负一屏,用openOverlay(),closeOverlay()来通知服务端。 5)Launcher 在onResume(), onPause()时通知服务端, 以保证Launcher和服务端同步生命周期。
服务端App的实现: 1)应用端创建一个服务,实现ILauncherOverlay接口。接口功能主要实现以下函数: 2)在客户端调用服务端的windowAttached的时候,创建一个Window, 将客户端的LayoutParams中的部分属性赋值给服务端的window。 到此,就可以在launcher的上层显示一个负一屏的window了,如果不给负一屏容器设置一个translationX的话,默认该window是盖在launcher上的,可以通过设置translationX的默认值将其默认显示在屏幕以外。 3)服务端接收到onScroll(float progress)传过来的scroll值,来改变负一屏window中的view的translationX,来达到负一屏滑动的效果。 4)服务端接收到客户端的closeOverlay和openOverlay时,也要对应处理负一屏的显示与隐藏。比如Launcher端执行onNewIntent()时,会调用closeOverlay来进行Launcher主页面的显示,并隐藏负一屏。 5)服务端window上的View需要处理onTouchEvent事件,判断滑动距离,计算滑动进度,要通过ILauncherOverlayCallback接口将滑动进度回调给Launcher,以达到Launcher与负一屏联动效果。 比如,如果是以dialog形式创建的窗口,需要自定义类继承Dialog,重写onTouchEvent函数, 来处理滑动事件过程。
|