FitSystemWindows программно для прозрачности строки состояния

В моем приложении есть одно действие, в котором размещаются разные фрагменты для каждого раздела. Недавно я сделал индикатор состояния полупрозрачным, установив fitSystemWindows в true, который установил его на цвет фона приложения. Это прекрасно для фрагментов, у которых есть панель инструментов, где цвета совпадают, например:

enter image description here

Однако у одного из моих фрагментов есть фотография и полупрозрачная панель инструментов, поэтому я хотел бы, чтобы фотография занимала пространство строки состояния, а не цвет фона.

Я считаю, что решение состоит в том, чтобы установить fitSystemWindows в false только для этого фрагмента и вручную добавить отступ к полупрозрачной панели инструментов. Выполнение этого программно, похоже, не имеет никакого эффекта, что я могу делать неправильно?

Вот мой основной вид деятельности:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_parent_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:fitsSystemWindows="true">

<!-- Container for various fragment layouts, including nav drawer and tool bar -->

</RelativeLayout>

И изнутри моего фрагмента onCreateView():

RelativeLayout daddyLayout = (RelativeLayout)getActivity().findViewById(R.id.main_parent_view);
daddyLayout.setFitsSystemWindows(false);
daddyLayout.invalidate();

Кажется, это не имеет никакого эффекта:

enter image description here

Если я установил fitSystemWindows в false в main_parent_view, заполнение строки состояния исчезнет, ​​и оно работает, но, очевидно, влияет на каждый фрагмент.

Ответ 1

Увидел ту же проблему. Выбрал его в моем приложении, удалив fitSystemWindows из объявления активности и добавив paddingTop к фрагменту. Очевидно, это не идеальное решение, но, похоже, работает.

Ответ 2

Вы можете использовать CoordinatorLayout в качестве корневого представления активности, а затем setFitsSystemWindows(boolean) будет работать.

Это связано с тем, что, как объясняется в этом сообщении в блоге, DrawerLayout и CoordinatorLayout имеют разные правила использования fitsSystemWindows для них - они оба используют его для вставки их дочерних представлений, но также вызывают dispatchApplyWindowInsets() для каждого дочернего элемента, позволяя им получить доступ к свойству fitsSystemWindows="true".

Это отличие от поведения по умолчанию с макетами, такими как FrameLayout, где при использовании fitsSystemWindows="true" используется все вставки, слепое применение отступов, не сообщая ни одного дочернего вида (что часть "глубина первой" в блоге).

Ответ 3

Я разрешаю этот вопрос в 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);
}

Ответ 4

Ну, вы находитесь в ситуации дилеммы, потому что с одной стороны вам нужно применять вставки (потому что Toolbar должен быть правильно дополнен), а с другой стороны вы должны не применять вставки ( потому что вы хотите, чтобы ImageView отображался в строке состояния).

Оказывается там хороший API, предоставляемый каркасом для этого случая:

ViewCompat.setOnApplyWindowInsetsListener(toolbar, (v, insets) -> {
    ((ViewGroup.MarginLayoutParams) v.getLayoutParams()).topMargin =
            insets.getSystemWindowInsetTop();
    return insets.consumeSystemWindowInsets();
});

Предполагая, что ваш корневой макет имеет android:fitsSystemWindows="true", теперь соответствующие вставки будут применены к вашему Toolbar только, а не к ImageView.

Но, есть проблема.

Проблема заключается в том, что ваш корневой макет RelativeLayout, который не передает своим детям информацию о вставках. Также не отображаются его раскладки (LinearLayout, FrameLayout).

Если у вас в качестве корневого макета один из "материальных" макетов (CoordinatorLayout, DrawerLayout), тогда детям будут отправляться эти вставки окна.

Другой вариант заключается в подклассе RelativeLayout и отправке WindowInsets в детей вручную.

@TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
    int childCount = getChildCount();
    for (int index = 0; index < childCount; index++)
        getChildAt(index).dispatchApplyWindowInsets(insets); // let children know about WindowInsets

    return insets;
}

Вы можете увидеть этот ответ для подробного объяснения с тем же самым требованием, которое у вас есть.

введите описание изображения здесь