如何在Android中实现悬浮Activity
2个回答
2016-04-26 · 百度知道合伙人官方认证企业
兄弟连教育
兄弟连教育成立于2006年,11年来专注IT职业教育,是国内专业的IT技术培训学校。2016年成功挂牌新三板(股票代码:839467)市值过亿。开设专注程序员培训专注php、Java、UI、云计算、Python、HTML5、
向TA提问
关注
展开全部
这里主要有三个任务:
计算已有的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。
计算已有的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。
展开全部
在Android中实现悬浮Activity可以通过以下方式完成:
1、将需要悬浮的Activity设置dialog的样式主题,定义样式文件如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="FullHeightDialog" parent="android:style/Theme.Dialog">
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
</resources>
2、在在清单文件中给activity设置theme
<activity
android:name=".MainActivity"
android:configChanges="locale|keyboardHidden|orientation"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:theme="@style/FullHeightDialog"
</activity>
1、将需要悬浮的Activity设置dialog的样式主题,定义样式文件如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="FullHeightDialog" parent="android:style/Theme.Dialog">
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
</resources>
2、在在清单文件中给activity设置theme
<activity
android:name=".MainActivity"
android:configChanges="locale|keyboardHidden|orientation"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:theme="@style/FullHeightDialog"
</activity>
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询