详解如何在Android中实现悬浮Activity
通常来说,为一款已经优化过的手机app开发平板的版本也不是很难。使用fragment、decompose entities等组件就可以又快又轻松地完成。但是,最近遇到一个项目就没有这么简单了。我们不只要开发一个平板app(基于actionbarsherlock库,也称作abs),还需要实现以下功能:
- 实现一个悬浮并且透明显示的activity,这样用户在进行输入操作的时候可以看到别的activity或者它自己的窗口背景;
- 保存悬浮的activity的原始尺寸,包括水平方向和竖直方向;最好是activity可以居中显示,在小尺寸设备上可以全屏显示,在大尺寸设备上至少显示2/3的大小。
因为我们之前说过已经有了一个开发好的手机app,所以如果为了讲这个重新设计再编码那就浪费时间了。以下的讲解和描述都是基于已有的代码,通过修改activity的实现来适配平板设备,已达到代码的最大利用率。
任务概述
这里主要有三个任务:
- 计算已有的activity的尺寸并确定它的新坐标位置;
- 使activity透明,可以看见其背景;
- 处理背景使其不能再和用户进行交互。
计算窗口大小
前面提到,我们需要以一个已有的手机app为基础(使用了actionbarsherlock库),这个库我们已经以一个外部库的形式集成到项目中,并带有源代码。
如果对abs的源码很熟悉或者曾对原生actionbar的构架有了解,就会发现:如果改变activity的大小,那在调用setcontentview方法的时候,功能没有实现:actionbar的大小和位置都没有变化。这时要做的就是在更高的级别里操作,在系统绘制actionbar的时候——abs或者原生的actionbar,这时候还没有任何窗口的数据,这样我们就可以按照需要调整了。
最显而易见的方式就是改变window的尺寸,所以这里需要以下这段代码:
@override public void onattachedtowindow() { super.onattachedtowindow(); if (getresources().getboolean(r.bool.is_tablet) && mopenassmallwindow) { final view view = getwindow().getdecorview(); final windowmanager.layoutparams lp = (windowmanager.layoutparams) view.getlayoutparams(); lp.gravity = gravity.center; lp.width = mactivitywindowwidth; lp.height = mactivitywindowheight; getwindowmanager().updateviewlayout(view, lp); } }
代码执行完毕后,就可以看到窗口的大小已经根据mactivitywindowwidth和mactivitywindowheight的值发生了改变。
is_tablet检查只对平板有效,mopenassmallwindow标识表示是否让窗口全屏显示或者是否作为新的窗口渲染。
如果在运行的时候报错了,错误日志是:actionbarview can only be used with android:layout_width="match_parent" (or fill_parent).那不用担心,我们有abs的源码,直接修改源码就可以了。
打开actionbarview这个文件,然后再onmeasure方法里把抛出的异常注释掉——这样应该就可以解决问题了。安卓上使用的是比较特殊的权限控制机制,所以这里我们可以继续深入的不多,也许还能粗略计算菜单项等,不过很多东西我们都不可把控。
注意:这个方法没有在原生actionbar上测试,因为这里只是在作者的android版本中测试过。如果要禁用actionbar,需要找到actionbarsherlock这个类,然后注释掉以下这行代码:
// registerimplementation(actionbarsherlocknative.class);
代码运行应该没问题,然后就可以看到不透明背景的activity了。
添加透明功能
在实现了activity的尺寸和大小都改变后,现在就要让它透明了。可以给这个平板上的activity主题添加这个属性:
<item name="android:windowistranslucent"> true </item>
这个属性值可以使activity背景透明。
看起来不错,效果已经基本实现了。
还有一个小问题:以上测试的都是在nexus7 android4.3上执行,而这个app在nexus7 的android4.2版本中,activity没有显示。
经过多次调试和日志检查后,发现我们的activity(就叫mainactivity吧)没有被销毁(没有调用ondestroy方法),所以android系统就把它忽略了,没有绘制它。为什么呢?因为android 4.4 kitkat新增了一个优化算法。因为这个优化算法,android系统看到activity为全屏显示模式(不管windowmanager的改变),就会绘制这个mainactivity,但是它之上的东西就被忽略了,所以我们就看不到任何显示了。
我们研究了下这个问题,然后发现对话框和其他不全屏显示的部件都可以正常绘制,所以我们需要在主题theme里加上这几行:
<item name="android:windowisfloating">true</item> <item name="android:windowcloseontouchoutside">false</item> <item name="android:colorbackgroundcachehint"><a href="http://www.jobbole.com/members/null/" rel="nofollow">@null</a></item> <item name="android:backgrounddimenabled">true</item>
这样问题就解决了。综上所述,我们就实现了一个悬浮、透明的activity。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。