Android, Как сделать прозрачную строку состояния правильно

Я пытаюсь сделать прозрачную строку состояния на Android 4.4+ Я знаю, как сделать его прозрачным, определяя мой собственный стиль:

<style name="Theme.MyTheme" parent="Theme.MyTheme.Base">
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowTranslucentNavigation">true</item> </style>

Я нашел здесь: qaru.site/info/61104/...

Проблема заключается в том, что, когда строка состояния прозрачна, она не соответствует цвету панели действий и вид активности в фоновом режиме: transparent status bar error

Итак, я обнаружил, что могу использовать android: fitsSystemWindows = "true" и android: clipToPadding = "false" в моем макете, который я нашел здесь http://mindofaandroiddev.wordpress.com/2013/12/28/making-the-status-bar-and-navigation-bar-transparent-with-a-listview-on-android-4-4-kitkat/

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background_darkRed"
android:fitsSystemWindows="true"
android:clipToPadding="false"    
tools:context="com.sandak.......">

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"> 
....

Это решает проблему с прозрачной статусной строкой и выглядит нормально. К сожалению, в нижней строке "навигационной панели" есть проблема с системными кнопками, которые краснеют и не прозрачны, как я желаю: enter image description here

Я пытался использовать все возможные варианты для достижения рабочего результата, но я не могу понять, как его решить. Моим единственным рабочим решением является верхнее дополнение размером около 60dp к корневому элементу. Но это решение является уродливым, и на разных устройствах может выглядеть по-другому и может не работать.

Я нашел несколько приложений в Google Play, которые работают нормально с прозрачным фоном, поэтому мне интересно, как они работают.

Например: https://play.google.com/store/apps/details?id=com.trello и несколько других

Ответ 1

//UPDATE:
Хорошо, это довольно старый ответ. Теперь вы можете использовать материальную тему, чтобы справиться с этим, и это довольно легко. Просто установите целевой api на 21+, используйте библиотеку поддержки, если вам нужно, и создайте тему с материальной темой, где вы можете напрямую указать цвет строки состояния.

<style name="AppTheme"
        parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- colorPrimary is used for the default action bar background -->
        <item name="colorPrimary">@color/color_primary</item>

        <!-- colorPrimaryDark is used for the status bar -->
        <item name="colorPrimaryDark">@color/color_primary_dark</item>

        <!-- colorAccent is used as the default value for colorControlActivated
             which is used to tint widgets -->
        <item name="colorAccent">@color/accent_orange</item>
    </style>

=============================================== ========================

OLD ANSWER:

Хорошо. Кажется, я решу свою проблему. Это не лучшее и четкое решение, но это рабочее решение. Если кто-то в будущем узнает лучшее и более четкое решение, сообщите мне, и я обновлю свой ответ/или отметю ваш ответ как правильный. Но на данный момент у меня нет лучшего решения, чем этот маленький взлом:

Корневой элемент макета должен быть RelativeLayout. Чем должно следовать ваш основной макет, например ScrollView или любые другие макеты, это не имеет значения. В конце до закрытия тега Relative Layout следует пустой LinearLayout, который установил тот же фон, что и панель действий, и фиксированная высота (высота строки состояния).

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.sandak....">
<ScrollView
    android:fitsSystemWindows="true"
    android:clipToPadding="false"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
.... all your main views etc..
</ScrollView>
<LinearLayout
        android:id="@+id/statusBarBackgroundLinearLayout"
        android:layout_width="match_parent"
        android:orientation="horizontal"
        android:layout_height="30dp"
        android:background="@color/background_darkRed"
        android:clickable="false"
        android:focusable="false">
     </LinearLayout>
</RelativeLayout>

Хорошо, тогда вы должны установить в коде ту же линейную высоту макета, что и в строке состояния:

private void setStatusBarBackground(View rootView) {
        setStatusBarLayout(rootView);
        statusBarHeight = getStatusBarHeight();
        setStatusBarLayoutHeight(statusBarHeight);
    }

    private void setStatusBarLayout(View rootView){
        statusBarBackgroundLinearLayout = (LinearLayout) rootView.findViewById(R.id.statusBarBackgroundLinearLayout);
        if (isPreKitkatDevice()) {
            hideStatusBarLayout();
        }
    }

    private int getStatusBarHeight() {
        int statusBarHeight = 0;
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            statusBarHeight = getResources().getDimensionPixelSize(resourceId);
        }
        return statusBarHeight;
    }

    private boolean isPreKitkatDevice(){
        return Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT;
    }

    private void hideStatusBarLayout(){
        statusBarBackgroundLinearLayout.setVisibility(View.INVISIBLE);
    }        

    private void setStatusBarLayoutHeight(int height){
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) statusBarBackgroundLinearLayout.getLayoutParams();
        layoutParams.height = height;
    }

А затем просто вызовите setStatusBarBackground в свой метод onCreate(). Это рабочее решение для всех различных устройств. Для устройств pre KitKat, где прозрачный фон не разрешен, вам нужно скрыть линейную компоновку.