fWX228941 / project

all by myself
1 stars 0 forks source link

小屏方案 #58

Open fWX228941 opened 6 months ago

fWX228941 commented 6 months ago

小屏Launcher设计方案 1 需求简要 需求主要支持以下功能,详细请看相关文档。 1)包含三个页面,页面可以切换 2)首页界面有状态栏显示,以及可以滑出通知或快捷设置面板 3)支持触摸按键各种操作 2 总体设计方案 1)整个Launcher使用一个LauncherActivity,利用ViewPager+Fragment实现三个页面显示以及切换。避免页面切换时,每次都创建各Fragment页面,使用setOffscreenPageLimit缓存这三个页面。 首页AppwidgetFragment主要用于加载BTrunc或echat应用携带的小部件,同时其包含一个状态栏,用于显示电池信号等信息,同时整个布局中包含通知以及快捷设置面板。 负一屏HotseatFragment用于加载Btrunc或echat应用的三个快捷启动Activity。 第二屏ApplistFragment使用GridView用来加载系统安装的Launcher应用,实现应用上下滑动等操作。

2)LauncherActivity最外层布局为MainContainer容器,其为自定义的FrameLayout,其包含一个继承于ViewPager的LauncherViewPager,用于加载上述三个Fragment页面。而MainContainer最重要的目的是用于拦截,分发,处理整个Launcher的触摸事件。 因为从需求看,三个页面存在水平方向滑动切换,首页滑出的通知列表存在水平滑动,快捷设置项也可能会存在水平方向页面切换。应用列表在垂直方向可以滑动,首页通知列表也可以垂直滑动。因此必然会存在水平或垂直方向的滑动冲突。设计的MainContainer可以根据当前情形,进行触摸拦截,分发给不同容器或视图View进行单独处理,解决冲突问题。 (解决滑动冲突) 例如: 如果首页通知面板都没有展开时,水平方向滑动一定距离,MainContainer可以不拦截触摸事件。由系统将触摸事件传递给LauncherViewPager进行处理,即进行页面滑动。 如果首页通知面板已经展开时,水平方向滑动一定距离。MainContainer在其onInterceptTouchEvent中拦截该滑动事件,禁止LauncherViewPager拦截,让整个事件传递给前台显示的通知列表,即进行侧滑。

3)首页顶部下滑出快捷设置面板或者底部上滑出通知面板 AppwidgetFragment整个布局中包含NotificationPanelView以及QuickSettingPanel。对于QuickSettingPanel快捷设置面板,默认处于Invisiable状态,其translationY设置为-height(QuickSettingPanel高度),即开始位置位于屏幕最上层,不可见的。当在垂直方向移动一定距离后,MainContainer容器拦截到该触摸事件,并在onTouchEvent中,根据垂直方向位移量,逐渐通过setTranslationY修改QuickSettingPanel的translationY,从而实现快捷设置面板的垂直移动,同时将状态设置为Visible可见状态。当触摸释放后,获取当前translationY以及要到达的translationY,通过属性动画ObjectAnimator进行translationY变化,将QuickSettingPanel滑动到最后的位置。对于通知面板NotificationPanelView其滑动类似。

4)整个Launcher的按键事件由LauncherActivity进行拦截,分发,处理等 Activity在dispatchKeyEvent拦截到所有按键事件,如果是需要处理的按键,则交给当前页面Fragment进行处理,否则不进行拦截处理。三个页面Fragment都实现了相同的类似如下的按键接口:

每个Fragment去处理左右上下,选择,返回等按键,而每个Fragment会根据各自当前情形,将按键分发给某个容器,某个视图,或某个应用进行处理等。 例如: 对于非首页Fragment来说,左右上下按键可能会在页面View之间进行焦点选择 而对于首页Fragment来说,收到旋钮按键或一键回传按键后,通过广播形式,将按键信息分发给小部件的BTrunc或echat应用进行处理。 3 主要UI布局设计 1)LauncherActivity布局为layout_launcher.xml,包含 MainContainer,其为FrameLayout。MainContainer下面包含一个LauncherViewPager,其继承于原生控件ViewPager用于容纳三个页面。

2)从整个Launcher UI效果看,Launcher大部分页面都是三段式结构。因此设计一个通用布局layout_base_container.xml,自定义为BaseContainerView,其为垂直的LinearLayout,其包含顶部区域TopBarView,中间内容区域ContentView以及底部区域BottomBarView。

顶部TopBarView用于显示页面描述信息 中间ContentView 用于显示每个页面独特的内容,占用剩下所有空间。 底部BottomBarView其是一个通用的自定义view,其命名为BottomBarView,其对应布局为layout_bottom_bar,其为一个Relayout布局包含三个ImageView。 如图:

3)对于ApplistFragment以及HotseatFragment这两个界面来说,其为标准的三段式结构,设计一个通用的BasePageFragment,其布局为上述通用的 layout_base_container.xml,HotseatFragment继承BasePageFragment,用于在内容区域加载该其布局fragment_hotseat.xml,其包含三个LinearLayout,包含应用名以及应用图标信息,根据系统实际模式,用于加载echat或btrunc相关activity信息。 AppListFragment继承BasePageFragment,在其内容区域加载其布局 fragment_applist.xml,其只包含一个GridView用于加载应用列表。

4)AppwidgetFragment相对比较复杂,其布局为fragment_appwidget.xml,其是一个FrameLayout,主要包含三部分,如下: 第一部分是:content_container区域,其为一个LinearLayout包含状态栏区域LauncherStatusbarView以及小部件内容区域widget_container。

第二部分是:顶部通知下拉容器NotificationPanelView 第三部分是: 系统快捷设置上拉容器QuickSettingPanel

5)状态栏LauncherStatusbarView为一个自定义的LinearLayout,对应布局文件为layout_statusbar.xml。从左到右包含以下几部分: BtruncSignalView: 其为自定义的LinearLayout。从左到右包含三部分ImageView分别为: 数据上下行,专网信号强度,注册状态。根据实际情况,控制显示与隐藏。

SignalClusterView: 其为一个自定义的LinearLayout.从左到右分别显示为: Wifi信号,mobile_signal_group包含上下行,信号强度,无sim卡图标,飞行模式。

system_status_icons: 系统事件图标区域用于显示蓝牙,闹钟,耳机等事件图标,其占据状态栏剩下所有空间,其为LinearLayout。通过动态addView来添加事件图标。

BatteryMeterView: 用于显示电池电量状态,其为自定义ImageView。

Clock: 用于显示时钟信息,其为自定义的TextView

6)顶部通知下拉容器NotificationPanelView 用于显示通知列表,其为标准的三段式结构,内容区域为自定义的支持侧滑删除功能的listview。

7)系统快捷设置上拉容器QuickSettingPanel 其为标准的三段式结构,内容区域包含一个viewpager用于分页加载所有快捷设置项。每一页是一个QSTilePage,其为自定义的网格布局ViewGroup,网格中每个快捷设置QSTileView为自定义的LinearLayout其包含图标以及文字的布局。 4 控制器controller Launcher中由大量的controller组成,用于接收View的数据输入,调用系统功能,同时系统功能状态变化时,将变化数据反馈给View。这些controller包含获取/设置,监听状态变化等接口,将直接作用于View或页面。

BatteryController: 获取电池连接状态以及电池电量接口 注册/反注册监听电池变化接口 ...

LocationController: 定位开关状态设置接口 获取定位开关状态接口 注册/反注册定位开关状态变化接口 ...

BluetoothController: 蓝牙开关以及连接状态设置接口 获取蓝牙开关以及连接状态接口 注册/反注册蓝牙开关状态以及连接状态接口

BtruncSignalController: 注册/反注册专网信号强度,注册,是否插卡等状态接口 ...

NfcController: NFC开关状态设置接口 获取NFC开关以及连接状态接口 注册/反注册NFC开关状态以及连接状态接口 ...

PackageController 获取当前系统安装的所有Launcher应用信息 根据条件查询Activity信息 卸载应用接口 启动activity 注册/反注册应用安装,卸载,更新等变化接口 ...

WifiSignalController: wifi开关以及连接状态设置接口 查询wifi开关以及连接状态接口 注册/反注册wifi信号强度等变化接口 ...

MobileSignalController 注册/反注册mobile信号强度,是否插sim卡,数据上下行等变化接口 ...

StatusbarIconController 提供在状态栏系统事件图标区 添加以及移除图标接口 ...

NextAlarmController 提供闹钟响起事件注册反注册接口 ...

NotificationController 获取通知信息列表接口 移除通知信息接口 注册/反注册通知更新变化接口 ...

5 触摸按键处理 触摸主要情形处理: 只针对当前页在首页AppwidgetFragment情况下才处理,其他页面不做处理。 1)当NotificationPanelView以及QuickSettingPanel页面处于不可见状态时 水平方向滑动一定距离,MainContainer不拦截触摸事件,交由LauncherViewPager拦截处理,进行Fragment页面滑动切换。

垂直方向滑动一定距离,MainContainer拦截触摸事件,将NotificationPanelView或QuickSettingPanel移动相应位移量,实现滑动。

2)NotificationPanelView或QuickSettingPanel页面处于全部展开可见状态时 水平或垂直方向滑动一定距离,MainContainer不拦截处理该触摸事件,但禁止LauncherViewPager对触摸事件的拦截处理。这样由系统将触摸事件传递给当前展开的面板进行处理,从而面板可以实现左右滑动,而不会与LauncherViewPager的页面水平切换想冲突。

按键主要情形处理: LauncherActivity负责拦截所有按键事件,分发给当前Fragment页面,而Fragment根据情况分发给相应容器,视图,或应用进行焦点选择等按键处理。

1)左右上下按键: 进行焦点的选择,在AppListFragment或HotseatFragment页面时,LauncherActivity拦截后,交给Fragment按照一定规则进行View焦点切换与选择,或在页面边缘处进行页面切换。

而在AppwidgetFragment页面,如果通知面板或快捷设置面板已经展开,LauncherActivity拦截后交给面板进行焦点选择即可。对于首页无展开的面板时,LauncherActivity可以不拦截这类按键,交由系统(LauncherViewPager)进行按照默认规则在小部件各View中进行焦点选择,以及在页面边缘处进行页面切换。

2) 旋钮左右键: 旋钮选中键: 群组列表(多功能键): 一键回传(多功能键): 当前在首页时,LauncherActivity拦截后,通过广播形式,将按键信息发送给小部件应用Btrunc或echat,进行按键处理,例如: Com.caltta.action.Launcher_Key_Btrunc 参数键值keyCode,是否长按 isLong等 Com.caltta.action.Launcher_Key_Echat

3)长按上/下键: 当前在首页时,滑出通知面板或快捷设置面板

4)选择键: 当前页在HoseatFragment时 短按进行QSTileView点击功能。长按进行QSTileView长按功能。 当前页在ApplistFragment时 短按启动当前焦点的应用,长按卸载当前焦点的应用。

5)其他按键 处理方式类似

6 问题点 对于Android来说,有两种模式,一种触摸模式,一种是按键模式。当触摸屏幕时,系统会进入触摸模式。通过方向键就可以退出触摸模式,进入按键模式,寻找视图获取焦点即会处于高亮状态。如果当前是按键模式,其中一个视图处于焦点状态,当进行触摸后,会导致其焦点的丢失,整个页面无视图处于高亮状态,只能通过方向键才能重新查找相应视图使其获取焦点,带来不好的体验。这个问题需要进行研究处理。