Android 4.4 - 半透明状态/导航栏 - fitsSystemWindows / clipToPadding无法通过片段事务处理

时间:2013-12-29 05:23:01

标签: android fragment transparent android-4.4-kitkat

使用新Android 4.4 KitKat API中的半透明状态和导航栏时,最初将fitsSystemWindows="true"clipToPadding="false"设置为ListViewfitsSystemWindows="true"将列表保留在操作栏下方导航栏上方,clipToPadding="false"允许列表在透明导航栏下滚动,并使列表中的最后一项向上滚动到足以通过导航杆

但是,当您通过Fragment将内容替换为另一个FragmentTransaction时,fitsSystemWindows的效果会消失,并且片段会位于操作栏和导航栏下。

我在这里有一个演示源代码的代码库以及一个可下载的APK作为示例:https://github.com/afollestad/kitkat-transparency-demo。要查看我正在谈论的内容,请从运行KitKat的设备中打开演示应用程序,点击列表中的项目(这将打开另一个活动),然后点击打开的新活动中的项目。替换内容的片段位于操作栏下,并且clipToPadding无法正常工作(当您向下滚动时,导航栏将覆盖列表中的最后一项)。

有什么想法吗?需要澄清吗?我发布了为我的雇主开发的个人应用程序的前后屏幕截图。

One Two

6 个答案:

答案 0 :(得分:12)

我昨天在同样的问题上挣扎。经过深思熟虑之后,我找到了解决这个问题的优雅方案。

首先,我在ViewParent上看到了方法requestFitSystemWindows(),我尝试在片段onActivityCreated()中调用它(在片段附加到视图层次结构之后)但是可悲的是,它没有任何效果。我想看一个如何使用该方法的具体例子。

然后我找到了一个简洁的解决方法:我创建了一个自定义FitsSystemWindowsFrameLayout,我在布局中用作片段容器,作为经典{{1}的替代品}。它的作用是在系统调用FrameLayout时记住窗口插入,然后在添加/附加片段后再将调用再次传播到其子布局(片段布局)。

这里是完整的代码:

fitSystemWindows()

我认为这比试图通过访问可能随时间变化的隐藏系统属性来确定UI元素大小的黑客更加简单和强大,然后手动将填充应用于元素。

答案 1 :(得分:9)

我通过使用库来解决了这个问题我设置了半透明状态栏的颜色。

SystemBarTint的SystemBarConfig类(如此处所见https://github.com/jgilfelt/SystemBarTint#systembarconfig)允许您获取插件,我将其设置为每个片段中列表的填充,以及使用clipToPadding="false" on清单。

我详细了解了我在这篇文章中所做的工作:http://mindofaandroiddev.wordpress.com/2013/12/28/making-the-status-bar-and-navigation-bar-transparent-with-a-listview-on-android-4-4-kitkat/

答案 2 :(得分:8)

好的,所以这非常奇怪。我刚刚遇到了同样的问题,除了我的涉及软键盘。它最初有效但如果我添加片段事务,android:fitsSystemWindows="true"不再有效。我在这里尝试了所有的解决方案,但没有一个能为我工作。

这是我的问题: enter image description here

而不是重新调整我的观点,它推动了我的观点,这就是问题所在。

但是,我很幸运,不小心偶然发现了一个对我有用的答案!

所以这是:

首先,我的应用主题是:Theme.AppCompat.Light.NoActionBar(如果这是相关的,也许是,android很奇怪)。

Maurycy在这里指出了一些非常有趣的东西,所以我想测试他说的是不是真的。他说的内容在我的情况下也是如此......除非你在app的Android清单中将此属性添加到你的活动中:

enter image description here

添加后:

android:windowSoftInputMode="adjustResize" 

到您的活动,片段事务后不再忽略android:fitsSystemWindows="true"

但是,我更喜欢你在片段的根布局上调用android:fitsSystemWindows="true"。如果您有EditText或ListView,最容易出现此问题的地方之一就是。如果你像我一样陷入困境,请在根布局的子项中设置android:fitsSystemWindows="true",如下所示:

enter image description here

是的,此解决方案适用于所有棒棒糖和棒棒糖前设备。

以下是证据: enter image description here

重新调整尺寸,而不是向上推动布局。 所以希望,我帮助了和我在同一条船上的人。

非常感谢你们!

答案 3 :(得分:5)

让一些人遇到这个问题。

使用fitSystemWindows方法完成大量工作的关键信息:

  

此功能在层次结构中的遍历是深度优先的。相同   内容insets对象沿层次结构向下传播,因此任何更改   所有以下观点(包括潜在的观点)都会看到它   层次结构中的那些,因为这是深度优先遍历)。   返回true的第一个视图将中止整个遍历。

因此,如果您有任何其他片段的内容视图,其中fitsSystemWindows设置为true,则可能会忽略该标志。如果可能的话,我会考虑让你的片段容器包含fitsSystemWindows标志。否则手动添加填充。

答案 4 :(得分:2)

我也一直在苦苦挣扎。 我在这里看到了所有的回复。不幸的是,他们都没有在100%的时间内解决我的问题。 SystemBarConfig始终无法正常工作,因为它无法检测某些设备上的栏。 我看了一下源代码,找到了在窗口中存储插图的位置。

        Rect insets = new Rect();
        Window window = getActivity().getWindow();
        try {
            Class clazz = Class.forName("com.android.internal.policy.impl.PhoneWindow");
            Field field = clazz.getDeclaredField("mDecor");
            field.setAccessible(true);
            Object decorView = field.get(window);
            Field insetsField = decorView.getClass().getDeclaredField("mFrameOffsets");
            insetsField.setAccessible(true);
            insets = (Rect) insetsField.get(decorView);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

这是如何获得它们的。 显然在Android L中,有一个很好的方法可以获得这些插入,但与此同时这可能是一个很好的解决方案。

答案 5 :(得分:0)

我已在4.4

中解决了这个问题
if(test){
    Log.d(TAG, "fit true ");
    relativeLayout.setFitsSystemWindows(true);
    relativeLayout.requestFitSystemWindows();
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}else {
    Log.d(TAG, "fit false");
    relativeLayout.setFitsSystemWindows(false);
    relativeLayout.requestFitSystemWindows();
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}