底部软件导航栏覆盖了我的ListView

16

我在 Nexus 5(Android 5) 上运行我的应用程序,但遇到了问题:底部的软导航栏重叠了我的 ListView 的最后一个项目。我尝试将 fitsSystemWindows 添加到我的样式和 ListView 中,但都没有起作用。

我的布局 XML:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:background="@color/sf4l"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <ListView android:id="@id/android:list"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:layout_weight="1"
        android:background="@color/sf4l" />
</LinearLayout>

你指的是哪个导航栏?你的活动是全屏吗? - Greg Ennis
软导航栏带有返回、主页和选项按钮。http://bit.ly/1vLpHSp - Bart Bergmans
2
如果我添加边距,那些没有软导航按钮的设备就会出现问题。 - Bart Bergmans
1
请查看上面的链接,它将对您有所帮助。 - sharma_kunal
6个回答

45

将以下内容添加到位于values-v21目录中的themes.xml文件中:

<item name="android:windowDrawsSystemBarBackgrounds">false</item>

示例(我正在使用AppCompat来创建操作栏):

<style name="Theme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="homeAsUpIndicator">@drawable/new_indicator</item>
    <item name="android:homeAsUpIndicator">@drawable/new_indicator</item>
    <item name="actionModeBackground">@android:color/black</item>
    <item name="android:windowDrawsSystemBarBackgrounds">false</item>
</style>

1
我正在使用AppTheme.NoActionBar,但它不起作用!还有其他的想法吗? - Yamen Nassif
1
它同样适用于NoActionBar,只需将样式文件的相同内容复制到v21中,并在其中包含<item name="android:windowDrawsSystemBarBackgrounds">false</item> - SimplyProgrammer
1
我正在使用AppTheme.NoActionBar,但它似乎不起作用!还有其他的想法吗? 我也尝试使用v21文件夹,但仍然没有反应。 - scienticious
它与Theme.AppCompat.Light.NoActionBar不兼容,有人可以帮忙吗? - Sandeep Manmode
如果您的主题是NoActionBar,且父布局为ConstraintsLayout,则此链接可能会有所帮助 https://dev59.com/FVoV5IYBdhLWcg3wA66x#67661966 - Rahul Sharma
显示剩余3条评论

4

我尝试了这篇帖子中的被接受的答案,像许多人一样,它对我不起作用。

然而下面的内容适用于我。

  <item name="android:windowTranslucentNavigation">false</item>

我把它放在styles-21.xml中。

这样做的效果是使软导航栏具有坚实的背景,并且现在组件的呈现方式正确无误。


4

这篇答案结合了其他答案和我的尝试,从API-15开始。

针对API-21+

styles.xml (v21)中,在activity的样式下添加以下内容。

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
     ....
    <item name="android:windowDrawsSystemBarBackgrounds">false</item>
</style>

针对API-19及以上版本

styles.xml(v19)中,将以下内容添加到活动样式中:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
     ....
    <item name="android:windowTranslucentNavigation">false</item>
</style>

适用于API-15+

在您的Activity中覆盖下面的内容

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    // return for API-19+
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
        return;

    // Customize Activity to not overlap with the bottom software buttons
    // navigation bar (back, home, & menu)
    boolean hasMenuKey = ViewConfiguration.get(this).hasPermanentMenuKey();
    boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);

    if (!hasMenuKey && !hasBackKey) { // check if this device has a bottom navigation bar
        ConstraintLayout rootLayout = findViewById(R.id.activity_root); // my activity root layout
        int NAVIGATION_BAR_HEIGHT = 70;
        rootLayout.getLayoutParams().height = rootLayout.getHeight() - NAVIGATION_BAR_HEIGHT;
    }
}

4

这是因为你的listView高度等于全屏高度,但操作栏会将布局向下推几个像素,导致布局与导航按钮重叠。

如果在操作栏下有全屏片段容器,也会发生这种情况。

解决方法是测量屏幕和操作栏的高度,然后将父视图的高度设置为它们的差值。例如:

@Override
public void onWindowFocusChanged (boolean hasFocus) {
    LinearLayout lMain = (LinearLayout) findViewById(R.id.lMain);
    lMain.getLayoutParams().height = lMain.getHeight() - getNavigationBarHeight();
}
  • 在布局已经绘制/渲染完成后才能执行此操作。在onCreate或onResume中执行太早了。在onWindowFocusChanged()中执行可能有点过度,但它可以正常工作。

1
非常简单的解决方案。只需使用ConstraintLayout将顶部视图的底边与底部视图的顶边对齐。 下面是示例:
xml:
    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<ListView
    android:id="@+id/list_item"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:divider="@color/black"
    android:dividerHeight="2dp"
    app:layout_constraintBottom_toTopOf="@+id/navigation"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="1.0"
    app:layout_constraintHorizontal_bias="1.0"></ListView>

<android.support.design.widget.BottomNavigationView
    android:id="@+id/navigation"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginEnd="0dp"
    android:layout_marginStart="0dp"
    android:background="?android:attr/windowBackground"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:menu="@menu/navigation" />
    </android.support.constraint.ConstraintLayout>

输出设计:-

enter image description here


对我来说,这只是在列表视图底部上方添加了一个白色块。 - ThomasW

0

没有人提到插入操作。

View.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
        @Override
        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
            int bottomInset = insets.getSystemWindowInsetBottom();
            // Do something with the bottom inset value, such as adjusting the layout
            v.getPaddingBottom();// useless.
            insets.getSystemWindowInsetBottom(); // correct
            insets.getStableInsetBottom();

            return insets;
        }
    });

此代码仅用于指引读者方向,而非具备功能性正确性。 请查看此 post


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接